aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck2.c')
-rw-r--r--gcc/cp/typeck2.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index b91c98d594b..b28044c11dc 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1142,8 +1142,29 @@ digest_init_r (tree type, tree init, int nested, int flags,
{
tree elt = CONSTRUCTOR_ELT (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 (init)
@@ -1538,6 +1559,13 @@ process_init_constructor_record (tree type, tree init, int nested,
}
}
+ if (DECL_SIZE (field) && integer_zerop (DECL_SIZE (field))
+ && !TREE_SIDE_EFFECTS (next))
+ /* Don't add trivial initialization of an empty base/field to the
+ constructor, as they might not be ordered the way the back-end
+ expects. */
+ continue;
+
/* If this is a bitfield, now convert to the lowered type. */
if (type != TREE_TYPE (field))
next = cp_convert_and_check (TREE_TYPE (field), next, complain);