summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2015-03-09 02:47:59 +0000
committerNico Weber <nicolasweber@gmx.de>2015-03-09 02:47:59 +0000
commitd64657f2989f0e1e279f1ad8a03f627b4b60f407 (patch)
tree771755984c567efb57fd15d7c16b463fbd2501e7 /clang/lib/Sema/SemaStmt.cpp
parent9af63b22a5e5e3f5dc921dc987ccf96dabb87b43 (diff)
downloadbcm5719-llvm-d64657f2989f0e1e279f1ad8a03f627b4b60f407.tar.gz
bcm5719-llvm-d64657f2989f0e1e279f1ad8a03f627b4b60f407.zip
Warn when jumping out of a __finally block via continue, break, return, __leave.
Since continue, break, return are much more common than __finally, this tries to keep the work for continue, break, return O(1). Sema keeps a stack of active __finally scopes (to do this, ActOnSEHFinally() is split into ActOnStartSEHFinally() and ActOnFinishSEHFinally()), and the various jump statements then check if the current __finally scope (if present) is deeper than then destination scope of the jump. The same warning for goto statements is still missing. This is the moral equivalent of MSVC's C4532. llvm-svn: 231623
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
-rw-r--r--clang/lib/Sema/SemaStmt.cpp24
1 files changed, 20 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index aaf29db702c..11ec4f5321e 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2428,6 +2428,14 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}
+static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc,
+ const Scope &DestScope) {
+ if (!S.CurrentSEHFinally.empty() &&
+ DestScope.Contains(*S.CurrentSEHFinally.back())) {
+ S.Diag(Loc, diag::warn_jump_out_of_seh_finally);
+ }
+}
+
StmtResult
Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
Scope *S = CurScope->getContinueParent();
@@ -2435,6 +2443,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
// C99 6.8.6.2p1: A break shall appear only in or as a loop body.
return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
}
+ CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S);
return new (Context) ContinueStmt(ContinueLoc);
}
@@ -2449,6 +2458,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
if (S->isOpenMPLoopScope())
return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt)
<< "break");
+ CheckJumpOutOfSEHFinally(*this, BreakLoc, *S);
return new (Context) BreakStmt(BreakLoc);
}
@@ -2908,6 +2918,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
CurScope->setNoNRVO();
}
+ CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
+
return R;
}
@@ -3406,11 +3418,14 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc,
return SEHExceptStmt::Create(Context,Loc,FilterExpr,Block);
}
-StmtResult
-Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
- Stmt *Block) {
+void Sema::ActOnStartSEHFinallyBlock() {
+ CurrentSEHFinally.push_back(CurScope);
+}
+
+StmtResult Sema::ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block) {
assert(Block);
- return SEHFinallyStmt::Create(Context,Loc,Block);
+ CurrentSEHFinally.pop_back();
+ return SEHFinallyStmt::Create(Context, Loc, Block);
}
StmtResult
@@ -3420,6 +3435,7 @@ Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) {
SEHTryParent = SEHTryParent->getParent();
if (!SEHTryParent)
return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));
+ CheckJumpOutOfSEHFinally(*this, Loc, *SEHTryParent);
return new (Context) SEHLeaveStmt(Loc);
}
OpenPOWER on IntegriCloud