On 5/13/25 10:30 AM, Iain Sandoe wrote:
This replaces the cleanup try-catch block in the ramp with a series of
eh-only cleanup statements.
gcc/cp/ChangeLog:
* coroutines.cc
(cp_coroutine_transform::build_ramp_function): Replace ramp
cleanup try-catch block with eh-only cleanup statements.
Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
---
gcc/cp/coroutines.cc | 207 +++++++++++++++----------------------------
1 file changed, 69 insertions(+), 138 deletions(-)
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index ce3e022a516..299e36fd3c2 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4866,39 +4866,6 @@ cp_coroutine_transform::build_ramp_function ()
coro_fp = pushdecl (coro_fp);
add_decl_expr (coro_fp);
- tree coro_promise_live = NULL_TREE;
- if (flag_exceptions)
- {
- /* Signal that we need to clean up the promise object on exception. */
- coro_promise_live
- = coro_build_and_push_artificial_var (loc, "_Coro_promise_live",
- boolean_type_node, orig_fn_decl,
- boolean_false_node);
-
- /* To signal that we need to cleanup copied function args. */
- if (DECL_ARGUMENTS (orig_fn_decl))
- for (tree arg = DECL_ARGUMENTS (orig_fn_decl); arg != NULL;
- arg = DECL_CHAIN (arg))
- {
- param_info *parm_i = param_uses.get (arg);
- if (parm_i->trivial_dtor)
- continue;
- parm_i->guard_var = pushdecl (parm_i->guard_var);
- add_decl_expr (parm_i->guard_var);
- }
- }
-
- /* deref the frame pointer, to use in member access code. */
- tree deref_fp
- = cp_build_indirect_ref (loc, coro_fp, RO_UNARY_STAR,
- tf_warning_or_error);
- tree frame_needs_free
- = coro_build_and_push_artificial_var_with_dve (loc,
- coro_frame_needs_free_id,
- boolean_type_node,
- orig_fn_decl, NULL_TREE,
- deref_fp);
-
/* Build the frame. */
/* The CO_FRAME internal function is a mechanism to allow the middle end
@@ -4942,25 +4909,24 @@ cp_coroutine_transform::build_ramp_function ()
finish_if_stmt (if_stmt);
}
+ /* deref the frame pointer, to use in member access code. */
+ tree deref_fp
+ = cp_build_indirect_ref (loc, coro_fp, RO_UNARY_STAR,
+ tf_warning_or_error);
+
/* For now, once allocation has succeeded we always assume that this needs
destruction, there's no impl. for frame allocation elision. */
- r = cp_build_init_expr (frame_needs_free, boolean_true_node);
- finish_expr_stmt (r);
-
- /* Set up the promise. */
- tree p
- = coro_build_and_push_artificial_var_with_dve (loc, coro_promise_id,
- promise_type, orig_fn_decl,
- NULL_TREE, deref_fp);
+ tree frame_needs_free
+ = coro_build_and_push_artificial_var_with_dve (loc,
+ coro_frame_needs_free_id,
+ boolean_type_node,
+ orig_fn_decl,
+ boolean_true_node,
+ deref_fp);
+ /* Although it appears to be unused here the frame entry is needed and we
+ just set it true. */
+ TREE_USED (frame_needs_free) = true;
- /* Up to now any exception thrown will propagate directly to the caller.
- This is OK since the only source of such exceptions would be in allocation
- of the coroutine frame, and therefore the ramp will not have initialized
- any further state. From here, we will track state that needs explicit
- destruction in the case that promise or g.r.o setup fails or an exception
- is thrown from the initial suspend expression. */
- tree ramp_try_block = NULL_TREE;
- tree ramp_try_stmts = NULL_TREE;
tree iarc_x = NULL_TREE;
tree coro_before_return = NULL_TREE;
if (flag_exceptions)
@@ -4976,8 +4942,17 @@ cp_coroutine_transform::build_ramp_function ()
orig_fn_decl,
boolean_false_node,
deref_fp);
- ramp_try_block = begin_try_block ();
- ramp_try_stmts = begin_compound_stmt (BCS_TRY_BLOCK);
+ tree frame_cleanup = push_stmt_list ();
+ tree do_fr_cleanup
+ = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, iarc_x);
+ do_fr_cleanup = build2_loc (loc, TRUTH_AND_EXPR, boolean_type_node,
+ do_fr_cleanup, coro_before_return);
This also needs reversing (and similarly below).
+ tree fr_cleanup_if = begin_if_stmt ();
+ finish_if_stmt_cond (do_fr_cleanup, fr_cleanup_if);
+ finish_expr_stmt (delete_frame_call);
+ finish_then_clause (fr_cleanup_if);
+ finish_if_stmt (fr_cleanup_if);
You could build a COND_EXPR instead of taking several statements to
build an IF_STMT? i.e.
frame_cleanup = build3 (COND_EXPR, void_type_node, fr_cleanup_if,
delete_frame_call, void_node);
Jason