https://gcc.gnu.org/g:3e4ca896baf1cd45ed922b645d1b8f8a7b9a0f21

commit r15-6264-g3e4ca896baf1cd45ed922b645d1b8f8a7b9a0f21
Author: Iain Sandoe <i...@sandoe.co.uk>
Date:   Thu Oct 3 09:02:59 2024 +0100

    c++, coroutines: Make the resume index consistent for debug.
    
    At present, we only update the resume index when we actually are
    at the stage that the coroutine is considered suspended. This is
    on the basis that it is UB to resume or destroy a coroutines that
    is not suspended (and therefore we never need to access this value
    otherwise).  However, it is possible that someone could set a debug
    breakpoint on the resume which can be reached without suspending
    if await_ready() returns true.  In that case, the debugger would
    read an incorrect resume index.  Fixed by moving the update to
    just before the test for ready.
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc (expand_one_await_expression): Update the
            resume index before checking if the coroutine is ready.
    
    Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>

Diff:
---
 gcc/cp/coroutines.cc | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 9214dfcc53ef..c286af7bd076 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2033,6 +2033,12 @@ expand_one_await_expression (tree *expr, tree 
*await_expr, void *d)
 
   /* Use the await_ready() call to test if we need to suspend.  */
   tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready().  */
+
+  /* We will resume (or continue) at the following index.  */
+  tree resume_idx = build_int_cst (short_unsigned_type_node, data->index);
+  tree r = cp_build_init_expr (data->resume_idx, resume_idx);
+  finish_expr_stmt (r);
+
   /* Convert to bool, if necessary.  */
   if (TREE_CODE (TREE_TYPE (ready_cond)) != BOOLEAN_TYPE)
     ready_cond = cp_convert (boolean_type_node, ready_cond,
@@ -2043,10 +2049,6 @@ expand_one_await_expression (tree *expr, tree 
*await_expr, void *d)
   ready_cond = invert_truthvalue_loc (loc, ready_cond);
   finish_if_stmt_cond (ready_cond, susp_if);
 
-  tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
-  tree r = cp_build_init_expr (data->resume_idx, susp_idx);
-  finish_expr_stmt (r);
-
   /* Find out what we have to do with the awaiter's suspend method.
      [expr.await]
      (5.1) If the result of await-ready is false, the coroutine is considered
@@ -2100,12 +2102,12 @@ expand_one_await_expression (tree *expr, tree 
*await_expr, void *d)
   tree cont = build_address (data->corocont);
   tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
 
-  susp_idx = build_int_cst (integer_type_node, data->index);
+  resume_idx = build_int_cst (integer_type_node, data->index);
 
   tree sw = begin_switch_stmt ();
 
   r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
-                                   susp_idx, final_susp, r_l, d_l,
+                                   resume_idx, final_susp, r_l, d_l,
                                    data->coro_fp);
   finish_switch_cond (r, sw);
   finish_case_label (loc, integer_zero_node, NULL_TREE); /*  case 0: */

Reply via email to