diff options
| -rw-r--r-- | clang/lib/Sema/SemaCoroutine.cpp | 19 | ||||
| -rw-r--r-- | clang/test/SemaCXX/coroutines.cpp | 36 | 
2 files changed, 36 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index b1dfd669383..2e56938c31c 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -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. diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index 85cc919c6d1..af50eabb245 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -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;    }  }  | 

