From a312c80194685790aec7cf678eba83a536031cbf Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 21 Jan 2020 20:42:17 +0000 Subject: [PATCH] [coro] Fix co_await of void type. gcc/cp 2020-01-21 Iain Sandoe Bin Cheng * coroutines.cc (coro_promise_type_found_p): Check for NULL return from complete_type_or_else. (register_param_uses): Likewise. (build_co_await): Do not try to use complete_type_or_else for void types, otherwise for incomplete types, check for NULL return from complete_type_or_else. gcc/testsuite 2020-01-21 Bin Cheng * g++.dg/coroutines/co-await-void_type.C: New test. --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/coroutines.cc | 15 ++++++- gcc/testsuite/ChangeLog | 4 ++ .../g++.dg/coroutines/co-await-void_type.C | 44 +++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/co-await-void_type.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 412702f9b62..3fc1b31e5cd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2020-01-21 Iain Sandoe + Bin Cheng + + * coroutines.cc (coro_promise_type_found_p): Check for NULL return + from complete_type_or_else. + (register_param_uses): Likewise. + (build_co_await): Do not try to use complete_type_or_else for void + types, otherwise for incomplete types, check for NULL return from + complete_type_or_else. + 2020-01-21 Jason Merrill PR c++/91476 - anon-namespace reference temp clash between TUs. diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 8a8c1b9829b..b99e7215639 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -428,8 +428,9 @@ coro_promise_type_found_p (tree fndecl, location_t loc) /* Complete this, we're going to use it. */ coro_info->handle_type = complete_type_or_else (handle_type, fndecl); + /* Diagnostic would be emitted by complete_type_or_else. */ - if (coro_info->handle_type == error_mark_node) + if (!coro_info->handle_type) return false; /* Build a proxy for a handle to "self" as the param to @@ -633,7 +634,13 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) else o = a; /* This is most likely about to fail anyway. */ - tree o_type = complete_type_or_else (TREE_TYPE (o), o); + tree o_type = TREE_TYPE (o); + if (o_type && !VOID_TYPE_P (o_type)) + o_type = complete_type_or_else (o_type, o); + + if (!o_type) + return error_mark_node; + if (TREE_CODE (o_type) != RECORD_TYPE) { error_at (loc, "awaitable type %qT is not a structure", @@ -2730,6 +2737,10 @@ register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d) if (!COMPLETE_TYPE_P (actual_type)) actual_type = complete_type_or_else (actual_type, *stmt); + if (actual_type == NULL_TREE) + /* Diagnostic emitted by complete_type_or_else. */ + actual_type = error_mark_node; + if (TREE_CODE (actual_type) == REFERENCE_TYPE) actual_type = build_pointer_type (TREE_TYPE (actual_type)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e8561cca412..f4f11a98ae7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-01-21 Bin Cheng + + * g++.dg/coroutines/co-await-void_type.C: New test. + 2020-01-21 Jakub Jelinek PR target/93333 diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C b/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C new file mode 100644 index 00000000000..0bb8818133e --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C @@ -0,0 +1,44 @@ +// { dg-additional-options "-std=c++17 -fsyntax-only -w" } + +#include + +class resumable { +public: + struct promise_type; + using coro_handle = std::coroutine_handle; + resumable(coro_handle handle) : handle_(handle) {} + resumable(resumable&) = delete; + resumable(resumable&&) = delete; + bool resume() { + if (not handle_.done()) + handle_.resume(); + return not handle_.done(); + } + int recent_val(); + ~resumable() { handle_.destroy(); } +private: + coro_handle handle_; +}; + +struct resumable::promise_type { + int value_; + + using coro_handle = std::coroutine_handle; + auto get_return_object() { + return coro_handle::from_promise(*this); + } + auto initial_suspend() { return std::suspend_always(); } + auto final_suspend() { return std::suspend_always(); } + void yield_value(int v) { value_ = v; } + void unhandled_exception() {} +}; + +int resumable::recent_val(){return handle_.promise().value_;} + +resumable foo(int n){ + int x = 1; + co_await std::suspend_always(); + int y = 2; + co_yield n + x + y; // { dg-error "awaitable type 'void' is not a structure" } +} + -- 2.30.2