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

Reply via email to