Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/decl_inits.c
Original file line number Diff line number Diff line change
Expand Up @@ -4704,12 +4704,17 @@ initializer, already copied and substituted.
a_routine_ptr dtor_rp = NULL;
a_boolean need_to_free_icp_tree = FALSE;
a_boolean saved_reduce_backing_expression_use;
an_expr_stack_entry expr_stack_entry, *saved_expr_stack;
a_boolean full_expression;

check_assertion(rescan_aggr != NULL || curr_token == tok_lbrace ||
(dps != NULL &&
anything_cached(&dps->prescanned_initializer_cache)));
saved_reduce_backing_expression_use = reduce_backing_expression_use;
dtype = skip_typerefs(dtype);
full_expression = !C_mode() && is->elements_are_full_expressions &&
is_aggregate_type(dtype) &&
!(dps != NULL && dps->is_struct_binding_decl);
if (rescan_aggr != NULL) {
/* Rescan. The {...} is provided by the caller in init-component form. */
icp_tree = rescan_aggr;
Expand All @@ -4728,6 +4733,12 @@ initializer, already copied and substituted.
} /* if */
icp = icp_tree;
check_assertion(icp != NULL && is_braced_init_component(icp));
if (full_expression) {
/* All elements share the lifetime of the complete initialization. */
push_expr_stack_for_initializer(&expr_stack_entry, &saved_expr_stack,
ek_normal,
/*is_full_expr=*/TRUE, dps, is);
} /* if */
is_var_init = dps != NULL && dps->sym != NULL &&
variable_for_symbol(dps->sym) != NULL;
/* The force_dynamic_init flag only applies to the top-level result. */
Expand Down Expand Up @@ -4933,6 +4944,17 @@ initializer, already copied and substituted.
} /* if */
is->no_diagnostics = saved_no_diagnostics;
reduce_backing_expression_use = saved_reduce_backing_expression_use;
if (full_expression) {
if (is->init_dip != NULL) {
wrap_up_dynamic_init_full_expression(is->init_dip);
} else if (is->init_error) {
discard_curr_expr_object_lifetime();
} else if (is->init_con != NULL) {
wrap_up_constant_full_expression(is->init_con);
} /* if */
pop_expr_stack_for_initializer(saved_expr_stack,
/*is_full_expr=*/TRUE, dps, is);
} /* if */
} /* braced_initializer */


Expand Down
3 changes: 3 additions & 0 deletions src/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -48016,11 +48016,13 @@ free the components prior to prev_icp.
an_expr_stack_entry *saved_expr_stack;
an_expr_stack_entry expr_stack_entry;
an_object_lifetime *saved_object_lifetime = curr_object_lifetime;
a_boolean saved_full_expressions;

