https://gcc.gnu.org/g:7b4cb031cf7de0ac350197e4ae869df9fe1d08a1

commit r14-11718-g7b4cb031cf7de0ac350197e4ae869df9fe1d08a1
Author: Arsen Arsenović <ar...@aarsen.me>
Date:   Thu Jul 25 01:00:02 2024 +0200

    c++: diagnose usage of co_await and co_yield in default args [PR115906]
    
    This is a partial fix for PR115906.  Per [expr.await] 2s3, "An
    await-expression shall not appear in a default argument
    ([dcl.fct.default])".  This patch introduces the diagnostic in that
    case, and in the case of a co_yield (as co_yield is defined in terms of
    co_await, so prerequisites of co_await hold).
    
    PR c++/115906 - [coroutines] missing diagnostic and ICE when co_await used 
as default argument in function declaration
    
    gcc/cp/ChangeLog:
    
            PR c++/115906
            * parser.cc (cp_parser_unary_expression): Reject await
            expressions if use of local variables is currently forbidden.
            (cp_parser_yield_expression): Reject yield expressions if use of
            local variables is currently forbidden.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/115906
            * g++.dg/coroutines/pr115906-yield.C: New test.
            * g++.dg/coroutines/pr115906.C: New test.
            * g++.dg/coroutines/co-await-syntax-02-outside-fn.C: Don't rely
            on default arguments.
            * g++.dg/coroutines/co-yield-syntax-01-outside-fn.C: Ditto.
    
    (cherry picked from commit 0c382da0943dc7d14455ba2ada2f620a25bd1366)

Diff:
---
 gcc/cp/parser.cc                                   | 17 ++++++++++++
 .../coroutines/co-await-syntax-02-outside-fn.C     |  2 +-
 .../coroutines/co-yield-syntax-01-outside-fn.C     |  3 +-
 gcc/testsuite/g++.dg/coroutines/pr115906-yield.C   | 29 ++++++++++++++++++++
 gcc/testsuite/g++.dg/coroutines/pr115906.C         | 32 ++++++++++++++++++++++
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 0a703cdc2207..0281d7eb99b6 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -9220,6 +9220,14 @@ cp_parser_unary_expression (cp_parser *parser, 
cp_id_kind * pidk,
            if (expr == error_mark_node)
              return error_mark_node;
 
+           /* ... but, we cannot use co_await in default arguments.  */
+           if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
+             {
+               error_at (kw_loc,
+                         "%<co_await%> cannot be used in default arguments");
+               return error_mark_node;
+             }
+
            /* Handle [expr.await].  */
            return cp_expr (finish_co_await_expr (kw_loc, expr));
          }
@@ -29407,6 +29415,15 @@ cp_parser_yield_expression (cp_parser* parser)
   else
     expr = cp_parser_assignment_expression (parser);
 
+  /* Similar to co_await, we cannot use co_yield in default arguments (as
+     co_awaits underlie co_yield).  */
+  if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
+    {
+      error_at (kw_loc,
+               "%<co_yield%> cannot be used in default arguments");
+      return error_mark_node;
+    }
+
   if (expr == error_mark_node)
     return expr;
 
diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-syntax-02-outside-fn.C 
b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-02-outside-fn.C
index 4ce5c2e04a0a..132128f27192 100644
--- a/gcc/testsuite/g++.dg/coroutines/co-await-syntax-02-outside-fn.C
+++ b/gcc/testsuite/g++.dg/coroutines/co-await-syntax-02-outside-fn.C
@@ -2,4 +2,4 @@
 
 #include "coro.h"
 
-auto f (int x = co_await coro::suspend_always{}); // { dg-error {'co_await' 
cannot be used outside a function} }
+auto x = co_await coro::suspend_always{}; // { dg-error {'co_await' cannot be 
used outside a function} }
diff --git a/gcc/testsuite/g++.dg/coroutines/co-yield-syntax-01-outside-fn.C 
b/gcc/testsuite/g++.dg/coroutines/co-yield-syntax-01-outside-fn.C
index 30db0e963b09..51c304625278 100644
--- a/gcc/testsuite/g++.dg/coroutines/co-yield-syntax-01-outside-fn.C
+++ b/gcc/testsuite/g++.dg/coroutines/co-yield-syntax-01-outside-fn.C
@@ -2,5 +2,4 @@
 
 #include "coro.h"
 
-auto f (int x = co_yield 5); // { dg-error {'co_yield' cannot be used outside 
a function} }
-
+auto x = co_yield 5; // { dg-error {'co_yield' cannot be used outside a 
function} }
diff --git a/gcc/testsuite/g++.dg/coroutines/pr115906-yield.C 
b/gcc/testsuite/g++.dg/coroutines/pr115906-yield.C
new file mode 100644
index 000000000000..f8b6ded5001c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr115906-yield.C
@@ -0,0 +1,29 @@
+#include <coroutine>
+
+struct Promise;
+
+struct Handle : std::coroutine_handle<Promise> {
+    using promise_type = Promise;
+};
+
+struct Promise {
+    Handle get_return_object() noexcept {
+        return {Handle::from_promise(*this)};
+    }
+    std::suspend_never initial_suspend() const noexcept { return {}; }
+    std::suspend_never final_suspend() const noexcept { return {}; }
+    void return_void() const noexcept {}
+    void unhandled_exception() const noexcept {}
+    std::suspend_never yield_value(int) { return {}; }
+};
+
+Handle Coro() {
+    [] (int x = co_yield 1){}; // { dg-error ".co_yield. cannot be used in 
default arguments" }
+    co_return;
+}
+
+int main() {
+    Coro();
+
+    return 0;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr115906.C 
b/gcc/testsuite/g++.dg/coroutines/pr115906.C
new file mode 100644
index 000000000000..28f408fbaddd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr115906.C
@@ -0,0 +1,32 @@
+#include <coroutine>
+
+struct Promise;
+
+struct Handle : std::coroutine_handle<Promise> {
+    using promise_type = Promise;
+};
+
+struct Promise {
+    Handle get_return_object() noexcept {
+        return {Handle::from_promise(*this)};
+    }
+    std::suspend_never initial_suspend() const noexcept { return {}; }
+    std::suspend_never final_suspend() const noexcept { return {}; }
+    void return_void() const noexcept {}
+    void unhandled_exception() const noexcept {}
+};
+
+Handle Coro() {
+    struct Awaiter : std::suspend_never {
+        int await_resume() { return 0; }
+    };
+
+    [] (int x = co_await Awaiter{}){}; // { dg-error ".co_await. cannot be 
used in default arguments" }
+    co_return;
+}
+
+int main() {
+    Coro();
+
+    return 0;
+}

Reply via email to