summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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