Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
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. --- gcc/cp/semantics.cc | 1 - .../g++.dg/coroutines/coro-range-for1.C | 38 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/coro-range-for1.C diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index ad9864c3a91..73b49174de4 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 00000000000..eaf4d19e62c --- /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.; + } +} base-commit: f3a41e6cb5d70f0c94cc8273a118b8542fb5c2fa -- 2.48.0