Message ID | B6CCF2A6-042F-42D4-B342-3C0B28073ADB@sandoe.co.uk |
---|---|
State | New |
Headers | show |
Series | coroutines: Allow parameter packs in co_await/yield expressions [PR95345] | expand |
On 6/1/20 4:09 AM, Iain Sandoe wrote: > Hi > > 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. > > tested on x86_64,powerpc64-linux, x86_64-darwin > OK for master? > OK for 10.2? ok for both > thanks > Iain > > 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. > --- > gcc/cp/coroutines.cc | 45 +++++++++++------------ > gcc/testsuite/g++.dg/coroutines/pr95345.C | 32 ++++++++++++++++ > 2 files changed, 53 insertions(+), 24 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/coroutines/pr95345.C > > diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc > index cc685ca73b2..7afa550037c 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 00000000000..90e946d91c2 > --- /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>(); > +} >
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index cc685ca73b2..7afa550037c 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 00000000000..90e946d91c2 --- /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>(); +}