https://gcc.gnu.org/g:ec716ad3f4bdccb6a2780161e74e3168efa68121

commit r15-7337-gec716ad3f4bdccb6a2780161e74e3168efa68121
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Jan 31 12:31:43 2025 -0500

    c++: coroutines and range for [PR118491]
    
    The implementation of extended range-for temporaries in r15-3840 confused
    coroutines, because await_statement_walker and the like get confused by the
    EXPR_STMT into thinking that the whole for-loop is a single expression
    statement and try to process it accordingly.  Fixing this seems to be a
    simple matter of dropping the EXPR_STMT.
    
            PR c++/116914
            PR c++/117231
            PR c++/118470
            PR c++/118491
    
    gcc/cp/ChangeLog:
    
            * semantics.cc (finish_for_stmt): Don't wrap the result of
            pop_stmt_list in EXPR_STMT.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/coro-range-for1.C: New test.

Diff:
---
 gcc/cp/semantics.cc                               |  1 -
 gcc/testsuite/g++.dg/coroutines/coro-range-for1.C | 38 +++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ad9864c3a91a..73b49174de43 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -1709,7 +1709,6 @@ finish_for_stmt (tree for_stmt)
     {
       tree stmt = pop_stmt_list (FOR_INIT_STMT (for_stmt));
       FOR_INIT_STMT (for_stmt) = NULL_TREE;
-      stmt = build_stmt (EXPR_LOCATION (for_stmt), EXPR_STMT, stmt);
       stmt = maybe_cleanup_point_expr_void (stmt);
       add_stmt (stmt);
     }
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-range-for1.C 
b/gcc/testsuite/g++.dg/coroutines/coro-range-for1.C
new file mode 100644
index 000000000000..eaf4d19e62cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/coro-range-for1.C
@@ -0,0 +1,38 @@
+// PR c++/118491
+// { dg-do compile { target c++20 } }
+
+#include <coroutine>
+
+struct task {
+  struct promise_type {
+    task get_return_object() { return {}; }
+    std::suspend_always initial_suspend() { return {}; }
+    std::suspend_always final_suspend() noexcept { return {}; }
+    std::suspend_always yield_value(double value) { return {}; }
+    void unhandled_exception() { throw; }
+  };
+};
+
+task do_task() {
+  const int arr[]{1, 2, 3};
+
+  // No ICE if classic loop and not range-based one.
+  // for (auto i = 0; i < 10; ++i) {
+
+  // No ICE if these are moved out of the loop.
+  // auto x = std::suspend_always{};
+  // co_await x;
+
+  for (auto _ : arr) {
+    auto bar = std::suspend_always{};
+    co_await bar;
+
+    // Alternatively:
+    // auto bar = 42.;
+    // co_yield bar;
+
+    // No ICE if r-values:
+    // co_await std::suspend_always{};
+    // co_yield 42.;
+  }
+}

Reply via email to