C++ PATCH: Fix PR/7363, a regression

Gabriel Dos Reis gdr@merlin.nerim.net
Sun Jul 21 02:28:00 GMT 2002


Neil Booth <neil@daikokuya.co.uk> writes:

| Gabriel Dos Reis wrote:-
| 
| > !   if (type_code == FUNCTION_TYPE)
| >       {
| > !       if (op == SIZEOF_EXPR && (pedantic || warn_pointer_arith))
| > ! 	{
| > ! 	  pedwarn ("invalid application of `sizeof' to a function type");
| > ! 	  value = size_one_node;
| > ! 	}
| > !       else
| > ! 	value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
| 
| This code implies that the result of "sizeof" depends on -pedantic or
| -Wpointer-arith, which IMO is not a good idea.

Good catch.

| Shouldn't the && part be taken inside the braces?

Yes.  Patch revised as below.

Mark, Jason, OK for mainline?

-- Gaby

2002-07-21  Gabriel Dos Reis  <gdr@nerim.net>

	Fix PR/7363:
	* c-common.c (c_sizeof_or_alignof_type): New function.
	(c_alignof): Remove definition.
	* c-common.h (c_sizeof, c_alignof): Define as macros.
	(c_sizeof_or_alignof_type): Declare.
	(my_friendly_assert): Moved from cp/cp-tree.h
	* c-typeck.c (c_sizeof): Remove definition.

cp/

2002-07-21  Gabriel Dos Reis  <gdr@nerim.net>

	Fix PR/7363:
	* typeck.c (cxx_sizeof_or_alignof_type): New function.
	(c_sizeof): Remove definition.
	(expr_sizeof): Use cxx_sizeof.
	* decl2.c (build_expr_from_tree): Use cxx_sizeof_or_alignof_type.
	* decl.c (finish_destructor_body): Use cxx_sizeof.
	* semantics.c (finish_alignof): Likewise.
	(finish_alignof): Use cxx_alignof.
	* cp-tree.h (cxx_sizeof, cxx_alignof): New macros.
	(cxx_sizeof_or_alignof_type): Declare.
	(my_friendly_assert): Move to ../c-common.h.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.c,v
retrieving revision 1.348
diff -p -r1.348 c-common.c
*** c-common.c	7 Jul 2002 22:10:16 -0000	1.348
--- c-common.c	21 Jul 2002 08:32:45 -0000
*************** c_common_get_alias_set (t)
*** 2601,2636 ****
    return -1;
  }
  
! /* Implement the __alignof keyword: Return the minimum required
!    alignment of TYPE, measured in bytes.  */
! 
  tree
! c_alignof (type)
       tree type;
  {
!   enum tree_code code = TREE_CODE (type);
!   tree t;
! 
!   /* In C++, sizeof applies to the referent.  Handle alignof the same way.  */
!   if (code == REFERENCE_TYPE)
      {
!       type = TREE_TYPE (type);
!       code = TREE_CODE (type);
      }
- 
-   if (code == FUNCTION_TYPE)
-     t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-   else if (code == VOID_TYPE || code == ERROR_MARK)
-     t = size_one_node;
    else if (!COMPLETE_TYPE_P (type))
      {
!       error ("__alignof__ applied to an incomplete type");
!       t = size_zero_node;
      }
    else
!     t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
  
!   return fold (build1 (NOP_EXPR, c_size_type_node, t));
  }
  
  /* Implement the __alignof keyword: Return the minimum required
--- 2601,2661 ----
    return -1;
  }
  
! /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
!    second parameter indicates which OPERATOR is being applied.  */
  tree
! c_sizeof_or_alignof_type (type, op)
       tree type;
+      enum tree_code op;
  {
!   const char *op_name;
!   tree value = NULL;
!   enum tree_code type_code = TREE_CODE (type);
!   
!   my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
!   op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
!   
!   if (type_code == FUNCTION_TYPE)
      {
!       if (op == SIZEOF_EXPR)
! 	{
! 	  if (pedantic || warn_pointer_arith)
! 	    pedwarn ("invalid application of `sizeof' to a function type");
! 	  value = size_one_node;
! 	}
!       else
! 	value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
!     }
!   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
!     {
!       if (type_code == VOID_TYPE && (pedantic || warn_pointer_arith))
! 	pedwarn ("invalid application of `%s' to a void type", op_name);
!       value = size_one_node;
      }
    else if (!COMPLETE_TYPE_P (type))
      {
!       error ("invalid application of `%s' to an incomplete type", op_name);
!       value = size_zero_node;
      }
    else
!     {
!       if (op == SIZEOF_EXPR)
! 	/* Convert in case a char is more than one unit.  */
! 	value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
! 			    size_int (TYPE_PRECISION (char_type_node)
! 				      / BITS_PER_UNIT));
!       else
! 	value = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
!     }
  
