[coroutines] Per latest wording paper, co_* are no longer permitted in any

unevaluated operands.

llvm-svn: 253641
This commit is contained in:
Richard Smith 2015-11-20 02:54:01 +00:00
parent 2dfc3b8be5
commit 744b224bb5
3 changed files with 27 additions and 13 deletions

View File

@ -7960,6 +7960,8 @@ def note_declared_coroutine_here : Note<
"'%select{co_await|co_yield|co_return}0' here">; "'%select{co_await|co_yield|co_return}0' here">;
def err_coroutine_objc_method : Error< def err_coroutine_objc_method : Error<
"Objective-C methods as coroutines are not yet supported">; "Objective-C methods as coroutines are not yet supported">;
def err_coroutine_unevaluated_context : Error<
"'%0' cannot be used in an unevaluated context">;
def err_coroutine_outside_function : Error< def err_coroutine_outside_function : Error<
"'%0' cannot be used outside a function">; "'%0' cannot be used outside a function">;
def err_coroutine_ctor_dtor : Error< def err_coroutine_ctor_dtor : Error<

View File

@ -99,10 +99,11 @@ static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
/// Check that this is a context in which a coroutine suspension can appear. /// Check that this is a context in which a coroutine suspension can appear.
static FunctionScopeInfo * static FunctionScopeInfo *
checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) { checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
// 'co_await' and 'co_yield' are permitted in unevaluated operands. // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
// FIXME: Not in 'noexcept'. if (S.isUnevaluatedContext()) {
if (S.isUnevaluatedContext()) S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
return nullptr; return nullptr;
}
// Any other usage must be within a function. // Any other usage must be within a function.
auto *FD = dyn_cast<FunctionDecl>(S.CurContext); auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
@ -206,11 +207,12 @@ ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
} }
ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) { ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await"); auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
if (!Coroutine)
return ExprError();
if (E->getType()->isDependentType()) { if (E->getType()->isDependentType()) {
Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E); Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
if (Coroutine) Coroutine->CoroutineStmts.push_back(Res);
Coroutine->CoroutineStmts.push_back(Res);
return Res; return Res;
} }
@ -230,8 +232,7 @@ ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1], Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
RSS.Results[2]); RSS.Results[2]);
if (Coroutine) Coroutine->CoroutineStmts.push_back(Res);
Coroutine->CoroutineStmts.push_back(Res);
return Res; return Res;
} }
@ -244,11 +245,12 @@ ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
} }
ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
if (!Coroutine)
return ExprError();
// FIXME: Build await_* calls. // FIXME: Build await_* calls.
Expr *Res = new (Context) CoyieldExpr(Loc, Context.VoidTy, E); Expr *Res = new (Context) CoyieldExpr(Loc, Context.VoidTy, E);
if (Coroutine) Coroutine->CoroutineStmts.push_back(Res);
Coroutine->CoroutineStmts.push_back(Res);
return Res; return Res;
} }
@ -257,11 +259,12 @@ StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
} }
StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) { StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return"); auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
if (!Coroutine)
return StmtError();
// FIXME: Build return_* calls. // FIXME: Build return_* calls.
Stmt *Res = new (Context) CoreturnStmt(Loc, E); Stmt *Res = new (Context) CoreturnStmt(Loc, E);
if (Coroutine) Coroutine->CoroutineStmts.push_back(Res);
Coroutine->CoroutineStmts.push_back(Res);
return Res; return Res;
} }

View File

@ -78,8 +78,17 @@ struct CtorDtor {
} }
}; };
constexpr void constexpr_coroutine() { // expected-error {{never produces a constant expression}} void unevaluated() {
co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}} expected-note {{subexpression}} decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
}
constexpr void constexpr_coroutine() {
co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
} }
void varargs_coroutine(const char *, ...) { void varargs_coroutine(const char *, ...) {