diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b66163379c3..aeb15c44913 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2002-07-23 Gabriel Dos Reis + + 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. + 2002-07-23 Jan Hubicka * gcse.c (try_replace_reg): Use num_changes_pending. diff --git a/gcc/c-common.c b/gcc/c-common.c index a948959da70..d7be6c812d1 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -2601,36 +2601,61 @@ c_common_get_alias_set (t) return -1; } -/* Implement the __alignof keyword: Return the minimum required - alignment of TYPE, measured in bytes. */ - +/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the + second parameter indicates which OPERATOR is being applied. */ tree -c_alignof (type) +c_sizeof_or_alignof_type (type, op) tree type; + enum tree_code op; { - 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) + 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) { - type = TREE_TYPE (type); - code = TREE_CODE (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; } - - 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; + error ("invalid application of `%s' to an incomplete type", op_name); + value = size_zero_node; } else - t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); + { + 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); + } - return fold (build1 (NOP_EXPR, c_size_type_node, t)); + /* 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 diff --git a/gcc/c-common.h b/gcc/c-common.h index 8aac85761a6..fabfb1642a1 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -548,12 +548,14 @@ extern tree c_common_signed_type PARAMS ((tree)); 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_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)); @@ -573,6 +575,8 @@ extern void unsigned_conversion_warning PARAMS ((tree, tree)); /* 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 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 48b421313d6..f6e8d538d75 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -736,47 +736,6 @@ type_lists_compatible_p (args1, args2) } } -/* 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; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4a63bc69392..3cb8bd6b0de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2002-07-23 Gabriel Dos Reis + + 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. + 2002-07-23 Neil Booth * class.c, method.c, pt.c, search.c: Don't define obstack macros. @@ -30,7 +44,7 @@ 2002-07-20 Gabriel Dos Reis - * spew.c (struct uinparsed_test): Replace 'filename' and 'lineno' + * spew.c (struct unparsed_test): Replace 'filename' and 'lineno' members with 'locus'. Adjust use throughout. (struct feed): Likewise. (alloc_unparsed_test): Change prototype, take a 'const location_t *'. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0f4bf9081cf..fa7243dc5a7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4437,6 +4437,7 @@ extern int compparms PARAMS ((tree, tree)); 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)); @@ -4483,6 +4484,8 @@ extern tree merge_types PARAMS ((tree, tree)); 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)); @@ -4495,9 +4498,6 @@ 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)); extern tree digest_init PARAMS ((tree, tree, tree *)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e4897953e3e..337107baf62 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -14070,7 +14070,7 @@ finish_destructor_body () if (DECL_VIRTUAL_P (current_function_decl)) { tree if_stmt; - tree virtual_size = c_sizeof (current_class_type); + tree virtual_size = cxx_sizeof (current_class_type); /* [class.dtor] diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 9a18586b8b6..66922b19de3 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3779,7 +3779,7 @@ build_expr_from_tree (t) 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); + return cxx_sizeof_or_alignof_type (r, TREE_CODE (t)); } case MODOP_EXPR: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index bedd97936fb..ad127bf1747 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2106,7 +2106,7 @@ finish_sizeof (t) if (processing_template_decl) return build_min_nt (SIZEOF_EXPR, t); - return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t); + return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t); } /* Implement the __alignof keyword: Return the minimum required @@ -2119,7 +2119,7 @@ finish_alignof (t) if (processing_template_decl) return build_min_nt (ALIGNOF_EXPR, t); - return TYPE_P (t) ? c_alignof (t) : c_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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 30d8cac9a79..6d810f592ae 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1486,73 +1486,42 @@ comp_target_parms (parms1, parms2) return warn_contravariance ? -1 : 1; } -/* Compute the value of the `sizeof' operator. */ - tree -c_sizeof (type) +cxx_sizeof_or_alignof_type (type, op) tree type; + enum tree_code op; { - enum tree_code code = TREE_CODE (type); - tree size; + 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 (SIZEOF_EXPR, type); + 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 (code == FUNCTION_TYPE) + if (type_code == METHOD_TYPE) { if (pedantic || warn_pointer_arith) - pedwarn ("ISO C++ forbids applying `sizeof' to a function type"); - size = size_one_node; + pedwarn ("invalid application of `%s' to a member function", op_name); + value = size_one_node; } - else if (code == METHOD_TYPE) + else if (type_code == OFFSET_TYPE) { - if (pedantic || warn_pointer_arith) - pedwarn ("ISO C++ forbids applying `sizeof' to a member function"); - size = size_one_node; + error ("invalid application of `%s' to non-static member", op_name); + value = size_zero_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); + value = c_sizeof_or_alignof_type (complete_type (type), op); - 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; + return value; } - tree expr_sizeof (e) tree e; @@ -1582,7 +1551,7 @@ expr_sizeof (e) if (e == error_mark_node) return e; - return c_sizeof (TREE_TYPE (e)); + return cxx_sizeof (TREE_TYPE (e)); } tree diff --git a/gcc/testsuite/g++.dg/ext/alignof1.C b/gcc/testsuite/g++.dg/ext/alignof1.C new file mode 100644 index 00000000000..9e930ed857f --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/alignof1.C @@ -0,0 +1,19 @@ +// { dg-do run } + +// Copyright (C) 2002 Free Software Foundation, Inc. +// Contributed by Gabriel Dos Reis , 2002-07-20 +// Bug PR/7363. + +template +int my_alignof() +{ + return __alignof__ (T); +} + +template + struct X { }; + +int main() +{ + return my_alignof >(); +}