!   /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
!      TYPE_IS_SIZETYPE means that certain things (like overflow) will
!      never happen.  However, this node should really have type
!      `size_t', which is just a typedef for an ordinary integer type.  */
!   value = fold (build1 (NOP_EXPR, c_size_type_node, value));
!   my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
!   
!   return value;
  }
  
  /* Implement the __alignof keyword: Return the minimum required
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.142
diff -p -r1.142 c-common.h
*** c-common.h	7 Jul 2002 22:10:17 -0000	1.142
--- c-common.h	21 Jul 2002 08:32:46 -0000
*************** extern tree c_common_signed_type		PARAMS
*** 548,559 ****
  extern tree c_common_signed_or_unsigned_type	PARAMS ((int, tree));
  extern tree c_common_truthvalue_conversion	PARAMS ((tree));
  extern void c_apply_type_quals_to_decl		PARAMS ((int, tree));
! extern tree c_sizeof				PARAMS ((tree));
! extern tree c_alignof				PARAMS ((tree));
  extern tree c_alignof_expr			PARAMS ((tree));
  /* Print an error message for invalid operands to arith operation CODE.
     NOP_EXPR is used as a special case (see truthvalue_conversion).  */
  extern void binary_op_error			PARAMS ((enum tree_code));
  extern tree c_expand_expr_stmt			PARAMS ((tree));
  extern void c_expand_start_cond			PARAMS ((tree, int, tree));
  extern void c_finish_then                       PARAMS ((void));
--- 548,561 ----
  extern tree c_common_signed_or_unsigned_type	PARAMS ((int, tree));
  extern tree c_common_truthvalue_conversion	PARAMS ((tree));
  extern void c_apply_type_quals_to_decl		PARAMS ((int, tree));
! extern tree c_sizeof_or_alignof_type	PARAMS ((tree, enum tree_code));
  extern tree c_alignof_expr			PARAMS ((tree));
  /* Print an error message for invalid operands to arith operation CODE.
     NOP_EXPR is used as a special case (see truthvalue_conversion).  */
  extern void binary_op_error			PARAMS ((enum tree_code));
+ #define my_friendly_assert(EXP, N) (void) \
+  (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
+ 
  extern tree c_expand_expr_stmt			PARAMS ((tree));
  extern void c_expand_start_cond			PARAMS ((tree, int, tree));
  extern void c_finish_then                       PARAMS ((void));
*************** extern void unsigned_conversion_warning	
*** 573,578 ****
--- 575,582 ----
  /* Read the rest of the current #-directive line.  */
  extern char *get_directive_line			PARAMS ((void));
  #define GET_DIRECTIVE_LINE() get_directive_line ()
+ #define c_sizeof(T)  c_sizeof_or_alignof_type (T, SIZEOF_EXPR)
+ #define c_alignof(T) c_sizeof_or_alignof_type (T, ALIGNOF_EXPR)
  
  /* Subroutine of build_binary_op, used for comparison operations.
     See if the operands have both been converted from subword integer types
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-typeck.c,v
retrieving revision 1.197
diff -p -r1.197 c-typeck.c
*** c-typeck.c	3 Jul 2002 09:49:45 -0000	1.197
--- c-typeck.c	21 Jul 2002 08:32:49 -0000
*************** type_lists_compatible_p (args1, args2)
*** 736,782 ****
      }
  }
  
- /* Compute the value of the `sizeof' operator.  */
- 
- tree
- c_sizeof (type)
-      tree type;
- {
-   enum tree_code code = TREE_CODE (type);
-   tree size;
- 
-   if (code == FUNCTION_TYPE)
-     {
-       if (pedantic || warn_pointer_arith)
- 	pedwarn ("sizeof applied to a function type");
-       size = size_one_node;
-     }
-   else if (code == VOID_TYPE)
-     {
-       if (pedantic || warn_pointer_arith)
- 	pedwarn ("sizeof applied to a void type");
-       size = size_one_node;
-     }
-   else if (code == ERROR_MARK)
-     size = size_one_node;
-   else if (!COMPLETE_TYPE_P (type))
-     {
-       error ("sizeof applied to an incomplete type");
-       size = size_zero_node;
-     }
-   else
-     /* Convert in case a char is more than one unit.  */
-     size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- 		       size_int (TYPE_PRECISION (char_type_node)
- 			         / BITS_PER_UNIT));
- 
-   /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
-      TYPE_IS_SIZETYPE means that certain things (like overflow) will
-      never happen.  However, this node should really have type
-      `size_t', which is just a typedef for an ordinary integer type.  */
-   return fold (build1 (NOP_EXPR, c_size_type_node, size));
- }
- 
  tree
  c_sizeof_nowarn (type)
       tree type;
--- 736,741 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.729
diff -p -r1.729 cp-tree.h
*** cp/cp-tree.h	10 Jul 2002 18:16:23 -0000	1.729
--- cp/cp-tree.h	21 Jul 2002 08:33:00 -0000
*************** extern int compparms				PARAMS ((tree, t
*** 4435,4440 ****
--- 4435,4441 ----
  extern int comp_cv_qualification                PARAMS ((tree, tree));
  extern int comp_cv_qual_signature               PARAMS ((tree, tree));
  extern tree expr_sizeof				PARAMS ((tree));
+ extern tree cxx_sizeof_or_alignof_type    PARAMS ((tree, enum tree_code));
  extern tree c_sizeof_nowarn			PARAMS ((tree));
  extern tree inline_conversion			PARAMS ((tree));
  extern tree decay_conversion			PARAMS ((tree));
*************** extern tree merge_types				PARAMS ((tree
*** 4481,4486 ****
--- 4482,4489 ----
  extern tree check_return_expr                   PARAMS ((tree));
  #define cp_build_binary_op(code, arg1, arg2) \
    build_binary_op(code, arg1, arg2, 1)
+ #define cxx_sizeof(T)  cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR)
+ #define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR)
  
  /* in typeck2.c */
  extern void cxx_incomplete_type_diagnostic	PARAMS ((tree, tree, int));
*************** extern tree error_not_base_type			PARAMS
*** 4492,4500 ****
  extern tree binfo_or_else			PARAMS ((tree, tree));
  extern void readonly_error			PARAMS ((tree, const char *, int));
  extern int abstract_virtuals_error		PARAMS ((tree, tree));
- 
- #define my_friendly_assert(EXP, N) (void) \
-  (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
  
  extern tree force_store_init_value		PARAMS ((tree, tree));
  extern tree store_init_value			PARAMS ((tree, tree));
--- 4495,4500 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.921
diff -p -r1.921 decl.c
*** cp/decl.c	17 Jul 2002 14:07:42 -0000	1.921
--- cp/decl.c	21 Jul 2002 08:33:07 -0000
*************** finish_destructor_body ()
*** 14064,14070 ****
    if (DECL_VIRTUAL_P (current_function_decl))
      {
        tree if_stmt;
!       tree virtual_size = c_sizeof (current_class_type);
  
        /* [class.dtor]
  
--- 14064,14070 ----
    if (DECL_VIRTUAL_P (current_function_decl))
      {
        tree if_stmt;
!       tree virtual_size = cxx_sizeof (current_class_type);
  
        /* [class.dtor]
  
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.546
diff -p -r1.546 decl2.c
*** cp/decl2.c	21 Jul 2002 02:07:01 -0000	1.546
--- cp/decl2.c	21 Jul 2002 08:33:09 -0000
*************** build_expr_from_tree (t)
*** 3779,3785 ****
  	if (!TYPE_P (r))
  	  return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
  	else
! 	  return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r);
        }
  
      case MODOP_EXPR:
--- 3779,3785 ----
  	if (!TYPE_P (r))
  	  return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
  	else
! 	  return cxx_sizeof_or_alignof_type (r, TREE_CODE (t));
        }
  
      case MODOP_EXPR:
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.268
diff -p -r1.268 semantics.c
*** cp/semantics.c	10 Jul 2002 18:16:24 -0000	1.268
--- cp/semantics.c	21 Jul 2002 08:33:11 -0000
*************** finish_sizeof (t)
*** 2106,2112 ****
    if (processing_template_decl)
      return build_min_nt (SIZEOF_EXPR, t);
  
!   return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t);
  }
  
  /* Implement the __alignof keyword: Return the minimum required
--- 2106,2112 ----
    if (processing_template_decl)
      return build_min_nt (SIZEOF_EXPR, t);
  
!   return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
  }
  
  /* Implement the __alignof keyword: Return the minimum required
*************** finish_alignof (t)
*** 2119,2125 ****
    if (processing_template_decl)
      return build_min_nt (ALIGNOF_EXPR, t);
  
!   return TYPE_P (t) ? c_alignof (t) : c_alignof_expr (t);
  }
  
  /* Generate RTL for the statement T, and its substatements, and any
--- 2119,2125 ----
    if (processing_template_decl)
      return build_min_nt (ALIGNOF_EXPR, t);
  
!   return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
  }
  
  /* Generate RTL for the statement T, and its substatements, and any
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck.c,v
retrieving revision 1.410
diff -p -r1.410 typeck.c
*** cp/typeck.c	26 Jun 2002 17:03:44 -0000	1.410
--- cp/typeck.c	21 Jul 2002 08:33:14 -0000
*************** comp_target_parms (parms1, parms2)
*** 1486,1558 ****
    return warn_contravariance ? -1 : 1;
  }
  
- /* Compute the value of the `sizeof' operator.  */
- 
  tree
