diff options
author | Jason Merrill <jason@redhat.com> | 2020-01-16 10:46:40 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-01-16 17:40:15 -0500 |
commit | 801f5b96775288e55193a66a746caab1ddd56f4a (patch) | |
tree | 4ca550165104863c6e01a704dfb637864051b2bf /gcc | |
parent | f48c6014133c8989702458f9082e34ba6dd326d4 (diff) | |
download | gcc-801f5b96775288e55193a66a746caab1ddd56f4a.zip gcc-801f5b96775288e55193a66a746caab1ddd56f4a.tar.gz gcc-801f5b96775288e55193a66a746caab1ddd56f4a.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 3 |
3 files changed, 10 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 47d55e5..3ca5d7a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-01-16 Jason Merrill <jason@redhat.com> + + 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 <paolo.carlini@oracle.com> PR c++/91073 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ba80474..543d127 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 f36a564..371b203 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; } |