Updated. I realised we no longer need to refer to
initial_await_resume_called in the ramp at all, v2 removes the setting
of the variable from there and puts it into the start of the actor.
Tested on x86_64-darwin and powerp64le-linux.
Confirmed that the sanitizer test in PR 118074 is fixed but we already
have a suitable testcase in PR 115908 which has now been moved to the
'torture' sub-directory to get wider code-gen coverage.
OK for trunk?
thanks
Iain
--- 8< ---
This implements the final piece of the revised CWG2563 wording;
"It exits the scope of promise only if the coroutine completed
without suspending."
The change removes the need to track whether we have reached the ramp
return. We can now assume that the coroutine frame is valid when
constructing the ramp return value. The ramp function no longer needs
to check initial_await_resume_called, and the references to that can
be made local to the resumer.
The cleanups for promise, arg copies and frame are now adjusted to
depend only on whether a suspend has occurred.
PR c++/115908
PR c++/118074
gcc/cp/ChangeLog:
* coroutines.cc: New GTY coro_ramp_cleanup_id.
(coro_init_identifiers): Initialize coro_ramp_cleanup_id.
(build_actor_fn): Set coro_ramp_cleanup_id false when we
exit via a suspend or continuation return. Do not clean
up if we pass the final await expression without suspending.
(cp_coroutine_transform::wrap_original_function_body):
Declare _Coro_ramp_cleanup.
(cp_coroutine_transform::build_ramp_function): Amend
cleanups to use coro_ramp_cleanup and set that to be true
on init. Remove the use of _Coro_befoe_return.
gcc/testsuite/ChangeLog:
* g++.dg/coroutines/pr115908.C: Move to...
* g++.dg/coroutines/torture/pr115908.C: ...here.
Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
---
gcc/cp/coroutines.cc | 121 +++++++++---------
.../coroutines/{ => torture}/pr115908.C | 9 +-
2 files changed, 60 insertions(+), 70 deletions(-)
rename gcc/testsuite/g++.dg/coroutines/{ => torture}/pr115908.C (88%)
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index a2b6d53805a..42f719ddde1 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -348,6 +348,7 @@ static GTY(()) tree coro_resume_index_id;
static GTY(()) tree coro_self_handle_id;
static GTY(()) tree coro_actor_continue_id;
static GTY(()) tree coro_frame_i_a_r_c_id;
+static GTY(()) tree coro_ramp_cleanup_id;
/* Create the identifiers used by the coroutines library interfaces and
the implementation frame state. */
@@ -385,6 +386,7 @@ coro_init_identifiers ()
coro_resume_index_id = get_identifier ("_Coro_resume_index");
coro_self_handle_id = get_identifier ("_Coro_self_handle");
coro_actor_continue_id = get_identifier ("_Coro_actor_continue");
+ coro_ramp_cleanup_id = get_identifier ("_Coro_ramp_should_cleanup");
}
/* Trees we only need to set up once. */
@@ -2568,6 +2570,17 @@ build_actor_fn (location_t loc, tree coro_frame_type,
tree actor, tree fnbody,
/* Now we start building the rewritten function body. */
add_stmt (build_stmt (loc, LABEL_EXPR, actor_begin_label));
+ tree i_a_r_c = NULL_TREE;
+ if (flag_exceptions)
+ {
+ i_a_r_c
+ = coro_build_frame_access_expr (actor_frame, coro_frame_i_a_r_c_id,
+ false, tf_warning_or_error);
+ tree m = cp_build_modify_expr (loc, i_a_r_c, NOP_EXPR,
+ boolean_false_node, tf_warning_or_error);
+ finish_expr_stmt (m);
+ }
+
/* actor's coroutine 'self handle'. */
tree ash = coro_build_frame_access_expr (actor_frame, coro_self_handle_id,
false, tf_warning_or_error);
@@ -2597,6 +2610,16 @@ build_actor_fn (location_t loc, tree coro_frame_type,
tree actor, tree fnbody,
/* Add in our function body with the co_returns rewritten to final form. */
add_stmt (fnbody);
+ /* If we reach here without suspending, then the ramp should cleanup. */
+ tree ramp_should_cleanup
+ = coro_build_frame_access_expr (actor_frame, coro_ramp_cleanup_id,
+ false, tf_warning_or_error);
+ tree ramp_cu_if = begin_if_stmt ();
+ finish_if_stmt_cond (ramp_should_cleanup, ramp_cu_if);
+ finish_return_stmt (NULL_TREE);
+ finish_then_clause (ramp_cu_if);
+ finish_if_stmt (ramp_cu_if);
+
/* Now do the tail of the function; first cleanups. */
r = build_stmt (loc, LABEL_EXPR, del_promise_label);
add_stmt (r);
@@ -2638,6 +2661,9 @@ build_actor_fn (location_t loc, tree coro_frame_type,
tree actor, tree fnbody,
/* This is the suspend return point. */
add_stmt (build_stmt (loc, LABEL_EXPR, ret_label));
+ r = cp_build_modify_expr (loc, ramp_should_cleanup, NOP_EXPR,
+ boolean_false_node, tf_warning_or_error);
+ finish_expr_stmt (r);
finish_return_stmt (NULL_TREE);
/* This is the 'continuation' return point. For such a case we have a
coro
@@ -2645,6 +2671,10 @@ build_actor_fn (location_t loc, tree coro_frame_type,
tree actor, tree fnbody,
execute as a tailcall allowing arbitrary chaining of coroutines. */
add_stmt (build_stmt (loc, LABEL_EXPR, continue_label));
+ r = cp_build_modify_expr (loc, ramp_should_cleanup, NOP_EXPR,
+ boolean_false_node, tf_warning_or_error);
+ finish_expr_stmt (r);