! c_sizeof (type)
       tree type;
  {
!   enum tree_code code = TREE_CODE (type);
!   tree size;
  
    if (processing_template_decl)
!     return build_min_nt (SIZEOF_EXPR, type);
  
!   if (code == FUNCTION_TYPE)
!     {
!       if (pedantic || warn_pointer_arith)
! 	pedwarn ("ISO C++ forbids applying `sizeof' to a function type");
!       size = size_one_node;
!     }
!   else if (code == METHOD_TYPE)
      {
        if (pedantic || warn_pointer_arith)
! 	pedwarn ("ISO C++ forbids applying `sizeof' to a member function");
!       size = size_one_node;
      }
!   else if (code == VOID_TYPE)
      {
!       if (pedantic || warn_pointer_arith)
! 	pedwarn ("ISO C++ forbids applying `sizeof' to type `void' which is an incomplete type");
!       size = size_one_node;
      }
-   else if (code == ERROR_MARK)
-     size = size_one_node;
    else
!     {
!       /* ARM $5.3.2: ``When applied to a reference, the result is the
! 	 size of the referenced object.'' */
!       if (code == REFERENCE_TYPE)
! 	type = TREE_TYPE (type);
! 
!       if (code == OFFSET_TYPE)
! 	{
! 	  error ("`sizeof' applied to non-static member");
! 	  size = size_zero_node;
! 	}
!       else if (!COMPLETE_TYPE_P (complete_type (type)))
! 	{
! 	  error ("`sizeof' applied to incomplete type `%T'", type);
! 	  size = size_zero_node;
! 	}
!       else
! 	/* Convert in case a char is more than one unit.  */
! 	size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
! 			   size_int (TYPE_PRECISION (char_type_node)
! 				     / BITS_PER_UNIT));
!     }
  
