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 @@ -47957,11 +47957,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 @@ -47996,6 +47998,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 @@ -11022,6 +11022,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 &&
latest_initialization_on_entry !=
eff_context->latest_initialization) {
/* This is an aggregate for which some partial-aggregate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[GH #458]
Preserve aggregate initializer temporary lifetimes

Temporaries created while initializing an aggregate now remain alive until
the complete initialization ends, including nested aggregate initializers.
21 changes: 21 additions & 0 deletions tests/tests/regressions/edg-29057.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//type:rp
//options_all:--c++20
//options:--g++ --gnu_version=130300:--strict
int live, fails;
struct Temp { Temp() { ++live; } ~Temp() { --live; } };
struct A { A(const Temp&) {} };
struct Pair { A a; int b; };
int check(int expected) { fails += live != expected; return 0; }
Pair make_pair() { return {A(Temp{}), check(1)}; }
int main() {
Pair p{A(Temp{}), check(1)};
check(0);
Pair q = make_pair();
check(0);
Pair a[2]{{A(Temp{}), check(1)}, {A(Temp{}), check(2)}};
check(0);
struct Nested { Pair p; int c; } n{{A(Temp{}), check(1)}, check(1)};
check(0);
(void)p; (void)q; (void)a; (void)n;
return fails;
}