diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 713450ccdd55..15bd247d5b23 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2007-11-19 Jason Merrill + + PR debug/29436, c/32326 + * tree.c (build_type_attribute_qual_variant): Refuse to make + a distinct copy of a struct/enum type. Use build_distinct_type_copy. + * doc/extend.texi (Type Attributes): Don't encourage people to add + attributes to struct/enum types in a typedef. Fix + transparent_union example. + + * tree-inline.c (remap_type_1): Remove code that's redundant with + remap_type. + (build_duplicate_type): Set id.copy_decl. + * c-common.c (handle_transparent_union_attribute): Simplify logic. + 2007-11-19 Peter Bergner * config/rs6000/rs6000.c (invalid_e500_subreg, diff --git a/gcc/c-common.c b/gcc/c-common.c index 763745a4937d..edc9b2c17fb3 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5007,21 +5007,13 @@ handle_transparent_union_attribute (tree *node, tree name, tree ARG_UNUSED (args), int flags, bool *no_add_attrs) { - tree type = NULL; + tree type; *no_add_attrs = true; - if (DECL_P (*node)) - { - if (TREE_CODE (*node) != TYPE_DECL) - goto ignored; - node = &TREE_TYPE (*node); - type = *node; - } - else if (TYPE_P (*node)) - type = *node; - else - goto ignored; + if (TREE_CODE (*node) == TYPE_DECL) + node = &TREE_TYPE (*node); + type = *node; if (TREE_CODE (type) == UNION_TYPE) { diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 1c0d476a63ae..c86052e29593 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3938,8 +3938,9 @@ attributes in header files without being concerned about a possible macro of the same name. For example, you may use @code{__aligned__} instead of @code{aligned}. -You may specify type attributes either in a @code{typedef} declaration -or in an enum, struct or union type declaration or definition. +You may specify type attributes in an enum, struct or union type +declaration or definition, or for other types in a @code{typedef} +declaration. For an enum, struct or union type, you may specify attributes either between the enum, struct or union tag and the name of the type, or @@ -4098,11 +4099,11 @@ less useful. Instead, @code{} might define the interface as follows: @smallexample -typedef union +typedef union __attribute__ ((__transparent_union__)) @{ int *__ip; union wait *__up; - @} wait_status_ptr_t __attribute__ ((__transparent_union__)); + @} wait_status_ptr_t; pid_t wait (wait_status_ptr_t); @end smallexample diff --git a/gcc/testsuite/gcc.c-torture/execute/mayalias-2.c b/gcc/testsuite/gcc.c-torture/execute/mayalias-2.c index 5a1a9d5e4a1b..39c010d91e68 100644 --- a/gcc/testsuite/gcc.c-torture/execute/mayalias-2.c +++ b/gcc/testsuite/gcc.c-torture/execute/mayalias-2.c @@ -1,5 +1,4 @@ -struct S { short x; }; -typedef struct S __attribute__((__may_alias__)) test; +typedef struct __attribute__((__may_alias__)) { short x; } test; int f() { int a=10; diff --git a/gcc/testsuite/gcc.c-torture/execute/mayalias-3.c b/gcc/testsuite/gcc.c-torture/execute/mayalias-3.c index 3d667911f4e0..53bd07ab19af 100644 --- a/gcc/testsuite/gcc.c-torture/execute/mayalias-3.c +++ b/gcc/testsuite/gcc.c-torture/execute/mayalias-3.c @@ -1,5 +1,4 @@ -struct S { short x; }; -typedef struct S __attribute__((__may_alias__)) test; +typedef struct __attribute__((__may_alias__)) { short x; } test; test *p; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index e0d4093a38c9..da52d6c82e2c 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -273,24 +273,8 @@ remap_decl (tree decl, copy_body_data *id) static tree remap_type_1 (tree type, copy_body_data *id) { - tree *node; tree new, t; - if (type == NULL) - return type; - - /* See if we have remapped this type. */ - node = (tree *) pointer_map_contains (id->decl_map, type); - if (node) - return *node; - - /* The type only needs remapping if it's variably modified. */ - if (! variably_modified_type_p (type, id->src_fn)) - { - insert_decl_map (id, type, type); - return type; - } - /* We do need a copy. build and register it now. If this is a pointer or reference type, remap the designated type and make a new pointer or reference type. */ @@ -3593,6 +3577,7 @@ build_duplicate_type (tree type) id.dst_fn = current_function_decl; id.src_cfun = cfun; id.decl_map = pointer_map_create (); + id.copy_decl = copy_decl_no_change; type = remap_type_1 (type, &id); diff --git a/gcc/tree.c b/gcc/tree.c index 81c54d0edf49..9c6547480b7f 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -3666,15 +3666,26 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) tree ntype; enum tree_code code = TREE_CODE (ttype); - ntype = copy_node (ttype); + /* Building a distinct copy of a tagged type is inappropriate; it + causes breakage in code that expects there to be a one-to-one + relationship between a struct and its fields. + build_duplicate_type is another solution (as used in + handle_transparent_union_attribute), but that doesn't play well + with the stronger C++ type identity model. */ + if (TREE_CODE (ttype) == RECORD_TYPE + || TREE_CODE (ttype) == UNION_TYPE + || TREE_CODE (ttype) == QUAL_UNION_TYPE + || TREE_CODE (ttype) == ENUMERAL_TYPE) + { + warning (OPT_Wattributes, + "ignoring attributes applied to %qT after definition", + TYPE_MAIN_VARIANT (ttype)); + return build_qualified_type (ttype, quals); + } + + ntype = build_distinct_type_copy (ttype); - TYPE_POINTER_TO (ntype) = 0; - TYPE_REFERENCE_TO (ntype) = 0; TYPE_ATTRIBUTES (ntype) = attribute; - - /* Create a new main variant of TYPE. */ - TYPE_MAIN_VARIANT (ntype) = ntype; - TYPE_NEXT_VARIANT (ntype) = 0; set_type_quals (ntype, TYPE_UNQUALIFIED); hashcode = iterative_hash_object (code, hashcode);