check_assertion(is_continuation_elem(prev_icp->next));
continuation = prev_icp->next->variant.continuation.state;
dps = continuation->decl_parse_state;
check_assertion(dps != NULL && dps->init_state.pending_elements);
saved_full_expressions = dps->init_state.elements_are_full_expressions;
if (continuation->resumable) {
/* Free most init components preceding prev_icp, but keep the first one in
case it is useful for diagnostic purposes. */
Expand Down Expand Up @@ -48055,6 +48057,7 @@ free the components prior to prev_icp.
/*bundle=*/TRUE, &continuation);
pop_expr_stack_for_initializer(saved_expr_stack, /*is_full_expr=*/TRUE,
dps, (an_init_state *)NULL);
dps->init_state.elements_are_full_expressions = saved_full_expressions;
if (continuation != NULL) {
/* Parsing was suspended again. Record additional state information to
enable a subsequent call to this function. */
Expand Down
2 changes: 2 additions & 0 deletions src/lower_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -11048,6 +11048,8 @@ do_assignment:;
/* coverity[uninit_use] */
if ((dip->kind == (a_dynamic_init_kind)dik_nonconstant_aggregate ||
dip->kind == (a_dynamic_init_kind)dik_lambda) &&
/* Inner partial cleanups are handled by add_dyn_init_cleanup. */
!dip->overlaps_temps_in_inner_lifetime &&

@daniel-petrovic daniel-petrovic Nov 4, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because of this it probably makes sense to add test for aggregate members with non-trivial destructors and member evaluations that throws exception mid-way through initialization

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added regressions/edg-29057-eh. It has members with nontrivial destructors, a nested aggregate, and exceptions thrown both during the initialization and after it, and it counts the constructions and destructions in each case. It passes in both x86_64 configurations.

latest_initialization_on_entry !=
eff_context->latest_initialization) {
/* This is an aggregate for which some partial-aggregate
Expand Down
14 changes: 14 additions & 0 deletions src/pending_changes/edg-29057-aggregate-temporary-lifetime.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[GH #458]
Lifetime of temporaries in aggregate initialization

In C++, a temporary created in the initializer of an element of an aggregate
was destroyed at the end of that element's initialization, instead of at the
end of the full-expression containing the complete initialization. It is now
destroyed when the initialization of the whole aggregate is complete,
including for nested aggregate initializers. For example:

struct Temp { Temp(); ~Temp(); };
struct A { A(const Temp&); };
struct Pair { A a; int b; };
int f();
Pair p{A(Temp{}), f()}; // The Temp is now still alive when f is called.
3 changes: 0 additions & 3 deletions tests/expectations/edg_x86_64/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -6647,7 +6647,6 @@ gnu/cpp/cpp0x/initlist-opt2.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist-ref1.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist-ref3.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist-value4.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist122.sft.cpp:rp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist13.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist36.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/cpp0x/initlist55.sft.cpp:s:-DTEST_NUMBER=1 --c++11 -W:SKIPPED:
Expand Down Expand Up @@ -7725,10 +7724,8 @@ gnu/cpp/inherit/pr97268.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/inherit/using4.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/addr-const1.sft.cpp:rp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/aggr4.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/init/aggr7-eh.sft.cpp:rp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/aggr7-eh2.sft.cpp:rp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/aggr7-eh3.sft.cpp:rp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/array12.sft.cpp:rp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/array44.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/brace4.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/init/copy3.sft.cpp:rp:-DTEST_NUMBER=1 --c++14:FAIL:
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/cwg/.cwg3100.rto/default.1.2.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
./a.out
~DTemp
~A
~A
~BTemp
~DTemp
~BTemp
Original file line number Diff line number Diff line change
Expand Up @@ -135,80 +135,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
check(t.x, " T", 0);
^

"test_passed.cpp", line 4301: error: static assertion failed with ""
static_assert(b.a.n == 4300, "");
^
"test_passed.cpp", line 4301: note: the final comparison was 4201 == 4300
static_assert(b.a.n == 4300, "");
^

"test_passed.cpp", line 4302: error: static assertion failed with ""
static_assert(b.a.n2 == 4300, "");
^
"test_passed.cpp", line 4302: note: the final comparison was 4201 == 4300
static_assert(b.a.n2 == 4300, "");
^

"test_passed.cpp", line 4303: error: static assertion failed with ""
static_assert(b.a.info.line() == 4300, "");
^
"test_passed.cpp", line 4303: note: the final comparison was 4201 == 4300
static_assert(b.a.info.line() == 4300, "");
^

"test_passed.cpp", line 4304: error: static assertion failed
static_assert(is_equal(b.a.f, "test_passed.cpp"));
^

"test_passed.cpp", line 4305: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_passed.cpp"));
^

"test_passed.cpp", line 4306: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_passed.cpp"));
^

"test_func_passed.cpp", line 4401: error: static assertion failed with ""
static_assert(b.a.n == 4400, "");
^
"test_func_passed.cpp", line 4401: note: the final comparison was 4201 == 4400
static_assert(b.a.n == 4400, "");
^

"test_func_passed.cpp", line 4402: error: static assertion failed with ""
static_assert(b.a.n2 == 4400, "");
^
"test_func_passed.cpp", line 4402: note: the final comparison was 4201 == 4400
static_assert(b.a.n2 == 4400, "");
^

"test_func_passed.cpp", line 4403: error: static assertion failed with ""
static_assert(b.a.info.line() == 4400, "");
^
"test_func_passed.cpp", line 4403: note: the final comparison was 4201 == 4400
static_assert(b.a.info.line() == 4400, "");
^

"test_func_passed.cpp", line 4404: error: static assertion failed
static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4405: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4406: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4407: error: static assertion failed
static_assert(is_equal(b.a.func, "test_in_func"));
^

"test_func_passed.cpp", line 4408: error: static assertion failed
static_assert(is_equal(b.a.func2, "test_in_func"));
^

"test_func_passed.cpp", line 4409: error: static assertion failed
static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
^
Expand Down Expand Up @@ -239,4 +165,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
^
detected during instantiation of "Pair<U, U> test_func::test_func_template(T, U) [with T=int, U=SL]" at line 361

39 errors detected in the compilation of "Test_name.c".
25 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -145,80 +145,6 @@ fe_only -DTEST_NUMBER=10 --clang -tused -e 200 --no_wrap_diagnostics --clang_ver
check(t.x, " T", 0);
^

"test_passed.cpp", line 4301: error: static assertion failed with ""
static_assert(b.a.n == 4300, "");
^
"test_passed.cpp", line 4301: note: the final comparison was 4201 == 4300
static_assert(b.a.n == 4300, "");
^

"test_passed.cpp", line 4302: error: static assertion failed with ""
static_assert(b.a.n2 == 4300, "");
^
"test_passed.cpp", line 4302: note: the final comparison was 4201 == 4300
static_assert(b.a.n2 == 4300, "");
^

"test_passed.cpp", line 4303: error: static assertion failed with ""
static_assert(b.a.info.line() == 4300, "");
^
"test_passed.cpp", line 4303: note: the final comparison was 4201 == 4300
static_assert(b.a.info.line() == 4300, "");
^

"test_passed.cpp", line 4304: error: static assertion failed
static_assert(is_equal(b.a.f, "test_passed.cpp"));
^

"test_passed.cpp", line 4305: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_passed.cpp"));
^

"test_passed.cpp", line 4306: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_passed.cpp"));
^

"test_func_passed.cpp", line 4401: error: static assertion failed with ""
static_assert(b.a.n == 4400, "");
^
"test_func_passed.cpp", line 4401: note: the final comparison was 4201 == 4400
static_assert(b.a.n == 4400, "");
^

"test_func_passed.cpp", line 4402: error: static assertion failed with ""
static_assert(b.a.n2 == 4400, "");
^
"test_func_passed.cpp", line 4402: note: the final comparison was 4201 == 4400
static_assert(b.a.n2 == 4400, "");
^

"test_func_passed.cpp", line 4403: error: static assertion failed with ""
static_assert(b.a.info.line() == 4400, "");
^
"test_func_passed.cpp", line 4403: note: the final comparison was 4201 == 4400
static_assert(b.a.info.line() == 4400, "");
^

"test_func_passed.cpp", line 4404: error: static assertion failed
static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4405: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4406: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4407: error: static assertion failed
static_assert(is_equal(b.a.func, "test_in_func"));
^

"test_func_passed.cpp", line 4408: error: static assertion failed
static_assert(is_equal(b.a.func2, "test_in_func"));
^

"test_func_passed.cpp", line 4409: error: static assertion failed
static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
^
Expand Down Expand Up @@ -286,4 +212,4 @@ fe_only -DTEST_NUMBER=10 --clang -tused -e 200 --no_wrap_diagnostics --clang_ver
^
detected during instantiation of "void test_func::inner::C<Ty>::df<T>(double) [with Ty=test_func::A, T=void]" at line 496

47 errors detected in the compilation of "Test_name.c".
33 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -135,80 +135,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
check(t.x, " T", 0);
^

"test_passed.cpp", line 4301: error: static assertion failed with ""
static_assert(b.a.n == 4300, "");
^
"test_passed.cpp", line 4301: note: the final comparison was 4201 == 4300
static_assert(b.a.n == 4300, "");
^

"test_passed.cpp", line 4302: error: static assertion failed with ""
static_assert(b.a.n2 == 4300, "");
^
"test_passed.cpp", line 4302: note: the final comparison was 4201 == 4300
static_assert(b.a.n2 == 4300, "");
^

"test_passed.cpp", line 4303: error: static assertion failed with ""
static_assert(b.a.info.line() == 4300, "");
^
"test_passed.cpp", line 4303: note: the final comparison was 4201 == 4300
static_assert(b.a.info.line() == 4300, "");
^

"test_passed.cpp", line 4304: error: static assertion failed
static_assert(is_equal(b.a.f, "test_passed.cpp"));
^

"test_passed.cpp", line 4305: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_passed.cpp"));
^

"test_passed.cpp", line 4306: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_passed.cpp"));
^

"test_func_passed.cpp", line 4401: error: static assertion failed with ""
static_assert(b.a.n == 4400, "");
^
"test_func_passed.cpp", line 4401: note: the final comparison was 4201 == 4400
static_assert(b.a.n == 4400, "");
^

"test_func_passed.cpp", line 4402: error: static assertion failed with ""
static_assert(b.a.n2 == 4400, "");
^
"test_func_passed.cpp", line 4402: note: the final comparison was 4201 == 4400
static_assert(b.a.n2 == 4400, "");
^

"test_func_passed.cpp", line 4403: error: static assertion failed with ""
static_assert(b.a.info.line() == 4400, "");
^
"test_func_passed.cpp", line 4403: note: the final comparison was 4201 == 4400
static_assert(b.a.info.line() == 4400, "");
^

"test_func_passed.cpp", line 4404: error: static assertion failed
static_assert(is_equal(b.a.f, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4405: error: static assertion failed
static_assert(is_equal(b.a.f2, "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4406: error: static assertion failed
static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp"));
^

"test_func_passed.cpp", line 4407: error: static assertion failed
static_assert(is_equal(b.a.func, "test_in_func"));
^

"test_func_passed.cpp", line 4408: error: static assertion failed
static_assert(is_equal(b.a.func2, "test_in_func"));
^

"test_func_passed.cpp", line 4409: error: static assertion failed
static_assert(is_equal(b.a.info.function(), "bool test_out_of_line_init::test_in_func()"));
^
Expand Down Expand Up @@ -239,4 +165,4 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
^
detected during instantiation of "Pair<U, U> test_func::test_func_template(T, U) [with T=int, U=SL]" at line 361

39 errors detected in the compilation of "Test_name.c".
25 errors detected in the compilation of "Test_name.c".
Loading
Loading