diff options
author | Richard Henderson <rth@redhat.com> | 2005-10-12 16:34:09 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-10-12 16:34:09 -0700 |
commit | 52dd234b210c06bea54ef726995e1fce035329be (patch) | |
tree | e0ba09b20b9401b57ddfd7bb96ac65cafde86a0b | |
parent | 6deb03391308dcffb9bb4a4155cd27d7e60329f9 (diff) | |
download | gcc-52dd234b210c06bea54ef726995e1fce035329be.zip gcc-52dd234b210c06bea54ef726995e1fce035329be.tar.gz gcc-52dd234b210c06bea54ef726995e1fce035329be.tar.bz2 |
re PR c/24255 (__transparent_union__ mishandled)
PR c/24255
* tree.h (DECL_TRANSPARENT_UNION): Remove.
* function.c (assign_parm_find_data_types): Don't support it.
* print-tree.c (print_node): Likewise.
* c-common.c (handle_transparent_union_attribute): Likewise.
Use build_duplicate_type.
* tree-inline.c (remap_type_1): Split out of remap_type;
properly remap aggregate fields.
(build_duplicate_type): New.
* doc/extend.texi (Variable Attributes): Remove documentation
for transparent_union.
From-SVN: r105338
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c-common.c | 50 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 8 | ||||
-rw-r--r-- | gcc/function.c | 5 | ||||
-rw-r--r-- | gcc/print-tree.c | 3 | ||||
-rw-r--r-- | gcc/tree-inline.c | 74 | ||||
-rw-r--r-- | gcc/tree.h | 12 |
7 files changed, 102 insertions, 64 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index abf8908..308be618 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-10-12 Richard Henderson <rth@redhat.com> + + PR c/24255 + * tree.h (DECL_TRANSPARENT_UNION): Remove. + * function.c (assign_parm_find_data_types): Don't support it. + * print-tree.c (print_node): Likewise. + * c-common.c (handle_transparent_union_attribute): Likewise. + Use build_duplicate_type. + * tree-inline.c (remap_type_1): Split out of remap_type; + properly remap aggregate fields. + (build_duplicate_type): New. + * doc/extend.texi (Variable Attributes): Remove documentation + for transparent_union. + 2005-10-12 Eric Botcazou <ebotcazou@libertysurf.fr> PR target/24284 diff --git a/gcc/c-common.c b/gcc/c-common.c index 4114fbf..c5b409e 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4309,39 +4309,43 @@ handle_transparent_union_attribute (tree *node, tree name, tree ARG_UNUSED (args), int flags, bool *no_add_attrs) { - tree decl = NULL_TREE; - tree *type = NULL; - int is_type = 0; + tree type = NULL; + + *no_add_attrs = true; if (DECL_P (*node)) { - decl = *node; - type = &TREE_TYPE (decl); - is_type = TREE_CODE (*node) == TYPE_DECL; + if (TREE_CODE (*node) != TYPE_DECL) + goto ignored; + node = &TREE_TYPE (*node); + type = *node; } else if (TYPE_P (*node)) - type = node, is_type = 1; + type = *node; + else + goto ignored; - if (is_type - && TREE_CODE (*type) == UNION_TYPE - && (decl == 0 - || (TYPE_FIELDS (*type) != 0 - && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))))) + if (TREE_CODE (type) == UNION_TYPE) { + /* When IN_PLACE is set, leave the check for FIELDS and MODE to + the code in finish_struct. */ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *type = build_variant_type_copy (*type); - TYPE_TRANSPARENT_UNION (*type) = 1; - } - else if (decl != 0 && TREE_CODE (decl) == PARM_DECL - && TREE_CODE (*type) == UNION_TYPE - && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))) - DECL_TRANSPARENT_UNION (decl) = 1; - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; + { + if (TYPE_FIELDS (type) == NULL_TREE + || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type))) + goto ignored; + + /* A type variant isn't good enough, since we don't a cast + to such a type removed as a no-op. */ + *node = type = build_duplicate_type (type); + } + + TYPE_TRANSPARENT_UNION (type) = 1; + return NULL_TREE; } + ignored: + warning (OPT_Wattributes, "%qE attribute ignored", name); return NULL_TREE; } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 71518e4..52a8cc2 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3019,14 +3019,6 @@ The @var{tls_model} argument should be one of @code{global-dynamic}, Not all targets support this attribute. -@item transparent_union -This attribute, attached to a function parameter which is a union, means -that the corresponding argument may have the type of any union member, -but the argument is passed as if its type were that of the first union -member. For more details see @xref{Type Attributes}. You can also use -this attribute on a @code{typedef} for a union data type; then it -applies to all function parameters with that type. - @item unused This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this diff --git a/gcc/function.c b/gcc/function.c index 2df1eff..7cff2a0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2013,9 +2013,8 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, /* If the parm is to be passed as a transparent union, use the type of the first field for the tests below. We have already verified that the modes are the same. */ - if (DECL_TRANSPARENT_UNION (parm) - || (TREE_CODE (passed_type) == UNION_TYPE - && TYPE_TRANSPARENT_UNION (passed_type))) + if (TREE_CODE (passed_type) == UNION_TYPE + && TYPE_TRANSPARENT_UNION (passed_type)) passed_type = TREE_TYPE (TYPE_FIELDS (passed_type)); /* See if this arg was passed by invisible reference. */ diff --git a/gcc/print-tree.c b/gcc/print-tree.c index ddc370b..9a8a5bb7 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -385,9 +385,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent) } } - if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node)) - fputs (" transparent-union", file); - if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS) && DECL_DEFER_OUTPUT (node)) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f22785c..0f7ea97 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -257,26 +257,10 @@ remap_decl (tree decl, inline_data *id) } static tree -remap_type (tree type, inline_data *id) +remap_type_1 (tree type, inline_data *id) { - splay_tree_node node; tree new, t; - if (type == NULL) - return type; - - /* See if we have remapped this type. */ - node = splay_tree_lookup (id->decl_map, (splay_tree_key) type); - if (node) - return (tree) node->value; - - /* The type only needs remapping if it's variably modified. */ - if (! variably_modified_type_p (type, id->callee)) - { - 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. */ @@ -353,7 +337,18 @@ remap_type (tree type, inline_data *id) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL); + { + tree f, nf = NULL; + + for (f = TYPE_FIELDS (new); f ; f = TREE_CHAIN (f)) + { + t = remap_decl (f, id); + DECL_CONTEXT (t) = new; + TREE_CHAIN (t) = nf; + nf = t; + } + TYPE_FIELDS (new) = nreverse (nf); + } break; case OFFSET_TYPE: @@ -369,6 +364,29 @@ remap_type (tree type, inline_data *id) } static tree +remap_type (tree type, inline_data *id) +{ + splay_tree_node node; + + if (type == NULL) + return type; + + /* See if we have remapped this type. */ + node = splay_tree_lookup (id->decl_map, (splay_tree_key) type); + if (node) + return (tree) node->value; + + /* The type only needs remapping if it's variably modified. */ + if (! variably_modified_type_p (type, id->callee)) + { + insert_decl_map (id, type, type); + return type; + } + + return remap_type_1 (type, id); +} + +static tree remap_decls (tree decls, inline_data *id) { tree old_var; @@ -2959,3 +2977,23 @@ inlining_p (inline_data * id) { return (!id->saving_p && !id->cloning_p && !id->versioning_p); } + +/* Duplicate a type, fields and all. */ + +tree +build_duplicate_type (tree type) +{ + inline_data id; + + memset (&id, 0, sizeof (id)); + id.callee = current_function_decl; + id.caller = current_function_decl; + id.callee_cfun = cfun; + id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); + + type = remap_type_1 (type, &id); + + splay_tree_delete (id.decl_map); + + return type; +} @@ -2199,12 +2199,11 @@ struct tree_decl_common GTY(()) /* In LABEL_DECL, this is DECL_ERROR_ISSUED. In VAR_DECL and PARM_DECL, this is DECL_REGISTER. */ unsigned decl_flag_0 : 1; - /* In FIELD_DECL, this is DECL_PACKED - In PARM_DECL, this is DECL_TRANSPARENT_UNION. */ + /* In FIELD_DECL, this is DECL_PACKED. */ unsigned decl_flag_1 : 1; /* In FIELD_DECL, this is DECL_BIT_FIELD In VAR_DECL and FUNCTION_DECL, this is DECL_EXTERNAL. - In TYPE_DECL, this is TYPE_DECL_SUPRESS_DEBUG*/ + In TYPE_DECL, this is TYPE_DECL_SUPRESS_DEBUG. */ unsigned decl_flag_2 : 1; /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR. */ @@ -2386,12 +2385,6 @@ struct tree_const_decl GTY(()) where the data was actually passed. */ #define DECL_INCOMING_RTL(NODE) (PARM_DECL_CHECK (NODE)->parm_decl.incoming_rtl) -/* Used in PARM_DECLs whose type are unions to indicate that the - argument should be passed in the same way that the first union - alternative would be passed. */ -#define DECL_TRANSPARENT_UNION(NODE) \ - (PARM_DECL_CHECK (NODE)->decl_common.decl_flag_1) - struct tree_parm_decl GTY(()) { struct tree_decl_with_rtl common; @@ -3989,6 +3982,7 @@ extern bool debug_find_tree (tree, tree); /* This is in tree-inline.c since the routine uses data structures from the inliner. */ extern tree unsave_expr_now (tree); +extern tree build_duplicate_type (tree); /* In emit-rtl.c */ extern rtx emit_line_note (location_t); |