diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2020-06-03 09:03:22 +0100 |
---|---|---|
committer | Iain Sandoe <iain@sandoe.co.uk> | 2020-06-03 20:23:59 +0100 |
commit | cf7eac5805e714c7e71b699329e2c4f4a88addc1 (patch) | |
tree | fc58d64b47f4c023670d0c8de19eb9f5c6596f88 /gcc | |
parent | b19d8aac15649f31a7588b2634411a1922906ea8 (diff) | |
download | gcc-cf7eac5805e714c7e71b699329e2c4f4a88addc1.zip gcc-cf7eac5805e714c7e71b699329e2c4f4a88addc1.tar.gz gcc-cf7eac5805e714c7e71b699329e2c4f4a88addc1.tar.bz2 |
coroutines: Allow parameter packs in co_await/yield expressions [PR95345]
This corrects a pasto, where I copied the constraint on bare
parameter packs from the co_return to co_yield/await without
properly reviewing it.
gcc/cp/ChangeLog:
PR c++/95345
* coroutines.cc (finish_co_await_expr): Revise to allow for
parameter packs.
(finish_co_yield_expr): Likewise.
gcc/testsuite/ChangeLog:
PR c++/95345
* g++.dg/coroutines/pr95345.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/coroutines.cc | 45 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/coroutines/pr95345.C | 32 |
2 files changed, 53 insertions, 24 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index e689625..58102f5 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -851,19 +851,18 @@ finish_co_await_expr (location_t kw, tree expr) /* The current function has now become a coroutine, if it wasn't already. */ DECL_COROUTINE_P (current_function_decl) = 1; - if (processing_template_decl) - { - current_function_returns_value = 1; - - if (check_for_bare_parameter_packs (expr)) - return error_mark_node; + /* This function will appear to have no return statement, even if it + is declared to return non-void (most likely). This is correct - we + synthesize the return for the ramp in the compiler. So suppress any + extraneous warnings during substitution. */ + TREE_NO_WARNING (current_function_decl) = true; - /* If we don't know the promise type, we can't proceed. */ - tree functype = TREE_TYPE (current_function_decl); - if (dependent_type_p (functype) || type_dependent_expression_p (expr)) - return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr, - NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node); - } + /* If we don't know the promise type, we can't proceed, build the + co_await with the expression unchanged. */ + tree functype = TREE_TYPE (current_function_decl); + if (dependent_type_p (functype) || type_dependent_expression_p (expr)) + return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr, + NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node); /* We must be able to look up the "await_transform" method in the scope of the promise type, and obtain its return type. */ @@ -928,19 +927,17 @@ finish_co_yield_expr (location_t kw, tree expr) /* The current function has now become a coroutine, if it wasn't already. */ DECL_COROUTINE_P (current_function_decl) = 1; - if (processing_template_decl) - { - current_function_returns_value = 1; - - if (check_for_bare_parameter_packs (expr)) - return error_mark_node; + /* This function will appear to have no return statement, even if it + is declared to return non-void (most likely). This is correct - we + synthesize the return for the ramp in the compiler. So suppress any + extraneous warnings during substitution. */ + TREE_NO_WARNING (current_function_decl) = true; - tree functype = TREE_TYPE (current_function_decl); - /* If we don't know the promise type, we can't proceed. */ - if (dependent_type_p (functype) || type_dependent_expression_p (expr)) - return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, - NULL_TREE); - } + /* If we don't know the promise type, we can't proceed, build the + co_await with the expression unchanged. */ + tree functype = TREE_TYPE (current_function_decl); + if (dependent_type_p (functype) || type_dependent_expression_p (expr)) + return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE); if (!coro_promise_type_found_p (current_function_decl, kw)) /* We must be able to look up the "yield_value" method in the scope of diff --git a/gcc/testsuite/g++.dg/coroutines/pr95345.C b/gcc/testsuite/g++.dg/coroutines/pr95345.C new file mode 100644 index 0000000..90e946d --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr95345.C @@ -0,0 +1,32 @@ +#if __has_include (<coroutine>) +#include <coroutine> +using namespace std; +#elif defined (__clang__) && __has_include (<experimental/coroutine>) +#include <experimental/coroutine> +using namespace std::experimental; +#endif + +struct dummy_coro +{ + using promise_type = dummy_coro; + bool await_ready() { return false; } + void await_suspend(std::coroutine_handle<>) { } + void await_resume() { } + dummy_coro get_return_object() { return {}; } + dummy_coro initial_suspend() { return {}; } + dummy_coro final_suspend() { return {}; } + void return_void() { } + void unhandled_exception() { } +}; + +template <int ...I> +dummy_coro +foo() +{ + ((co_await [](int){ return std::suspend_never{}; }(I)), ...); + co_return; +} + +void bar() { + foo<1>(); +} |