diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4608f11e8e9..111edcc283a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 2002-03-15 Jason Merrill + PR c++/5857 + * decl.c (duplicate_decls): Use merge_types instead of common_type. + * typeck.c (common_type): Just hand off to + type_after_usual_arithmetic_conversions and + composite_pointer_type. + (merge_types): New fn. + (commonparms): Use it instead of common_type. + (type_after_usual_arithmetic_conversions): Also handle COMPLEX_TYPE. + (composite_pointer_type): Also handle attributes. + * cp-tree.h: Declare merge_types. + * decl.c (make_rtl_for_nonlocal_decl): Also defer COMDAT variables. * decl2.c (maybe_make_one_only): Also mark the decl as needed. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 33e09e3457b..5f58ef66ca5 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4355,6 +4355,7 @@ extern tree pfn_from_ptrmemfunc PARAMS ((tree)); extern tree type_after_usual_arithmetic_conversions PARAMS ((tree, tree)); extern tree composite_pointer_type PARAMS ((tree, tree, tree, tree, const char*)); +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) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 758524b7c75..d76c6a5c490 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3515,16 +3515,16 @@ duplicate_decls (newdecl, olddecl) tree newtype; /* Merge the data types specified in the two decls. */ - newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); + newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); - /* If common_type produces a non-typedef type, just use the old type. */ + /* If merge_types produces a non-typedef type, just use the old type. */ if (TREE_CODE (newdecl) == TYPE_DECL && newtype == DECL_ORIGINAL_TYPE (newdecl)) newtype = oldtype; if (TREE_CODE (newdecl) == VAR_DECL) DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); - /* Do this after calling `common_type' so that default + /* Do this after calling `merge_types' so that default parameters don't confuse us. */ else if (TREE_CODE (newdecl) == FUNCTION_DECL && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b14687b5027..a8a424a7b59 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -285,7 +285,7 @@ commonparms (p1, p2) if (TREE_VALUE (p1) != TREE_VALUE (p2)) { any_change = 1; - TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2)); + TREE_VALUE (n) = merge_types (TREE_VALUE (p1), TREE_VALUE (p2)); } else TREE_VALUE (n) = TREE_VALUE (p1); @@ -330,16 +330,38 @@ type_after_usual_arithmetic_conversions (t1, t2) /* FIXME: Attributes. */ my_friendly_assert (ARITHMETIC_TYPE_P (t1) + || TREE_CODE (t1) == COMPLEX_TYPE || TREE_CODE (t1) == ENUMERAL_TYPE, 19990725); my_friendly_assert (ARITHMETIC_TYPE_P (t2) + || TREE_CODE (t2) == COMPLEX_TYPE || TREE_CODE (t2) == ENUMERAL_TYPE, 19990725); - /* In what follows, we slightly generalize the rules given in [expr] - so as to deal with `long long'. First, merge the attributes. */ + /* In what follows, we slightly generalize the rules given in [expr] so + as to deal with `long long' and `complex'. First, merge the + attributes. */ attributes = (*targetm.merge_type_attributes) (t1, t2); + /* If one type is complex, form the common type of the non-complex + components, then make that complex. Use T1 or T2 if it is the + required type. */ + if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) + { + tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; + tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; + tree subtype + = type_after_usual_arithmetic_conversions (subtype1, subtype2); + + if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) + return build_type_attribute_variant (t1, attributes); + else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) + return build_type_attribute_variant (t2, attributes); + else + return build_type_attribute_variant (build_complex_type (subtype), + attributes); + } + /* If only one is real, use it as the result. */ if (code1 == REAL_TYPE && code2 != REAL_TYPE) return build_type_attribute_variant (t1, attributes); @@ -439,6 +461,7 @@ composite_pointer_type (t1, t2, arg1, arg2, location) const char* location; { tree result_type; + tree attributes; /* [expr.rel] @@ -456,6 +479,9 @@ composite_pointer_type (t1, t2, arg1, arg2, location) if (TYPE_PTRMEMFUNC_P (t2)) t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); + /* Merge the attributes. */ + attributes = (*targetm.merge_type_attributes) (t1, t2); + /* We have: [expr.rel] @@ -504,21 +530,18 @@ composite_pointer_type (t1, t2, arg1, arg2, location) } } - return result_type; + return build_type_attribute_variant (result_type, attributes); } -/* Return the common type of two types. +/* Return the merged type of two types. We assume that comptypes has already been done and returned 1; if that isn't so, this may crash. - This is the type for the result of most arithmetic operations - if the operands have the given two types. - - We do not deal with enumeral types here because they have already been - converted to integer types. */ + This just combines attributes and default arguments; any other + differences would cause the two types to compare unalike. */ tree -common_type (t1, t2) +merge_types (t1, t2) tree t1, t2; { register enum tree_code code1; @@ -528,9 +551,7 @@ common_type (t1, t2) /* Save time if the two types are the same. */ if (t1 == t2) return t1; - t1 = original_type (t1); - t2 = original_type (t2); - if (t1 == t2) + if (original_type (t1) == original_type (t2)) return t1; /* If one type is nonsense, use the other. */ @@ -539,20 +560,11 @@ common_type (t1, t2) if (t2 == error_mark_node) return t1; - if ((ARITHMETIC_TYPE_P (t1) || TREE_CODE (t1) == ENUMERAL_TYPE) - && (ARITHMETIC_TYPE_P (t2) || TREE_CODE (t2) == ENUMERAL_TYPE)) - return type_after_usual_arithmetic_conversions (t1, t2); - /* Merge the attributes. */ attributes = (*targetm.merge_type_attributes) (t1, t2); /* Treat an enum type as the unsigned integer type of the same width. */ - if (TREE_CODE (t1) == ENUMERAL_TYPE) - t1 = type_for_size (TYPE_PRECISION (t1), 1); - if (TREE_CODE (t2) == ENUMERAL_TYPE) - t2 = type_for_size (TYPE_PRECISION (t2), 1); - if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) @@ -561,82 +573,13 @@ common_type (t1, t2) code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); - /* If one type is complex, form the common type of the non-complex - components, then make that complex. Use T1 or T2 if it is the - required type. */ - if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) - { - tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; - tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; - tree subtype = common_type (subtype1, subtype2); - - if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) - return build_type_attribute_variant (t1, attributes); - else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) - return build_type_attribute_variant (t2, attributes); - else - return build_type_attribute_variant (build_complex_type (subtype), - attributes); - } - switch (code1) { - case INTEGER_TYPE: - case REAL_TYPE: - /* We should have called type_after_usual_arithmetic_conversions - above. */ - abort (); - break; - case POINTER_TYPE: case REFERENCE_TYPE: - /* For two pointers, do this recursively on the target type, - and combine the qualifiers of the two types' targets. */ - /* This code was turned off; I don't know why. - But ISO C++ specifies doing this with the qualifiers. - So I turned it on again. */ + /* For two pointers, do this recursively on the target type. */ { - tree tt1 = TREE_TYPE (t1); - tree tt2 = TREE_TYPE (t2); - tree b1, b2; - int type_quals; - tree target; - - if (TREE_CODE (tt1) == OFFSET_TYPE) - { - b1 = TYPE_OFFSET_BASETYPE (tt1); - b2 = TYPE_OFFSET_BASETYPE (tt2); - tt1 = TREE_TYPE (tt1); - tt2 = TREE_TYPE (tt2); - } - else - b1 = b2 = NULL_TREE; - - type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2)); - tt1 = TYPE_MAIN_VARIANT (tt1); - tt2 = TYPE_MAIN_VARIANT (tt2); - - if (tt1 == tt2) - target = tt1; - else if (VOID_TYPE_P (tt1) || VOID_TYPE_P (tt2)) - target = void_type_node; - else if (tt1 == unknown_type_node) - target = tt2; - else if (tt2 == unknown_type_node) - target = tt1; - else - target = common_type (tt1, tt2); - - target = cp_build_qualified_type (target, type_quals); - - if (b1) - { - if (same_type_p (b1, b2) - || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))) - target = build_offset_type (b2, target); - else if (binfo_or_else (b2, b1)) - target = build_offset_type (b1, target); - } + tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2)); if (code1 == POINTER_TYPE) t1 = build_pointer_type (target); @@ -650,9 +593,17 @@ common_type (t1, t2) return t1; } + case OFFSET_TYPE: + { + tree base = TYPE_OFFSET_BASETYPE (t1); + tree target = merge_types (TREE_TYPE (t1), TREE_TYPE (t2)); + t1 = build_offset_type (base, target); + break; + } + case ARRAY_TYPE: { - tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree elt = merge_types (TREE_TYPE (t1), TREE_TYPE (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) return build_type_attribute_variant (t1, attributes); @@ -661,14 +612,14 @@ common_type (t1, t2) /* Merge the element types, and have a size if either arg has one. */ t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); - return build_type_attribute_variant (t1, attributes); + break; } case FUNCTION_TYPE: /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { - tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2)); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); tree rval, raises; @@ -697,73 +648,72 @@ common_type (t1, t2) } rval = build_function_type (valtype, commonparms (p1, p2)); - rval = build_exception_variant (rval, raises); - return build_type_attribute_variant (rval, attributes); + t1 = build_exception_variant (rval, raises); + break; } - case RECORD_TYPE: - case UNION_TYPE: - t1 = TYPE_MAIN_VARIANT (t1); - t2 = TYPE_MAIN_VARIANT (t2); - - if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2)) - return build_type_attribute_variant (t1, attributes); - else if (binfo_or_else (t2, t1)) - return build_type_attribute_variant (t2, attributes); - else - { - compiler_error ("common_type called with uncommon aggregate types"); - return error_mark_node; - } - case METHOD_TYPE: - if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) - { - /* Get this value the long way, since TYPE_METHOD_BASETYPE - is just the main variant of this. */ - tree basetype; - tree raises, t3; + { + /* Get this value the long way, since TYPE_METHOD_BASETYPE + is just the main variant of this. */ + tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2))); + tree raises = TYPE_RAISES_EXCEPTIONS (t1); + tree t3; - tree b1 = TYPE_OFFSET_BASETYPE (t1); - tree b2 = TYPE_OFFSET_BASETYPE (t2); + /* If this was a member function type, get back to the + original type of type member function (i.e., without + the class instance variable up front. */ + t1 = build_function_type (TREE_TYPE (t1), + TREE_CHAIN (TYPE_ARG_TYPES (t1))); + t2 = build_function_type (TREE_TYPE (t2), + TREE_CHAIN (TYPE_ARG_TYPES (t2))); + t3 = merge_types (t1, t2); + t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), + TYPE_ARG_TYPES (t3)); + t1 = build_exception_variant (t3, raises); + break; + } - if (same_type_p (b1, b2) - || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))) - basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2))); - else - { - if (binfo_or_else (b2, b1) == NULL_TREE) - compiler_error ("common_type called with uncommon method types"); - basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1))); - } - - raises = TYPE_RAISES_EXCEPTIONS (t1); - - /* If this was a member function type, get back to the - original type of type member function (i.e., without - the class instance variable up front. */ - t1 = build_function_type (TREE_TYPE (t1), - TREE_CHAIN (TYPE_ARG_TYPES (t1))); - t2 = build_function_type (TREE_TYPE (t2), - TREE_CHAIN (TYPE_ARG_TYPES (t2))); - t3 = common_type (t1, t2); - t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), - TYPE_ARG_TYPES (t3)); - t1 = build_exception_variant (t3, raises); - } - else - compiler_error ("common_type called with uncommon method types"); - - return build_type_attribute_variant (t1, attributes); - - case OFFSET_TYPE: - /* Pointers to members should now be handled by the POINTER_TYPE - case above. */ - abort (); - - default: - return build_type_attribute_variant (t1, attributes); + default:; } + return build_type_attribute_variant (t1, attributes); +} + +/* Return the common type of two types. + We assume that comptypes has already been done and returned 1; + if that isn't so, this may crash. + + This is the type for the result of most arithmetic operations + if the operands have the given two types. */ + +tree +common_type (t1, t2) + tree t1, t2; +{ + enum tree_code code1; + enum tree_code code2; + + /* If one type is nonsense, bail. */ + if (t1 == error_mark_node || t2 == error_mark_node) + return error_mark_node; + + code1 = TREE_CODE (t1); + code2 = TREE_CODE (t2); + + if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE + || code1 == COMPLEX_TYPE) + && (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE + || code2 == COMPLEX_TYPE)) + return type_after_usual_arithmetic_conversions (t1, t2); + + else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) + || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)) + || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) + return composite_pointer_type (t1, t2, error_mark_node, error_mark_node, + "conversion"); + + else + abort (); } /* Compare two exception specifier types for exactness or subsetness, if diff --git a/gcc/testsuite/g++.dg/other/redecl1.C b/gcc/testsuite/g++.dg/other/redecl1.C new file mode 100644 index 00000000000..cfcf6682691 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/redecl1.C @@ -0,0 +1,10 @@ +// PR c++/5857 +// This testcase failed because during duplicate_decls the type was promoted +// to int. + +// { dg-do compile } + +typedef char baz; +extern const char foo[]; +const baz foo[] = "xyz"; +const char bar[] = "abc";