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.
This commit is contained in:
Iain Sandoe 2022-04-18 16:23:30 +01:00
parent 6cae3bb65c
commit 7b96274a34
2 changed files with 36 additions and 6 deletions

View File

@ -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
{

View File

@ -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())
;
}