diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2022-04-18 16:23:30 +0100 |
---|---|---|
committer | Iain Sandoe <iains@gcc.gnu.org> | 2024-06-27 13:56:34 +0100 |
commit | f4cdbf1f757fa9525d70780546d7daa43dfb129f (patch) | |
tree | 7fdbf51a71550981d73befab0fbd8a7cd0a95f3e | |
parent | 1d5779274ce9807358f9e04f1112b65c6ed6c284 (diff) | |
download | gcc-f4cdbf1f757fa9525d70780546d7daa43dfb129f.zip gcc-f4cdbf1f757fa9525d70780546d7daa43dfb129f.tar.gz gcc-f4cdbf1f757fa9525d70780546d7daa43dfb129f.tar.bz2 |
c++, coroutines: Improve check for throwing final await [PR104051].
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 use returns some nonsensical type from the
method, we need to handle that in the checking for noexcept.
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.
(cherry picked from commit 7b96274a340bc0e9bcaef9baff3a44ec2f12c3df)
-rw-r--r-- | gcc/cp/coroutines.cc | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/coroutines/pr104051.C | 29 |
2 files changed, 36 insertions, 6 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 406c85c..b12d74b 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -877,13 +877,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 0000000..ce7ae55 --- /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()) + ; +} |