From 801f5b96775288e55193a66a746caab1ddd56f4a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 16 Jan 2020 10:46:40 -0500 Subject: [PATCH] PR c++/93280 - ICE with aggregate assignment and DMI. I recently added an assert to cp-gimplify to catch any TARGET_EXPR_DIRECT_INIT_P being expanded without a target object, and this testcase found one. We started out with a TARGET_EXPR around the CONSTRUCTOR, which would normally mean that the member initializer would be used to directly initialize the appropriate member of whatever object the TARGET_EXPR ends up initializing. But then gimplify_modify_expr_rhs stripped the TARGET_EXPR in order to assign directly from the elements of the CONSTRUCTOR, leaving no object for the TARGET_EXPR_DIRECT_INIT_P to initialize. I considered setting CONSTRUCTOR_PLACEHOLDER_BOUNDARY in that case, which implies TARGET_EXPR_NO_ELIDE, but decided that there's no particular reason the A initializer needs to initialize a member of a B rather than a distinct A object, so let's only set TARGET_EXPR_DIRECT_INIT_P when we're using the DMI in a constructor. * init.c (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P here. * typeck2.c (digest_nsdmi_init): Not here. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/init.c | 4 ++++ gcc/cp/typeck2.c | 3 --- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 47d55e5066d..3ca5d7a11b4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-01-16 Jason Merrill + + PR c++/93280 - ICE with aggregate assignment and DMI. + * init.c (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P here. + * typeck2.c (digest_nsdmi_init): Not here. + 2020-01-15 Paolo Carlini PR c++/91073 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ba80474e6ac..543d127abcd 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -655,6 +655,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) if (simple_target) init = TARGET_EXPR_INITIAL (init); init = break_out_target_exprs (init, /*loc*/true); + if (in_ctor && init && TREE_CODE (init) == TARGET_EXPR) + /* This expresses the full initialization, prevent perform_member_init from + calling another constructor (58162). */ + TARGET_EXPR_DIRECT_INIT_P (init) = true; if (simple_target && TREE_CODE (init) != CONSTRUCTOR) /* Now put it back so C++17 copy elision works. */ init = get_target_expr (init); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index f36a5649ae6..371b203c29b 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1369,9 +1369,6 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain) && CP_AGGREGATE_TYPE_P (type)) init = reshape_init (type, init, complain); init = digest_init_flags (type, init, flags, complain); - if (TREE_CODE (init) == TARGET_EXPR) - /* This represents the whole initialization. */ - TARGET_EXPR_DIRECT_INIT_P (init) = true; return init; } -- 2.30.2