Message ID | 20220418153404.71282-1-iain@sandoe.co.uk |
---|---|
State | New |
Headers | show |
Series | c++, coroutines: Improve check for throwing final await [PR104051]. | expand |
On 4/18/22 11:34, Iain Sandoe wrote: > We check that the final_suspend () method returns a sane type (i.e. a class > or structure) but, unfortunately, that check has to be later than the one > for a throwing case. If the user returns some nonsensical type from the > method, we need to handle that in the checking for noexcept. > > tested on x86_64-darwin, OK for mainline? (when?), OK. > thanks > Iain > > Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> > > PR c++/104051 > > gcc/cp/ChangeLog: > > * coroutines.cc (coro_diagnose_throwing_final_aw_expr): Handle > non-target expression inputs. > > gcc/testsuite/ChangeLog: > > * g++.dg/coroutines/pr104051.C: New test. > --- > gcc/cp/coroutines.cc | 13 +++++----- > gcc/testsuite/g++.dg/coroutines/pr104051.C | 29 ++++++++++++++++++++++ > 2 files changed, 36 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/coroutines/pr104051.C > > diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc > index d2a765cac11..cb9bbed51e6 100644 > --- a/gcc/cp/coroutines.cc > +++ b/gcc/cp/coroutines.cc > @@ -883,13 +883,14 @@ coro_diagnose_throwing_fn (tree fndecl) > static bool > coro_diagnose_throwing_final_aw_expr (tree expr) > { > - tree t = TARGET_EXPR_INITIAL (expr); > + if (TREE_CODE (expr) == TARGET_EXPR) > + expr = TARGET_EXPR_INITIAL (expr); > tree fn = NULL_TREE; > - if (TREE_CODE (t) == CALL_EXPR) > - fn = CALL_EXPR_FN(t); > - else if (TREE_CODE (t) == AGGR_INIT_EXPR) > - fn = AGGR_INIT_EXPR_FN (t); > - else if (TREE_CODE (t) == CONSTRUCTOR) > + if (TREE_CODE (expr) == CALL_EXPR) > + fn = CALL_EXPR_FN (expr); > + else if (TREE_CODE (expr) == AGGR_INIT_EXPR) > + fn = AGGR_INIT_EXPR_FN (expr); > + else if (TREE_CODE (expr) == CONSTRUCTOR) > return false; > else > { > diff --git a/gcc/testsuite/g++.dg/coroutines/pr104051.C b/gcc/testsuite/g++.dg/coroutines/pr104051.C > new file mode 100644 > index 00000000000..ce7ae55405a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/coroutines/pr104051.C > @@ -0,0 +1,29 @@ > +// { dg-additional-options "-fsyntax-only" } > +#include <coroutine> > +#include <vector> > +template <typename> struct promise { > + struct final_awaitable { > + bool await_ready() noexcept; > + template <typename Promise> > + std::coroutine_handle<> > + await_suspend(std::coroutine_handle<Promise>) noexcept; > + void await_resume() noexcept; > + }; > + auto get_return_object() { > + return std::coroutine_handle<promise>::from_promise(*this); > + } > + auto initial_suspend() { return std::suspend_always(); } > + auto final_suspend() noexcept { return true; } > + void unhandled_exception(); > +}; > +template <typename T> struct task { > + using promise_type = promise<T>; > + task(std::coroutine_handle<promise<T>>); > + bool await_ready(); > + std::coroutine_handle<> await_suspend(std::coroutine_handle<>); > + T await_resume(); > +}; > +task<std::vector<int>> foo() { // { dg-error {awaitable type 'bool' is not a structure} } > + while ((co_await foo()).empty()) > + ; > +}
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index d2a765cac11..cb9bbed51e6 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -883,13 +883,14 @@ coro_diagnose_throwing_fn (tree fndecl) static bool coro_diagnose_throwing_final_aw_expr (tree expr) { - tree t = TARGET_EXPR_INITIAL (expr); + if (TREE_CODE (expr) == TARGET_EXPR) + expr = TARGET_EXPR_INITIAL (expr); tree fn = NULL_TREE; - if (TREE_CODE (t) == CALL_EXPR) - fn = CALL_EXPR_FN(t); - else if (TREE_CODE (t) == AGGR_INIT_EXPR) - fn = AGGR_INIT_EXPR_FN (t); - else if (TREE_CODE (t) == CONSTRUCTOR) + if (TREE_CODE (expr) == CALL_EXPR) + fn = CALL_EXPR_FN (expr); + else if (TREE_CODE (expr) == AGGR_INIT_EXPR) + fn = AGGR_INIT_EXPR_FN (expr); + else if (TREE_CODE (expr) == CONSTRUCTOR) return false; else { diff --git a/gcc/testsuite/g++.dg/coroutines/pr104051.C b/gcc/testsuite/g++.dg/coroutines/pr104051.C new file mode 100644 index 00000000000..ce7ae55405a --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr104051.C @@ -0,0 +1,29 @@ +// { dg-additional-options "-fsyntax-only" } +#include <coroutine> +#include <vector> +template <typename> struct promise { + struct final_awaitable { + bool await_ready() noexcept; + template <typename Promise> + std::coroutine_handle<> + await_suspend(std::coroutine_handle<Promise>) noexcept; + void await_resume() noexcept; + }; + auto get_return_object() { + return std::coroutine_handle<promise>::from_promise(*this); + } + auto initial_suspend() { return std::suspend_always(); } + auto final_suspend() noexcept { return true; } + void unhandled_exception(); +}; +template <typename T> struct task { + using promise_type = promise<T>; + task(std::coroutine_handle<promise<T>>); + bool await_ready(); + std::coroutine_handle<> await_suspend(std::coroutine_handle<>); + T await_resume(); +}; +task<std::vector<int>> foo() { // { dg-error {awaitable type 'bool' is not a structure} } + while ((co_await foo()).empty()) + ; +}
We check that the final_suspend () method returns a sane type (i.e. a class or structure) but, unfortunately, that check has to be later than the one for a throwing case. If the user returns some nonsensical type from the method, we need to handle that in the checking for noexcept. tested on x86_64-darwin, OK for mainline? (when?), thanks Iain Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR c++/104051 gcc/cp/ChangeLog: * coroutines.cc (coro_diagnose_throwing_final_aw_expr): Handle non-target expression inputs. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr104051.C: New test. --- gcc/cp/coroutines.cc | 13 +++++----- gcc/testsuite/g++.dg/coroutines/pr104051.C | 29 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr104051.C