aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-01-31 12:31:43 -0500
committerJason Merrill <jason@redhat.com>2025-02-03 16:55:03 -0500
commitec716ad3f4bdccb6a2780161e74e3168efa68121 (patch)
tree7bd0fdac93d50f1324ffd925ea28b34b18e73730
parentf3a41e6cb5d70f0c94cc8273a118b8542fb5c2fa (diff)
downloadgcc-ec716ad3f4bdccb6a2780161e74e3168efa68121.zip
gcc-ec716ad3f4bdccb6a2780161e74e3168efa68121.tar.gz
gcc-ec716ad3f4bdccb6a2780161e74e3168efa68121.tar.bz2
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.
-rw-r--r--gcc/cp/semantics.cc1
-rw-r--r--gcc/testsuite/g++.dg/coroutines/coro-range-for1.C38
2 files changed, 38 insertions, 1 deletions
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ad9864c..73b4917 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 0000000..eaf4d19
--- /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.;
+ }
+}