Skip to content

Commit 44868e7

Browse files
committed
c++: co_await and initializer_list [PR109227]
Here we end up with an initializer_list of 'aa', a type with a non-trivial destructor, and need to destroy it. The code called build_special_member_call for cleanups, but that doesn't work for arrays, so use cxx_maybe_build_cleanup instead. Let's go ahead and do that everywhere that has been calling the destructor directly. PR c++/109227 gcc/cp/ChangeLog: * coroutines.cc (build_co_await): Use cxx_maybe_build_cleanup. (build_actor_fn, process_conditional, maybe_promote_temps) (morph_fn_to_coro): Likewise. (expand_one_await_expression): Use build_cleanup. gcc/testsuite/ChangeLog: * g++.dg/coroutines/co-await-initlist2.C: New test.
1 parent f03b8f5 commit 44868e7

2 files changed

Lines changed: 67 additions & 80 deletions

File tree

gcc/cp/coroutines.cc

Lines changed: 38 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -932,19 +932,14 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
932932

933933
/* We now know that the final suspend object is distinct from the
934934
final awaiter, so check for a non-throwing DTOR where needed. */
935-
tree a_type = TREE_TYPE (a);
936-
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
937-
if (tree dummy
938-
= build_special_member_call (a, complete_dtor_identifier,
939-
NULL, a_type, LOOKUP_NORMAL,
940-
tf_none))
941-
{
942-
if (CONVERT_EXPR_P (dummy))
943-
dummy = TREE_OPERAND (dummy, 0);
944-
dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
945-
if (coro_diagnose_throwing_fn (dummy))
946-
return error_mark_node;
947-
}
935+
if (tree dummy = cxx_maybe_build_cleanup (a, tf_none))
936+
{
937+
if (CONVERT_EXPR_P (dummy))
938+
dummy = TREE_OPERAND (dummy, 0);
939+
dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
940+
if (coro_diagnose_throwing_fn (dummy))
941+
return error_mark_node;
942+
}
948943
}
949944
}
950945
else
@@ -1096,18 +1091,14 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
10961091
return error_mark_node;
10971092
if (coro_diagnose_throwing_fn (awrs_func))
10981093
return error_mark_node;
1099-
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
1100-
if (tree dummy
1101-
= build_special_member_call (e_proxy, complete_dtor_identifier,
1102-
NULL, o_type, LOOKUP_NORMAL,
1103-
tf_none))
1104-
{
1105-
if (CONVERT_EXPR_P (dummy))
1106-
dummy = TREE_OPERAND (dummy, 0);
1107-
dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1108-
if (coro_diagnose_throwing_fn (dummy))
1109-
return error_mark_node;
1110-
}
1094+
if (tree dummy = cxx_maybe_build_cleanup (e_proxy, tf_none))
1095+
{
1096+
if (CONVERT_EXPR_P (dummy))
1097+
dummy = TREE_OPERAND (dummy, 0);
1098+
dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1099+
if (coro_diagnose_throwing_fn (dummy))
1100+
return error_mark_node;
1101+
}
11111102
}
11121103

11131104
/* We now have three call expressions, in terms of the promise, handle and
@@ -1662,7 +1653,6 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
16621653
tree resume_label = create_named_label_with_ctx (loc, buf, actor);
16631654
tree empty_list = build_empty_stmt (loc);
16641655

1665-
tree await_type = TREE_TYPE (var);
16661656
tree stmt_list = NULL;
16671657
tree r;
16681658
tree *await_init = NULL;
@@ -1791,9 +1781,7 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
17911781
append_to_statement_list (destroy_label, &body_list);
17921782
if (needs_dtor)
17931783
{
1794-
tree dtor = build_special_member_call (var, complete_dtor_identifier,
1795-
NULL, await_type, LOOKUP_NORMAL,
1796-
tf_warning_or_error);
1784+
tree dtor = build_cleanup (var);
17971785
append_to_statement_list (dtor, &body_list);
17981786
}
17991787
r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
@@ -1821,9 +1809,7 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
18211809
tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
18221810
if (needs_dtor)
18231811
{
1824-
tree dtor = build_special_member_call (var, complete_dtor_identifier,
1825-
NULL, await_type, LOOKUP_NORMAL,
1826-
tf_warning_or_error);
1812+
tree dtor = build_cleanup (var);
18271813
append_to_statement_list (dtor, &stmt_list);
18281814
}
18291815
data->index += 2;
@@ -2330,10 +2316,8 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
23302316
add_stmt (r);
23312317

23322318
/* Destructors for the things we built explicitly. */
2333-
r = build_special_member_call (promise_proxy, complete_dtor_identifier, NULL,
2334-
promise_type, LOOKUP_NORMAL,
2335-
tf_warning_or_error);
2336-
add_stmt (r);
2319+
if (tree c = cxx_maybe_build_cleanup (promise_proxy, tf_warning_or_error))
2320+
add_stmt (c);
23372321

23382322
tree del_frame_label
23392323
= create_named_label_with_ctx (loc, "coro.delete.frame", actor);
@@ -2362,12 +2346,8 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
23622346
= lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
23632347
tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
23642348
false, tf_warning_or_error);
2365-
tree t = TREE_TYPE (a);
2366-
tree dtor;
2367-
dtor
2368-
= build_special_member_call (a, complete_dtor_identifier, NULL, t,
2369-
LOOKUP_NORMAL, tf_warning_or_error);
2370-
add_stmt (dtor);
2349+
if (tree dtor = cxx_maybe_build_cleanup (a, tf_warning_or_error))
2350+
add_stmt (dtor);
23712351
}
23722352
}
23732353

