aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2024-07-25 01:00:02 +0200
committerArsen Arsenović <arsen@gcc.gnu.org>2024-07-30 13:44:13 +0200
commit0c382da0943dc7d14455ba2ada2f620a25bd1366 (patch)
tree365b8e6e9f9d7ff3c94c996978425fa01016bd11
parenta362c9ca4ef6585e678f899705043a9aa10dd670 (diff)
downloadgcc-0c382da0943dc7d14455ba2ada2f620a25bd1366.zip
gcc-0c382da0943dc7d14455ba2ada2f620a25bd1366.tar.gz
gcc-0c382da0943dc7d14455ba2ada2f620a25bd1366.tar.bz2
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.
-rw-r--r--gcc/cp/parser.cc17
-rw-r--r--gcc/testsuite/g++.dg/coroutines/co-await-syntax-02-outside-fn.C2
-rw-r--r--gcc/testsuite/g++.dg/coroutines/co-yield-syntax-01-outside-fn.C3
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr115906-yield.C29
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr115906.C32
5 files changed, 80 insertions, 3 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e46cdfd..eb102de 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -9242,6 +9242,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));
}
@@ -29651,6 +29659,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 4ce5c2e..132128f 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 30db0e9..51c3046 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 0000000..f8b6ded
--- /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 0000000..28f408f
--- /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;
+}