!   /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
!      TYPE_IS_SIZETYPE means that certain things (like overflow) will
!      never happen.  However, this node should really have type
!      `size_t', which is just a typedef for an ordinary integer type.  */
!   size = fold (build1 (NOP_EXPR, c_size_type_node, size));
!   my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)), 
! 		      20001021);
!   return size;
  }
  
- 
  tree
  expr_sizeof (e)
       tree e;
--- 1486,1527 ----
    return warn_contravariance ? -1 : 1;
  }
  
  tree
! cxx_sizeof_or_alignof_type (type, op)
       tree type;
+      enum tree_code op;
  {
!   enum tree_code type_code;
!   tree value;
!   const char *op_name;
  
+   my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
    if (processing_template_decl)
!     return build_min_nt (op, type);
!   
!   op_name = operator_name_info[(int) op].name;
!   
!   if (TREE_CODE (type) == REFERENCE_TYPE)
!     type = TREE_TYPE (type);
!   type_code = TREE_CODE (type);
  
!   if (type_code == METHOD_TYPE)
      {
        if (pedantic || warn_pointer_arith)
! 	pedwarn ("invalid application of `%s' to a member function", op_name);
!       value = size_one_node;
      }
!   else if (type_code == OFFSET_TYPE)
      {
!       error ("invalid application of `%s' to non-static member", op_name);
!       value = size_zero_node;
      }
    else
!     value = c_sizeof_or_alignof_type (complete_type (type), op);
  
!   return value;
  }
  
  tree
  expr_sizeof (e)
       tree e;
*************** expr_sizeof (e)
*** 1582,1588 ****
    if (e == error_mark_node)
      return e;
  
!   return c_sizeof (TREE_TYPE (e));
  }
    
  tree
--- 1551,1557 ----
    if (e == error_mark_node)
      return e;
  
!   return cxx_sizeof (TREE_TYPE (e));
  }
    
  tree
Index: testsuite/g++.dg/ext/alignof1.C
===================================================================
RCS file: testsuite/g++.dg/ext/alignof1.C
diff -N testsuite/g++.dg/ext/alignof1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/alignof1.C	21 Jul 2002 08:33:15 -0000
***************
*** 0 ****
--- 1,19 ----
+ // { dg-do run }
+ 
+ // Copyright (C) 2002 Free Software Foundation, Inc.
+ // Contributed by Gabriel Dos Reis <gdr@codesourcery.com>, 2002-07-20
+ // Bug PR/7363.
+ 
+ template<typename T>
+ int my_alignof()
+ {
+   return __alignof__ (T);
+ }
+ 
+ template<typename>
+   struct X { };
+ 
+ int main()
+ {
+   return my_alignof<X<void> >();
+ }



More information about the Gcc-patches mailing list