@@ -3045,16 +3025,14 @@ process_conditional (var_nest_node *n, tree& vlist)
30453025
tree *flag = var_flags.get (var);
30463026
if (!flag)
30473027
continue;
3048-
tree var_type = TREE_TYPE (var);
3049-
tree cleanup
3050-
= build_special_member_call (var, complete_dtor_identifier,
3051-
NULL, var_type, LOOKUP_NORMAL,
3052-
tf_warning_or_error);
3053-
tree cond_cleanup = begin_if_stmt ();
3054-
finish_if_stmt_cond (*flag, cond_cleanup);
3055-
finish_expr_stmt (cleanup);
3056-
finish_then_clause (cond_cleanup);
3057-
finish_if_stmt (cond_cleanup);
3028+
if (tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error))
3029+
{
3030+
tree cond_cleanup = begin_if_stmt ();
3031+
finish_if_stmt_cond (*flag, cond_cleanup);
3032+
finish_expr_stmt (cleanup);
3033+
finish_then_clause (cond_cleanup);
3034+
finish_if_stmt (cond_cleanup);
3035+
}
30583036
}
30593037
final_actions = pop_stmt_list (final_actions);
30603038
tree try_finally
@@ -3135,13 +3113,8 @@ maybe_promote_temps (tree *stmt, void *d)
31353113
process_conditional (t, vlist);
31363114
else
31373115
finish_expr_stmt (t->init);
3138-
tree var_type = TREE_TYPE (var);
3139-
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3116+
if (tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error))
31403117
{
3141-
tree cleanup
3142-
= build_special_member_call (var, complete_dtor_identifier,
3143-
NULL, var_type, LOOKUP_NORMAL,
3144-
tf_warning_or_error);
31453118
tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
31463119
add_stmt (cl); /* push this onto the level above. */
31473120
}
@@ -4903,10 +4876,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
49034876
vec_safe_push (param_dtor_list, parm.field_id);
49044877
/* Cleanup this frame copy on exception. */
49054878
parm.fr_copy_dtor
4906-
= build_special_member_call (fld_idx, complete_dtor_identifier,
4907-
NULL, parm.frame_type,
4908-
LOOKUP_NORMAL,
4909-
tf_warning_or_error);
4879+
= cxx_maybe_build_cleanup (fld_idx, tf_warning_or_error);
49104880
if (flag_exceptions)
49114881
{
49124882
/* This var is now live. */
@@ -4961,10 +4931,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
49614931
boolean_type_node);
49624932
finish_expr_stmt (r);
49634933

4964-
promise_dtor
4965-
= build_special_member_call (p, complete_dtor_identifier,
4966-
NULL, promise_type, LOOKUP_NORMAL,
4967-
tf_warning_or_error);
4934+
promise_dtor = cxx_maybe_build_cleanup (p, tf_warning_or_error);
49684935
}
49694936

49704937
/* Set up a new bind context for the GRO. */
@@ -5025,11 +4992,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
50254992
/* If some part of the initalization code (prior to the await_resume
50264993
of the initial suspend expression), then we need to clean up the
50274994
return value. */
5028-
gro_ret_dtor
5029-
= build_special_member_call (DECL_RESULT (orig),
5030-
complete_dtor_identifier, NULL,
5031-
gro_type, LOOKUP_NORMAL,
5032-
tf_warning_or_error);
4995+
gro_ret_dtor = cxx_maybe_build_cleanup (DECL_RESULT (orig),
4996+
tf_warning_or_error);
50334997
}
50344998
else
50354999
{
@@ -5042,15 +5006,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
50425006
r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
50435007
tf_warning_or_error);
50445008
/* The constructed object might require a cleanup. */
5045-
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5046-
{
5047-
gro_cleanup_stmt
5048-
= build_special_member_call (gro, complete_dtor_identifier,
5049-
NULL, gro_type, LOOKUP_NORMAL,
5050-
tf_warning_or_error);
5051-
gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
5052-
gro_cleanup_stmt, gro);
5053-
}
5009+
if (tree cleanup = cxx_maybe_build_cleanup (gro, tf_warning_or_error))
5010+
gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
5011+
cleanup, gro);
50545012
}
50555013
finish_expr_stmt (r);
50565014

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// PR c++/109227
2+
// { dg-do compile { target c++20 } }
3+
4+
#include <initializer_list>
5+
#include <coroutine>
6+
7+
struct awaitable {
8+
bool await_ready();
9+
void await_suspend(std::coroutine_handle<> h);
10+
void await_resume();
11+
};
12+
awaitable async_new_session(int capabilities);
13+
struct aa { ~aa(); };
14+
aa f(void);
15+
struct Capabilities {
16+
Capabilities(std::initializer_list<aa> __l);
17+
};
18+
int g(Capabilities);
19+
struct task {
20+
struct promise_type {
21+
std::suspend_never initial_suspend();
22+
std::suspend_never final_suspend() noexcept;
23+
void unhandled_exception();
24+
task get_return_object() noexcept;
25+
};
26+
};
27+
task make() {
28+
co_await async_new_session(g({aa()}));
29+
}

0 commit comments

Comments
 (0)