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. --- gcc/cp/typeck2.c +++ 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) --- /dev/null +++ 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" } +} --- /dev/null +++ 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" } +}