It doesn't make sense to mark a type with no fields as a transparent
union, and indeed handle_transparent_union checks for that. But this
testcase was slipping past the checks because we're applying the
attribute in place but after the type has been completed. This patch
adjusts the check logic so that we check for a suitable field even when
applying the attribute in place if we've already done finish_struct.
Tested x86_64-pc-linux-gnu. OK for trunk? This is apparently a
regression back to 4.5.0, but doesn't seem worth fixing in older
releases since this isn't a valid use of the attribute.
commit f3b9daf04363159ed8707df50ed77989e1ee31be
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Dec 14 14:05:57 2011 -0500
PR c++/51228
* c-common.c (handle_transparent_union_attribute): Check the first
field if the type is complete.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index fbbcb38..87eee79 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6286,13 +6286,21 @@ handle_transparent_union_attribute (tree *node, tree name,
if (TREE_CODE (type) == UNION_TYPE)
{
- /* When IN_PLACE is set, leave the check for FIELDS and MODE to
- the code in finish_struct. */
+ /* Make sure that the first field will work for a transparent union.
+ If the type isn't complete yet, leave the check to the code in
+ finish_struct. */
+ if (TYPE_SIZE (type))
+ {
+ tree first = first_field (type);
+ if (first == NULL_TREE
+ || TYPE_MODE (type) != DECL_MODE (first))
+ goto ignored;
+ }
+
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
{
- if (TYPE_FIELDS (type) == NULL_TREE
- || c_dialect_cxx ()
- || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type)))
+ /* build_duplicate_type doesn't work for C++. */
+ if (c_dialect_cxx ())
goto ignored;
/* A type variant isn't good enough, since we don't a cast
diff --git a/gcc/testsuite/c-c++-common/transparent-union-1.c b/gcc/testsuite/c-c++-common/transparent-union-1.c
new file mode 100644
index 0000000..3fb6e78
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/transparent-union-1.c
@@ -0,0 +1,5 @@
+/* PR c++/51228 */
+
+typedef union {} U __attribute__((transparent_union)); /* { dg-warning "ignored" } */
+
+void foo(U u) {}