aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-10-12 16:34:09 -0700
committerRichard Henderson <rth@gcc.gnu.org>2005-10-12 16:34:09 -0700
commit52dd234b210c06bea54ef726995e1fce035329be (patch)
treee0ba09b20b9401b57ddfd7bb96ac65cafde86a0b /gcc
parent6deb03391308dcffb9bb4a4155cd27d7e60329f9 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c-common.c50
-rw-r--r--gcc/doc/extend.texi8
-rw-r--r--gcc/function.c5
-rw-r--r--gcc/print-tree.c3
-rw-r--r--gcc/tree-inline.c74
-rw-r--r--gcc/tree.h12
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;
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 144dbd8..f54f6d3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);