c++: temporary lifetime with aggregate init [PR94041]
authorJason Merrill <jason@redhat.com>
Thu, 5 Mar 2020 20:50:45 +0000 (15:50 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 7 Jan 2022 00:23:16 +0000 (19:23 -0500)
commitce0ab8fb46f07b0bde56aa31e46d57b81379fde3
treebdb5e8757231f734c284db6f3fac886a127b78c7
parente948436eab818c527dd60b0ef939c4f42fbe8ba4
c++: temporary lifetime with aggregate init [PR94041]

In C++98 the lifetime of temporaries in aggregate initialization was
unclear, but C++11 DR201 clarified that only temporaries created for
default-initialization of an array element with no corresponding
initializer-clause are destroyed immediately; all others persist until the
end of the full-expression.

But we never implemented that, and continued treating individual element
initializations as full-expressions, such as in my patch for PR50866 in
r180442.  This blocked my attempted fix for PR66139, which extended the use
of split_nonconstant_init, and thus the bug, to aggregate initialization of
temporaries within an expression.

The longer temporary lifetime creates further EH region overlap problems
like the ones that wrap_temporary_cleanups addresses: in aggr7.C, we start
out with a normal nesting of

A1
 c.b1
   A2
    c.b2
     ...
   ~A2
~A1

where on the way in, throwing from one of the inits will clean up from the
previous inits.  But once c.b2 is initialized, throwing from ~A2 must not
clean up c.b1; instead it needs to clean up c.  So as in build_new_1, we
deal with this by guarding the B cleanups with flags that are cleared once c
is fully constructed; throwing from one of the ~A still hits that region,
but does not call ~B.  And then wrap_temporary_cleanups deals with calling
~C, but we need to tell it not to wrap the subobject cleanups.

The change from expressing the subobject cleanups with CLEANUP_STMT to
TARGET_EXPR was also necessary because we need them to collate with the ~A
in gimplify_cleanup_point_expr; the CLEANUP_STMT representation only worked
with treating subobject initializations as full-expressions.

PR c++/94041

gcc/cp/ChangeLog:

* decl.c (check_initializer): Remove obsolete comment.
(wrap_cleanups_r): Don't wrap CLEANUP_EH_ONLY.
(initialize_local_var): Change assert to test.
* typeck2.c (maybe_push_temp_cleanup): New.
(split_nonconstant_init_1): Use it.
(split_nonconstant_init): Clear cleanup flags.

gcc/testsuite/ChangeLog:

* g++.dg/init/aggr7-eh.C: New test.
* g++.dg/cpp0x/initlist122.C: Also test aggregate variable.
gcc/cp/decl.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/cpp0x/initlist122.C
gcc/testsuite/g++.dg/init/aggr7-eh.C [new file with mode: 0644]