From: Richard Smith Date: Sun, 22 Nov 2015 07:33:28 +0000 (+0000) Subject: [coroutines] Check for overload sets in co_yield / co_return operands being resolved... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a064028e17c5818cce57e9d57c85e23c4c26f525;p=clang [coroutines] Check for overload sets in co_yield / co_return operands being resolved by a call to yield_value / return_value before rejecting them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253817 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index b1dfd66938..2e56938c31 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/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/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index 85cc919c6d..af50eabb24 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/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 { + 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; } }