EricWF created this revision.

@rsmith Does this correctly address the issues mentioned in 
https://reviews.llvm.org/D33625#inline-292971 ?


https://reviews.llvm.org/D33636

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaCoroutine.cpp
  test/SemaCXX/coroutines.cpp


Index: test/SemaCXX/coroutines.cpp
===================================================================
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -840,12 +840,12 @@
 
 struct bad_await_suspend_return {
   bool await_ready();
-  // expected-error@+1 {{the return type of 'await_suspend' is required to be 
'void' or 'bool' (have 'char')}}
+  // expected-error@+1 {{return type of 'await_suspend' is required to be 
'void' or 'bool' (have 'char')}}
   char await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
 };
 struct bad_await_ready_return {
-  // expected-note@+1 {{the return type of 'await_ready' is required to be 
contextually convertible to 'bool'}}
+  // expected-note@+1 {{return type of 'await_ready' is required to be 
contextually convertible to 'bool'}}
   void await_ready();
   bool await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
@@ -858,6 +858,14 @@
   void await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
 };
+template <class SuspendTy>
+struct await_suspend_type_test {
+  bool await_ready();
+  // expected-error@+2 {{return type of 'await_suspend' is required to be 
'void' or 'bool' (have 'bool &')}}
+  // expected-error@+1 {{return type of 'await_suspend' is required to be 
'void' or 'bool' (have 'bool &&')}}
+  SuspendTy await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
 void test_bad_suspend() {
   {
     // FIXME: The actual error emitted here is terrible, and no number of 
notes can save it.
@@ -873,4 +881,14 @@
     await_ready_explicit_bool c;
     co_await c; // OK
   }
+  {
+    await_suspend_type_test<bool &&> a;
+    await_suspend_type_test<bool &> b;
+    await_suspend_type_test<const void> c;
+    await_suspend_type_test<const volatile bool> d;
+    co_await a; // expected-note {{call to 'await_suspend' implicitly required 
by coroutine function here}}
+    co_await b; // expected-note {{call to 'await_suspend' implicitly required 
by coroutine function here}}
+    co_await c; // OK
+    co_await d; // OK
+  }
 }
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -391,8 +391,11 @@
     // [expr.await]p3 [...]
     //   - await-suspend is the expression e.await_suspend(h), which shall be
     //     a prvalue of type void or bool.
-    QualType RetType = AwaitSuspend->getType();
-    if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) {
+    QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
+    // non-class prvalues always have cv-unqualified types
+    QualType AdjRetType = RetType.getUnqualifiedType();
+    if (RetType->isReferenceType() ||
+        (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
       S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
              diag::err_await_suspend_invalid_return_type)
           << RetType;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -8974,10 +8974,10 @@
 def note_coroutine_promise_call_implicitly_required : Note<
   "call to %0 implicitly required by coroutine function here">;
 def err_await_suspend_invalid_return_type : Error<
-  "the return type of 'await_suspend' is required to be 'void' or 'bool' (have 
%0)"
+  "return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
 >;
 def note_await_ready_no_bool_conversion : Note<
-  "the return type of 'await_ready' is required to be contextually convertible 
to 'bool'"
+  "return type of 'await_ready' is required to be contextually convertible to 
'bool'"
 >;
 }
 


Index: test/SemaCXX/coroutines.cpp
===================================================================
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -840,12 +840,12 @@
 
 struct bad_await_suspend_return {
   bool await_ready();
-  // expected-error@+1 {{the return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
+  // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
   char await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
 };
 struct bad_await_ready_return {
-  // expected-note@+1 {{the return type of 'await_ready' is required to be contextually convertible to 'bool'}}
+  // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
   void await_ready();
   bool await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
@@ -858,6 +858,14 @@
   void await_suspend(std::experimental::coroutine_handle<>);
   void await_resume();
 };
+template <class SuspendTy>
+struct await_suspend_type_test {
+  bool await_ready();
+  // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
+  // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
+  SuspendTy await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
 void test_bad_suspend() {
   {
     // FIXME: The actual error emitted here is terrible, and no number of notes can save it.
@@ -873,4 +881,14 @@
     await_ready_explicit_bool c;
     co_await c; // OK
   }
+  {
+    await_suspend_type_test<bool &&> a;
+    await_suspend_type_test<bool &> b;
+    await_suspend_type_test<const void> c;
+    await_suspend_type_test<const volatile bool> d;
+    co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
+    co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
+    co_await c; // OK
+    co_await d; // OK
+  }
 }
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -391,8 +391,11 @@
     // [expr.await]p3 [...]
     //   - await-suspend is the expression e.await_suspend(h), which shall be
     //     a prvalue of type void or bool.
-    QualType RetType = AwaitSuspend->getType();
-    if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) {
+    QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
+    // non-class prvalues always have cv-unqualified types
+    QualType AdjRetType = RetType.getUnqualifiedType();
+    if (RetType->isReferenceType() ||
+        (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
       S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
              diag::err_await_suspend_invalid_return_type)
           << RetType;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -8974,10 +8974,10 @@
 def note_coroutine_promise_call_implicitly_required : Note<
   "call to %0 implicitly required by coroutine function here">;
 def err_await_suspend_invalid_return_type : Error<
-  "the return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
+  "return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
 >;
 def note_await_ready_no_bool_conversion : Note<
-  "the return type of 'await_ready' is required to be contextually convertible to 'bool'"
+  "return type of 'await_ready' is required to be contextually convertible to 'bool'"
 >;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D33636: [coroutines]... Eric Fiselier via Phabricator via cfe-commits

Reply via email to