summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2015-03-09 04:27:56 +0000
committerNico Weber <nicolasweber@gmx.de>2015-03-09 04:27:56 +0000
commiteb0cfb5ab0bcd3c794aaf1425b38ef165d64eabb (patch)
treef11cdd887e6b2a8feae59ebb743cd3dbe48393f4
parent5768e9fde95e03a0fc5388a7814670cee1ae21e9 (diff)
downloadbcm5719-llvm-eb0cfb5ab0bcd3c794aaf1425b38ef165d64eabb.tar.gz
bcm5719-llvm-eb0cfb5ab0bcd3c794aaf1425b38ef165d64eabb.zip
Warn when jumping out of a __finally block via goto.
This only warns on direct gotos and indirect gotos with a unique label (`goto *&&label;`). Jumping out ith a true indirect goto is already an error. This isn't O(1), but goto statements are less common than continue, break, and return. Also, the GetDeepestCommonScope() call in the same function does the same amount of work, so this isn't worse than what's there in a complexity sense, and it should be pretty fast in practice. This is the last piece that was missing in r231623. llvm-svn: 231628
-rw-r--r--clang/lib/Sema/JumpDiagnostics.cpp12
-rw-r--r--clang/test/SemaCXX/scope-check.cpp18
2 files changed, 20 insertions, 10 deletions
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index 03fcc9482e0..aac28bedfa5 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -789,6 +789,18 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
// Common case: exactly the same scope, which is fine.
if (FromScope == ToScope) return;
+ // Warn on gotos out of __finally blocks.
+ if (isa<GotoStmt>(From) || isa<IndirectGotoStmt>(From)) {
+ // If FromScope > ToScope, FromScope is more nested and the jump goes to a
+ // less nested scope. Check if it crosses a __finally along the way.
+ for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) {
+ if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
+ S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally);
+ break;
+ }
+ }
+ }
+
unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);
// It's okay to jump out from a nested scope.
diff --git a/clang/test/SemaCXX/scope-check.cpp b/clang/test/SemaCXX/scope-check.cpp
index c7638aea106..1d2893c7e00 100644
--- a/clang/test/SemaCXX/scope-check.cpp
+++ b/clang/test/SemaCXX/scope-check.cpp
@@ -507,12 +507,12 @@ out_of_finally_try:
__try {
} __finally {
- // FIXME: This should warn that jumping out of __finally has undefined
- // behavior.
- // FIXME: Once that warns, check that
- // __try { __try {} __finally { __leave; } } __except (0) {}
- // warns in the same way.
- goto out_of_finally_finally;
+ goto out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
+ }
+
+ __try {
+ } __finally {
+ goto *&&out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
}
out_of_finally_finally:
;
@@ -548,7 +548,7 @@ void jump_try_finally() {
from_finally_to_try:
;
} __finally {
- goto from_finally_to_try; // expected-error {{cannot jump from this goto statement to its label}}
+ goto from_finally_to_try; // expected-error {{cannot jump from this goto statement to its label}} expected-warning {{jump out of __finally block has undefined behavior}}
}
}
@@ -578,9 +578,7 @@ void nested() {
__try {
__try {
} __finally {
- // FIXME: This should warn that jumping out of __finally has undefined
- // behavior.
- goto after_outer_except;
+ goto after_outer_except; // expected-warning {{jump out of __finally block has undefined behavior}}
}
} __except(0) {
}
OpenPOWER on IntegriCloud