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) {}

Reply via email to