https://gcc.gnu.org/g:977fadd69776e2a8a6daca43e1c898bc4f87154d

commit r16-969-g977fadd69776e2a8a6daca43e1c898bc4f87154d
Author: Iain Sandoe <i...@sandoe.co.uk>
Date:   Thu May 29 15:45:29 2025 +0100

    c++, coroutines: Make a check more specific [PR109283].
    
    The check was intended to assert that we had visited contained
    ternary expressions with embedded co_awaits, but had been made
    too general - and therefore was ICEing on code that was actually
    OK.  Fixed by checking specifically that no co_awaits embedded.
    
            PR c++/109283
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc (find_any_await): Only save the statement
            pointer if the caller passes a place for it.
            (flatten_await_stmt): When checking that ternary expressions
            have been handled, also check that they contain a co_await.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/pr109283.C: New test.
    
    Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>

Diff:
---
 gcc/cp/coroutines.cc                       |  8 +++++---
 gcc/testsuite/g++.dg/coroutines/pr109283.C | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 64a0a344349e..5815a8cef2c4 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2865,8 +2865,8 @@ find_any_await (tree *stmt, int *dosub, void *d)
   if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
     {
       *dosub = 0; /* We don't need to consider this any further.  */
-      tree **p = (tree **) d;
-      *p = stmt;
+      if (d)
+       *(tree **)d = stmt;
       return *stmt;
     }
   return NULL_TREE;
@@ -3116,7 +3116,9 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> 
*promoted,
          bool already_present = promoted->add (var);
          gcc_checking_assert (!already_present);
          tree inner = TARGET_EXPR_INITIAL (init);
-         gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
+         gcc_checking_assert
+           (TREE_CODE (inner) != COND_EXPR
+            || !cp_walk_tree (&inner, find_any_await, nullptr, nullptr));
          init = cp_build_modify_expr (input_location, var, INIT_EXPR, init,
                                       tf_warning_or_error);
          /* Simplify for the case that we have an init containing the temp
diff --git a/gcc/testsuite/g++.dg/coroutines/pr109283.C 
b/gcc/testsuite/g++.dg/coroutines/pr109283.C
new file mode 100644
index 000000000000..d73092b595e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr109283.C
@@ -0,0 +1,23 @@
+// PR 109283.
+// This used to ICE from a check set too widely.
+#include <coroutine>
+
+struct foo
+{ ~foo(); };
+
+struct task
+{
+   struct promise_type
+   {
+       std::suspend_never initial_suspend();
+       std::suspend_never final_suspend() noexcept;
+       std::suspend_never yield_value(foo);
+       void return_void();
+       void unhandled_exception(); 
+       task get_return_object();
+   };
+};
+
+task source(int b) {
+   co_yield b ? foo{} : foo{};
+}

Reply via email to