Commit c75199b7 by JunMa

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.
parent 10502831
2020-01-22 Jun Ma <JunMa@linux.alibaba.com>
* 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 <jason@redhat.com> 2020-01-21 Jason Merrill <jason@redhat.com>
PR c++/60855 - ICE with sizeof VLA capture. PR c++/60855 - ICE with sizeof VLA capture.
......
...@@ -497,8 +497,8 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc, ...@@ -497,8 +497,8 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc,
tree promise = get_coroutine_promise_type (fndecl); tree promise = get_coroutine_promise_type (fndecl);
tree pm_memb tree pm_memb
= lookup_member (promise, member_id, = lookup_member (promise, member_id,
/*protect*/ 1, /*want_type*/ 0, tf_warning_or_error); /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
if (musthave && (pm_memb == NULL_TREE || pm_memb == error_mark_node)) if (musthave && pm_memb == NULL_TREE)
{ {
error_at (loc, "no member named %qE in %qT", member_id, promise); error_at (loc, "no member named %qE in %qT", member_id, promise);
return error_mark_node; return error_mark_node;
...@@ -506,6 +506,23 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc, ...@@ -506,6 +506,23 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc,
return pm_memb; 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 /* Here we check the constraints that are common to all keywords (since the
presence of a coroutine keyword makes the function into a coroutine). */ 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) ...@@ -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. */ /* Check for required awaitable members and their types. */
tree awrd_meth tree awrd_meth
= lookup_member (o_type, coro_await_ready_identifier, = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
/* protect */ 1, /*want_type=*/0, tf_warning_or_error);
if (!awrd_meth || awrd_meth == error_mark_node) if (!awrd_meth || awrd_meth == error_mark_node)
return error_mark_node; return error_mark_node;
tree awsp_meth tree awsp_meth
= lookup_member (o_type, coro_await_suspend_identifier, = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
/* protect */ 1, /*want_type=*/0, tf_warning_or_error);
if (!awsp_meth || awsp_meth == error_mark_node) if (!awsp_meth || awsp_meth == error_mark_node)
return error_mark_node; return error_mark_node;
/* The type of the co_await is the return type of the awaitable's /* 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 tree awrs_meth
= lookup_member (o_type, coro_await_resume_identifier, = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
/* protect */ 1, /*want_type=*/0, tf_warning_or_error);
if (!awrs_meth || awrs_meth == error_mark_node) if (!awrs_meth || awrs_meth == error_mark_node)
return error_mark_node; return error_mark_node;
......
2020-01-22 Jun Ma <JunMa@linux.alibaba.com>
* g++.dg/coroutines/coro1-missing-await-method.C: New test.
2020-01-21 Andrew Pinski <apinski@marvell.com> 2020-01-21 Andrew Pinski <apinski@marvell.com>
PR target/93119 PR target/93119
......
// { 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;
}
...@@ -27,14 +27,20 @@ struct coro1 { ...@@ -27,14 +27,20 @@ struct coro1 {
// Some awaitables to use in tests. // Some awaitables to use in tests.
// With progress printing for debug. // With progress printing for debug.
struct suspend_never_prt { struct suspend_never_prt {
#ifdef MISSING_AWAIT_READY
#else
bool await_ready() const noexcept { return true; } bool await_ready() const noexcept { return true; }
#endif
void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");} void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");}
void await_resume() const noexcept { PRINT ("susp-never-resume");} void await_resume() const noexcept { PRINT ("susp-never-resume");}
}; };
struct suspend_always_prt { struct suspend_always_prt {
bool await_ready() const noexcept { return false; } bool await_ready() const noexcept { return false; }
#ifdef MISSING_AWAIT_SUSPEND
#else
void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");} void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");}
#endif
void await_resume() const noexcept { PRINT ("susp-always-resume");} void await_resume() const noexcept { PRINT ("susp-always-resume");}
~suspend_always_prt() { PRINT ("susp-always-dtor"); } ~suspend_always_prt() { PRINT ("susp-always-dtor"); }
}; };
...@@ -46,7 +52,10 @@ struct coro1 { ...@@ -46,7 +52,10 @@ struct coro1 {
~suspend_always_intprt() {} ~suspend_always_intprt() {}
bool await_ready() const noexcept { return false; } bool await_ready() const noexcept { return false; }
void await_suspend(coro::coroutine_handle<>) const noexcept { PRINT ("susp-always-susp-intprt");} 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;} 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. */ /* This returns the square of the int that it was constructed with. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment