]> granicus.if.org Git - clang/commitdiff
[coroutines] Check for overload sets in co_yield / co_return operands being resolved...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 22 Nov 2015 07:33:28 +0000 (07:33 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 22 Nov 2015 07:33:28 +0000 (07:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253817 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCoroutine.cpp
test/SemaCXX/coroutines.cpp

index b1dfd6693838b588e88c1032d91b221e4f0432f8..2e56938c31cfcc24ea269ee9749081fe4923424a 100644 (file)
@@ -52,6 +52,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
   Args.addArgument(TemplateArgumentLoc(
       TemplateArgument(FnType->getReturnType()),
       S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc)));
+  // FIXME: If the function is a non-static member function, add the type
+  // of the implicit object parameter before the formal parameters.
   for (QualType T : FnType->getParamTypes())
     Args.addArgument(TemplateArgumentLoc(
         TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
@@ -270,12 +272,6 @@ static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
 }
 
 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
-  if (E->getType()->isPlaceholderType()) {
-    ExprResult R = CheckPlaceholderExpr(E);
-    if (R.isInvalid()) return ExprError();
-    E = R.get();
-  }
-
   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
   if (!Coroutine)
     return ExprError();
@@ -330,16 +326,17 @@ StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
   return BuildCoreturnStmt(Loc, E);
 }
 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
-  if (E && E->getType()->isPlaceholderType()) {
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+  if (!Coroutine)
+    return StmtError();
+
+  if (E && E->getType()->isPlaceholderType() &&
+      !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
     ExprResult R = CheckPlaceholderExpr(E);
     if (R.isInvalid()) return StmtError();
     E = R.get();
   }
 
-  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
-  if (!Coroutine)
-    return StmtError();
-
   // FIXME: If the operand is a reference to a variable that's about to go out
   // ot scope, we should treat the operand as an xvalue for this overload
   // resolution.
index 85cc919c6d19aa9712eda1f832526dd7c46aa2d4..af50eabb2454fe48bbd92505fe6cb0ccae0740b5 100644 (file)
@@ -49,11 +49,11 @@ struct yielded_thing { const char *p; short a, b; };
 struct not_awaitable {};
 
 struct promise {
-  awaitable yield_value(int); // expected-note {{candidate}}
-  awaitable yield_value(yielded_thing); // expected-note {{candidate}}
-  not_awaitable yield_value(void()); // expected-note {{candidate}}
+  awaitable yield_value(int); // expected-note 2{{candidate}}
+  awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
+  not_awaitable yield_value(void()); // expected-note 2{{candidate}}
   void return_void();
-  void return_value(int); // expected-note {{here}}
+  void return_value(int); // expected-note 2{{here}}
 };
 
 void yield() {
@@ -159,17 +159,37 @@ namespace dependent_operator_co_await_lookup {
   template void await_template_2(outer);
 }
 
+struct yield_fn_tag {};
+template<> struct std::coroutine_traits<void, yield_fn_tag> {
+  struct promise_type {
+    // FIXME: add an await_transform overload for functions
+    awaitable yield_value(int());
+    void return_value(int());
+  };
+};
+
 namespace placeholder {
-  awaitable f(), f(int); // expected-note 2{{possible target}}
-  int g(), g(int); // expected-note 4{{possible target}}
+  awaitable f(), f(int); // expected-note 4{{possible target}}
+  int g(), g(int); // expected-note 2{{candidate}}
   void x() {
     co_await f; // expected-error {{reference to overloaded function}}
   }
   void y() {
-    co_yield g; // expected-error {{reference to overloaded function}}
+    co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
   }
   void z() {
     co_await a;
-    co_return g; // expected-error {{reference to overloaded function}}
+    co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
+  }
+
+  void x(yield_fn_tag) {
+    co_await f; // expected-error {{reference to overloaded function}}
+  }
+  void y(yield_fn_tag) {
+    co_yield g;
+  }
+  void z(yield_fn_tag) {
+    co_await a;
+    co_return g;
   }
 }