From c75199b716ed54638ce8949d0f1f4ef71c0b31a5 Mon Sep 17 00:00:00 2001 From: JunMa Date: Thu, 21 Nov 2019 08:51:22 +0800 Subject: [PATCH] Add error messages for missing methods of awaitable class gcc/cp/ChangeLog * coroutines.cc (lookup_awaitable_member): Lookup an awaitable member. (lookup_promise_method): Emit diagnostic when get NULL_TREE back only. (build_co_await): Use lookup_awaitable_member instead of lookup_member. gcc/testsuite/ChangeLog * g++.dg/coroutines/coro1-missing-await-method.C: New test. --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/coroutines.cc | 36 ++++++++++++------- gcc/testsuite/ChangeLog | 4 +++ .../coroutines/coro1-missing-await-method.C | 21 +++++++++++ .../coroutines/coro1-ret-int-yield-int.h | 9 +++++ 5 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 04c5d2ee8f4..3f379d0d996 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-01-22 Jun Ma + + * coroutines.cc (lookup_awaitable_member): Lookup an awaitable member. + (lookup_promise_method): Emit diagnostic when get NULL_TREE back only. + (build_co_await): Use lookup_awaitable_member instead of lookup_member. + 2020-01-21 Jason Merrill PR c++/60855 - ICE with sizeof VLA capture. diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index b99e7215639..6381fdc2f11 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -497,8 +497,8 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc, tree promise = get_coroutine_promise_type (fndecl); tree pm_memb = lookup_member (promise, member_id, - /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error); - if (musthave && (pm_memb == NULL_TREE || pm_memb == error_mark_node)) + /*protect=*/1, /*want_type=*/0, tf_warning_or_error); + if (musthave && pm_memb == NULL_TREE) { error_at (loc, "no member named %qE in %qT", member_id, promise); return error_mark_node; @@ -506,6 +506,23 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc, return pm_memb; } +/* Lookup an Awaitable member, which should be await_ready, await_suspend + or await_resume. */ + +static tree +lookup_awaitable_member (tree await_type, tree member_id, location_t loc) +{ + tree aw_memb + = lookup_member (await_type, member_id, + /*protect=*/1, /*want_type=*/0, tf_warning_or_error); + if (aw_memb == NULL_TREE) + { + error_at (loc, "no member named %qE in %qT", member_id, await_type); + return error_mark_node; + } + return aw_memb; +} + /* Here we check the constraints that are common to all keywords (since the presence of a coroutine keyword makes the function into a coroutine). */ @@ -650,25 +667,18 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) /* Check for required awaitable members and their types. */ tree awrd_meth - = lookup_member (o_type, coro_await_ready_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc); if (!awrd_meth || awrd_meth == error_mark_node) return error_mark_node; - tree awsp_meth - = lookup_member (o_type, coro_await_suspend_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc); if (!awsp_meth || awsp_meth == error_mark_node) return error_mark_node; /* The type of the co_await is the return type of the awaitable's - co_resume(), so we need to look that up. */ + await_resume, so we need to look that up. */ tree awrs_meth - = lookup_member (o_type, coro_await_resume_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc); if (!awrs_meth || awrs_meth == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1be1b59ac02..08c81e1bf8a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-01-22 Jun Ma + + * g++.dg/coroutines/coro1-missing-await-method.C: New test. + 2020-01-21 Andrew Pinski PR target/93119 diff --git a/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C new file mode 100644 index 00000000000..c1869e0654c --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C @@ -0,0 +1,21 @@ +// { dg-additional-options "-fsyntax-only -w" } +#include "coro.h" + +#define MISSING_AWAIT_READY +#define MISSING_AWAIT_SUSPEND +#define MISSING_AWAIT_RESUME +#include "coro1-ret-int-yield-int.h" + +coro1 +bar0 () // { dg-error {no member named 'await_suspend' in 'coro1::suspend_always_prt'} } +{ + co_await coro1::suspend_never_prt{}; // { dg-error {no member named 'await_ready' in 'coro1::suspend_never_prt'} } + co_yield 5; // { dg-error {no member named 'await_suspend' in 'coro1::suspend_always_prt'} } + co_await coro1::suspend_always_intprt(5); // { dg-error {no member named 'await_resume' in 'coro1::suspend_always_intprt'} } + co_return 0; +} + +int main (int ac, char *av[]) { + struct coro1 x0 = bar0 (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h b/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h index b961755e472..abf625869fa 100644 --- a/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h +++ b/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h @@ -27,14 +27,20 @@ struct coro1 { // Some awaitables to use in tests. // With progress printing for debug. struct suspend_never_prt { +#ifdef MISSING_AWAIT_READY +#else bool await_ready() const noexcept { return true; } +#endif void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");} void await_resume() const noexcept { PRINT ("susp-never-resume");} }; struct suspend_always_prt { bool await_ready() const noexcept { return false; } +#ifdef MISSING_AWAIT_SUSPEND +#else void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");} +#endif void await_resume() const noexcept { PRINT ("susp-always-resume");} ~suspend_always_prt() { PRINT ("susp-always-dtor"); } }; @@ -46,7 +52,10 @@ struct coro1 { ~suspend_always_intprt() {} bool await_ready() const noexcept { return false; } void await_suspend(coro::coroutine_handle<>) const noexcept { PRINT ("susp-always-susp-intprt");} +#ifdef MISSING_AWAIT_RESUME +#else int await_resume() const noexcept { PRINT ("susp-always-resume-intprt"); return x;} +#endif }; /* This returns the square of the int that it was constructed with. */ -- 2.30.2