From bf8c1b11d560b377c46177d4bcfe146c8b220587 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 25 Mar 2019 16:38:48 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 4 +++ gcc/cp/typeck2.c | 25 +++++++++++-- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/g++.dg/cpp1z/aggr-base8.C | 48 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/aggr-base9.C | 33 +++++++++++++++++ 5 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/aggr-base8.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/aggr-base9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b2b7b41d334..04f5639b96a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-03-25 Marek Polacek + 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 e50d6ed83c3..7f242ba93da 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 01364a9d779..82981ad2a4c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-03-25 Marek Polacek + 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 00000000000..8b495a80cb3 --- /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 00000000000..56aa59cb64a --- /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" } +} -- 2.30.2