[gcc(refs/users/ppalka/heads/libstdcxx-constrained-algos)] Add error messages for missing methods of awaitable class

Patrick Palka ppalka@gcc.gnu.org
Sat Jan 25 22:49:00 GMT 2020


https://gcc.gnu.org/g:c75199b716ed54638ce8949d0f1f4ef71c0b31a5

commit c75199b716ed54638ce8949d0f1f4ef71c0b31a5
Author: JunMa <JunMa@linux.alibaba.com>
Date:   Thu Nov 21 08:51:22 2019 +0800

    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.

Diff:
---
 gcc/cp/ChangeLog                                   |  6 ++++
 gcc/cp/coroutines.cc                               | 36 ++++++++++++++--------
 gcc/testsuite/ChangeLog                            |  4 +++
 .../g++.dg/coroutines/coro1-missing-await-method.C | 21 +++++++++++++
 .../g++.dg/coroutines/coro1-ret-int-yield-int.h    |  9 ++++++
 5 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 04c5d2e..3f379d0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+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>
 
 	PR c++/60855 - ICE with sizeof VLA capture.
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index b99e721..6381fdc 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 1be1b59..08c81e1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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>
 
 	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 0000000..c1869e0
--- /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 b961755..abf6258 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.  */



More information about the Gcc-cvs mailing list