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
This commit is contained in:
Marek Polacek 2019-03-25 16:38:48 +00:00 committed by Marek Polacek
parent a55f758221
commit bf8c1b11d5
5 changed files with 112 additions and 2 deletions

View 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.

View 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)

View 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.

View file

@ -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" }
}

View file

@ -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" }
}