Hi Jason,

Jason Merrill <ja...@redhat.com> wrote:

> On 2/22/21 3:59 PM, Iain Sandoe wrote:

>> * I was not able to see any way in which the instantiation process
>>   could be made to bail in this case and re-try for non-constexpr.
> 
> Many of the other places that set cp_function_chain->invalid_constexpr 
> condition their errors on !is_instantiation_of_constexpr, which should also 
> fix this testcase.

Thanks!
(FWIW, there only seem to be three instances of this in the FE and two of those 
are in constexpr.c).

so like this?
(tested on x86_64-darwin, regtest running x86_64 linux)

thanks
iain

====
 [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++/PR96251
        * 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 e61de1fac01..abfe8d08192 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 %<constexpr%> 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 %<constexpr%> 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 00000000000..3f435044e41
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr96251.C
@@ -0,0 +1,32 @@
+#include <coroutine>
+    
+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.24.1


Reply via email to