PR c++/89214 - ICE when initializing aggregates with bases.
authorMarek Polacek <polacek@redhat.com>
Mon, 25 Mar 2019 16:38:48 +0000 (16:38 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 25 Mar 2019 16:38:48 +0000 (16:38 +0000)
* typeck2.c (digest_init_r): Warn about object slicing instead of
crashing.

* g++.dg/cpp1z/aggr-base8.C: New test.
* g++.dg/cpp1z/aggr-base9.C: New test.

From-SVN: r269919

gcc/cp/ChangeLog
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/aggr-base8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/aggr-base9.C [new file with mode: 0644]

index b2b7b41d3347e6cbc699267d7fcd89264bf5e7b4..04f5639b96a4fa5a90cde21228e836076914a7d3 100644 (file)
@@ -1,5 +1,9 @@
 2019-03-25  Marek Polacek  <polacek@redhat.com>
 
+       PR c++/89214 - ICE when initializing aggregates with bases.
+       * typeck2.c (digest_init_r): Warn about object slicing instead of
+       crashing.
+
        PR c++/89705 - ICE with reference binding with conversion function.
        * call.c (reference_binding): If the result of the conversion function
        is a prvalue of non-class type, use the cv-unqualified type.
index e50d6ed83c3795a3f316e97a409dc0735f240106..7f242ba93daa3f236ef91d57442c46d766f9ebec 100644 (file)
@@ -1209,8 +1209,29 @@ digest_init_r (tree type, tree init, int nested, int flags,
     {
       tree elt = CONSTRUCTOR_ELT (stripped_init, 0)->value;
       if (reference_related_p (type, TREE_TYPE (elt)))
-       /* We should have fixed this in reshape_init.  */
-       gcc_unreachable ();
+       {
+         /* In C++17, aggregates can have bases, thus participate in
+            aggregate initialization.  In the following case:
+
+              struct B { int c; };
+              struct D : B { };
+              D d{{D{{42}}}};
+
+           there's an extra set of braces, so the D temporary initializes
+           the first element of d, which is the B base subobject.  The base
+           of type B is copy-initialized from the D temporary, causing
+           object slicing.  */
+         tree field = next_initializable_field (TYPE_FIELDS (type));
+         if (field && DECL_FIELD_IS_BASE (field))
+           {
+             if (warning_at (loc, 0, "initializing a base class of type %qT "
+                             "results in object slicing", TREE_TYPE (field)))
+               inform (loc, "remove %<{ }%> around initializer");
+           }
+         else
+           /* We should have fixed this in reshape_init.  */
+           gcc_unreachable ();
+       }
     }
 
   if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init)
index 01364a9d7795c1dd04e5b2993904650d77671a15..82981ad2a4c3e7927b43ed9b7ddf488eee6cfc02 100644 (file)
@@ -1,5 +1,9 @@
 2019-03-25  Marek Polacek  <polacek@redhat.com>
 
+       PR c++/89214 - ICE when initializing aggregates with bases.
+       * g++.dg/cpp1z/aggr-base8.C: New test.
+       * g++.dg/cpp1z/aggr-base9.C: New test.
+
        PR c++/89705 - ICE with reference binding with conversion function.
        * g++.dg/cpp0x/rv-conv2.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/aggr-base8.C b/gcc/testsuite/g++.dg/cpp1z/aggr-base8.C
new file mode 100644 (file)
index 0000000..8b495a8
--- /dev/null
@@ -0,0 +1,48 @@
+// PR c++/89214
+// { dg-do compile { target c++17 } }
+
+struct A
+{
+  A (int);
+};
+
+struct BB
+{
+  A a;
+};
+
+struct B : BB
+{
+};
+
+void
+foo ()
+{
+  B b1 = {42};
+  B b2 = {{42}};
+  B b3 = {{{42}}};
+
+  B b4 = B{42};
+  B b5 = B{{42}};
+  B b6 = B{{{42}}};
+
+  B b7 = {B{42}};
+  B b8 = {B{{42}}};
+  B b9 = {B{{{42}}}};
+
+  B b10 = {{B{42}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+  B b11 = {{B{{42}}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+  B b12 = {{B{{{42}}}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+
+  B bb1{42};
+  B bb2{{42}};
+  B bb3{{{42}}};
+
+  B bb7{B{42}};
+  B bb8{B{{42}}};
+  B bb9{B{{{42}}}};
+
+  B bb10{{B{42}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+  B bb11{{B{{42}}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+  B bb12{{B{{{42}}}}}; // { dg-warning "initializing a base class of type .BB. results in object slicing" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/aggr-base9.C b/gcc/testsuite/g++.dg/cpp1z/aggr-base9.C
new file mode 100644 (file)
index 0000000..56aa59c
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/89214
+// { dg-do compile { target c++17 } }
+
+struct B {
+  int c;
+};
+
+struct D : B { };
+
+void
+foo ()
+{
+  D d1 = {42};
+  D d2 = {{42}};
+  
+  D d4 = D{42};
+  D d5 = D{{42}};
+  D d7 = {D{42}};
+  D d8 = {D{{42}}};
+
+  D d10 = {{D{42}}}; // { dg-warning "initializing a base class of type .B. results in object slicing" }
+  D d11 = {{D{{42}}}}; // { dg-warning "initializing a base class of type .B. results in object slicing" }
+
+  D dd1{42};
+  D dd2{{42}};
+  
+  D dd7{D{42}};
+  D dd8{D{{42}}};
+
+  D dd10{{D{42}}}; // { dg-warning "initializing a base class of type .B. results in object slicing" }
+  D dd11{{D{{42}}}}; // { dg-warning "initializing a base class of type .B. results in object slicing" }
+}