From f13d9e48eeca7ed8f8df55c9a62fc9980d5606ad Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 23 Feb 2021 12:54:26 +0000 Subject: [PATCH] coroutines : Adjust error handling for type-dependent coroutines [PR96251]. Although coroutines are not permitted to be constexpr, generic lambdas are implicitly from C++17 and, because of this, a generic coroutine lambda can be marked as potentially constexpr. As per the PR, this then fails when type substitution is attempted because the check disallowing constexpr in the coroutines code was overly restrictive. This changes the error handing to mark the function as 'invalid_constexpr' but suppresses the error in the case that we are instantiating a constexpr. gcc/cp/ChangeLog: PR c++/96251 * coroutines.cc (coro_common_keyword_context_valid_p): Suppress error reporting when instantiating for a constexpr. gcc/testsuite/ChangeLog: PR c++/96251 * g++.dg/coroutines/pr96251.C: New test. --- gcc/cp/coroutines.cc | 11 +++++++---- gcc/testsuite/g++.dg/coroutines/pr96251.C | 32 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr96251.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index e61de1f..abfe8d0 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -683,11 +683,14 @@ coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc, if (DECL_DECLARED_CONSTEXPR_P (fndecl)) { - /* [dcl.constexpr] 3.3 it shall not be a coroutine. */ - error_at (kw_loc, "%qs cannot be used in a % function", - kw_name); cp_function_chain->invalid_constexpr = true; - return false; + if (!is_instantiation_of_constexpr (fndecl)) + { + /* [dcl.constexpr] 3.3 it shall not be a coroutine. */ + error_at (kw_loc, "%qs cannot be used in a % function", + kw_name); + return false; + } } if (FNDECL_USED_AUTO (fndecl)) diff --git a/gcc/testsuite/g++.dg/coroutines/pr96251.C b/gcc/testsuite/g++.dg/coroutines/pr96251.C new file mode 100644 index 0000000..3f43504 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr96251.C @@ -0,0 +1,32 @@ +#include + +struct coroutine { + struct promise_type { + auto get_return_object() { return coroutine(); } + auto initial_suspend() { return std::suspend_always(); } + auto yield_value(int) { return std::suspend_always(); } + void return_void() {} + auto final_suspend() noexcept { return std::suspend_always(); } + void unhandled_exception() {} + }; +}; + +int main() { + auto f = [](auto max) -> coroutine { + for (int i = 0; i < max; ++i) { + co_yield i; + } + }; + + f(10); + + // From PR98976 + auto foo = [](auto&&) -> coroutine { + switch (42) { + case 42: + co_return; + } + }; + foo(1); + +} -- 2.7.4