diff options
-rw-r--r-- | clang/lib/Sema/JumpDiagnostics.cpp | 12 | ||||
-rw-r--r-- | clang/test/SemaCXX/scope-check.cpp | 18 |
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) { } |