Hi Nathan, This corrects my mixup between the error returns for complete_type and complete_type_or_else, spotted by Jakub,
I have included Bin’s change that makes the coro-specific error message fire if a void type is provided for this. Additional comments below. Iain Sandoe <i...@sandoe.co.uk> wrote: > Bin.Cheng <amker.ch...@gmail.com> wrote: > >> On Mon, Jan 20, 2020 at 6:31 PM Iain Sandoe <i...@sandoe.co.uk> wrote: >>> Bin.Cheng <amker.ch...@gmail.com> wrote: >>> >>> tree o_type = TREE_TYPE (o); >>> - if (!VOID_TYPE_P (o_type)) >>> - o_type = complete_type_or_else (TREE_TYPE (o), o); >>> + if (o_type && !VOID_TYPE_P (o_type) && !COMPLETE_TYPE_P (o_type)) >> IIUC, Jakub doesn't like checking void type specially here? > > that is necessary if we want the coro-specific diagnostic (which is more > meaningful > than the vanilla void one) however, if there’s opposition to that, I don’t > have such a > strong opinion. Note, we cannot eliminate the following code for the diagnostic check; we still have to verify that complete types are suitable. Bin’s addition makes that warning fire for void types too. OK for trunk? thanks Iain [coro] Fix co_await of void type. gcc/cp 2020-01-21 Iain Sandoe <i...@sandoe.co.uk> Bin Cheng <bin.ch...@linux.alibaba.com> * 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 <bin.ch...@linux.alibaba.com> * g++.dg/coroutines/co-await-void_type.C: New test. diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 8a8c1b9829b..aea341604b9 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) && !COMPLETE_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/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 <coroutine> + +class resumable { +public: + struct promise_type; + using coro_handle = std::coroutine_handle<promise_type>; + 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<promise_type>; + 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" } +} +