diff mbox

[C++] PR 66644

Message ID 572267EF.1060200@oracle.com
State New
Headers show

Commit Message

Paolo Carlini April 28, 2016, 7:43 p.m. UTC
Hi,

only when Jakub bumped some bugs in preparation for the release I noted 
that this one remained assigned to me for way too much time...

Roughly speaking, the problem is caused by the fact that when we have a 
GNU anonymous struct inside a union the fields are flattened out and 
appear to be just individual fields of the union. Thus we end up 
rejecting test1 below because multiple fields are initialized and we 
don't simply handle them later on as NSDMIs. A GNU anonymous struct is 
required for the issue to show up, thus the details of the way we want 
to handle such code are debatable, but we know that, eg, both EDG and 
clang accept test1 too (in relaxed GNU mode, at least), besides test2 
and test3.

Given the underlying cause of the rejection I could easily imagine other 
less straightforward ways to match the cases at issues in 
check_field_decl (eg, along the lines DECL_CONTEXT (field) == t ??), but 
the below certainly passes testing on x86_64-linux.

Thanks,
Paolo.

////////////////////////////
/cp
2016-04-28  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/66644
	* class.c (check_field_decl): Do not reject multiple initialized
	fields in anonymous struct.

/testsuite
2016-04-28  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/66644
	* g++.dg/cpp0x/nsdmi-anon-struct1.C: New.

Comments

Jason Merrill April 28, 2016, 9:45 p.m. UTC | #1
I would expect this to cause a false negative on a union of two 
anonymous structs, both of which have initialized members.

I think better would be to have a local any_default_members rather than 
passing the same pointer through all levels.

Also, you can look at 'type' rather than DECL_CONTEXT (field).

Jason
diff mbox

Patch

Index: cp/class.c
===================================================================
--- cp/class.c	(revision 235557)
+++ cp/class.c	(working copy)
@@ -3623,7 +3623,11 @@  check_field_decl (tree field,
     {
       /* `build_class_init_list' does not recognize
 	 non-FIELD_DECLs.  */
-      if (TREE_CODE (t) == UNION_TYPE && *any_default_members != 0)
+      if (TREE_CODE (t) == UNION_TYPE && *any_default_members != 0
+	  /* As a GNU extension initializing in C++11 multiple fields
+	     of an anonymous struct living inside a union is fine.  */
+	  && !(TREE_CODE (DECL_CONTEXT (field)) == RECORD_TYPE
+	       && ANON_AGGR_TYPE_P (DECL_CONTEXT (field))))
 	error ("multiple fields in union %qT initialized", t);
       *any_default_members = 1;
     }
Index: testsuite/g++.dg/cpp0x/nsdmi-anon-struct1.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-anon-struct1.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-anon-struct1.C	(working copy)
@@ -0,0 +1,30 @@ 
+// PR c++/66644
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-pedantic" }
+
+struct test1  
+{
+  union
+  {
+    struct { char a=0, b=0; };
+    char buffer[16];
+  };
+};
+
+struct test2 
+{
+  union  
+  {
+    struct { char a=0, b; };
+    char buffer[16];
+  };
+};
+
+struct test3
+{
+  union
+  {
+    struct { char a, b; } test2{0,0};
+    char buffer[16];
+  };
+};