summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaCoroutine.cpp
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-03-11 02:35:37 +0000
committerEric Fiselier <eric@efcs.ca>2017-03-11 02:35:37 +0000
commitcac0a5971879533625fed92f6c7a9ff3c675cf55 (patch)
treebe512ab1006ed64f9d24996fc1c5578d47b05579 /clang/lib/Sema/SemaCoroutine.cpp
parent81d1744519129755e64cc9f262249f89fda81e85 (diff)
downloadbcm5719-llvm-cac0a5971879533625fed92f6c7a9ff3c675cf55.tar.gz
bcm5719-llvm-cac0a5971879533625fed92f6c7a9ff3c675cf55.zip
[coroutines] Fix diagnostics depending on the first coroutine statement.
Summary: Some coroutine diagnostics need to point to the location of the first coroutine keyword in the function, like when diagnosing a `return` inside a coroutine. Previously we did this by storing each *valid* coroutine statement in a list and select the first one to use in diagnostics. However if every coroutine statement is invalid we would have no location to point to. This patch fixes the storage of the first coroutine statement location, ensuring that it gets stored even when the resulting AST node would be invalid. This patch also removes the `CoroutineStmts` list in `FunctionScopeInfo` because it was unused. Reviewers: rsmith, GorNishanov, aaron.ballman Reviewed By: GorNishanov Subscribers: mehdi_amini, cfe-commits Differential Revision: https://reviews.llvm.org/D30776 llvm-svn: 297547
Diffstat (limited to 'clang/lib/Sema/SemaCoroutine.cpp')
-rw-r--r--clang/lib/Sema/SemaCoroutine.cpp35
1 files changed, 14 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 7bbb2f46e56..4d0f8a8f768 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -400,7 +400,8 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
/// Check that this is a context in which a coroutine suspension can appear.
static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
- StringRef Keyword) {
+ StringRef Keyword,
+ bool IsImplicit = false) {
if (!isValidCoroutineContext(S, Loc, Keyword))
return nullptr;
@@ -409,6 +410,9 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
auto *ScopeInfo = S.getCurFunction();
assert(ScopeInfo && "missing function scope for function");
+ if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)
+ ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);
+
if (ScopeInfo->CoroutinePromise)
return ScopeInfo;
@@ -488,7 +492,7 @@ ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
}
ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
- UnresolvedLookupExpr *Lookup) {
+ UnresolvedLookupExpr *Lookup) {
auto *FSI = checkCoroutineContext(*this, Loc, "co_await");
if (!FSI)
return ExprError();
@@ -504,7 +508,6 @@ ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
if (Promise->getType()->isDependentType()) {
Expr *Res =
new (Context) DependentCoawaitExpr(Loc, Context.DependentTy, E, Lookup);
- FSI->CoroutineStmts.push_back(Res);
return Res;
}
@@ -528,7 +531,7 @@ ExprResult Sema::BuildUnresolvedCoawaitExpr(SourceLocation Loc, Expr *E,
ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
bool IsImplicit) {
- auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await", IsImplicit);
if (!Coroutine)
return ExprError();
@@ -541,8 +544,6 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
if (E->getType()->isDependentType()) {
Expr *Res = new (Context)
CoawaitExpr(Loc, Context.DependentTy, E, IsImplicit);
- if (!IsImplicit)
- Coroutine->CoroutineStmts.push_back(Res);
return Res;
}
@@ -560,8 +561,7 @@ ExprResult Sema::BuildResolvedCoawaitExpr(SourceLocation Loc, Expr *E,
Expr *Res =
new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
RSS.Results[2], RSS.OpaqueValue, IsImplicit);
- if (!IsImplicit)
- Coroutine->CoroutineStmts.push_back(Res);
+
return Res;
}
@@ -597,7 +597,6 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
if (E->getType()->isDependentType()) {
Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
- Coroutine->CoroutineStmts.push_back(Res);
return Res;
}
@@ -614,7 +613,7 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
RSS.Results[2], RSS.OpaqueValue);
- Coroutine->CoroutineStmts.push_back(Res);
+
return Res;
}
@@ -628,7 +627,7 @@ StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
bool IsImplicit) {
- auto *FSI = checkCoroutineContext(*this, Loc, "co_return");
+ auto *FSI = checkCoroutineContext(*this, Loc, "co_return", IsImplicit);
if (!FSI)
return StmtError();
@@ -656,8 +655,6 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit);
- if (!IsImplicit)
- FSI->CoroutineStmts.push_back(Res);
return Res;
}
@@ -774,15 +771,11 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
// Coroutines [stmt.return]p1:
// A return statement shall not appear in a coroutine.
if (Fn->FirstReturnLoc.isValid()) {
+ assert(Fn->FirstCoroutineStmtLoc.isValid() &&
+ "first coroutine location not set");
Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
- // FIXME: Every Coroutine statement may be invalid and therefore not added
- // to CoroutineStmts. Find another way to provide location information.
- if (!Fn->CoroutineStmts.empty()) {
- auto *First = Fn->CoroutineStmts[0];
- Diag(First->getLocStart(), diag::note_declared_coroutine_here)
- << (isa<CoawaitExpr>(First) ? "co_await" :
- isa<CoyieldExpr>(First) ? "co_yield" : "co_return");
- }
+ Diag(Fn->FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
+ << Fn->getFirstCoroutineStmtKeyword();
}
SubStmtBuilder Builder(*this, *FD, *Fn, Body);
if (Builder.isInvalid())
OpenPOWER on IntegriCloud