aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-03-25 16:38:48 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-03-25 16:38:48 +0000
commitbf8c1b11d560b377c46177d4bcfe146c8b220587 (patch)
tree5c45e44201be32398ac31f7e6f8d373145b17cb6
parenta55f758221cfd574cc341f969c27f8ecdac087a4 (diff)
downloadgcc-bf8c1b11d560b377c46177d4bcfe146c8b220587.zip
gcc-bf8c1b11d560b377c46177d4bcfe146c8b220587.tar.gz
gcc-bf8c1b11d560b377c46177d4bcfe146c8b220587.tar.bz2
PR c++/89214 - ICE when initializing aggregates with bases.
* 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
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/typeck2.c25
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/aggr-base8.C48
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/aggr-base9.C33
5 files changed, 112 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b2b7b41..04f5639 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e50d6ed..7f242ba 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 01364a9..82981ad 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..8b495a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aggr-base8.C
@@ -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
index 0000000..56aa59c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aggr-base9.C
@@ -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" }
+}