diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-10-31 23:55:28 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-10-31 23:55:28 +0000 |
commit | 889b99e6d5b389c0ed99e7ad8470c28b146a42d3 (patch) | |
tree | fb1ae55200b31f5d92e19c00d957a4db7da37453 | |
parent | bbb751a1788c461bc9765ec3387536cad6b52619 (diff) |
Correctly reject gotos in function-level try blocks. PR14225.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167184 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 47 | ||||
-rw-r--r-- | test/SemaCXX/scope-check.cpp | 18 |
2 files changed, 39 insertions, 26 deletions
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index a76a552e2e..e2ec1ccebd 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -332,6 +332,29 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) Jumps.push_back(S); break; + case Stmt::CXXTryStmtClass: { + CXXTryStmt *TS = cast<CXXTryStmt>(S); + unsigned newParentScope; + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_try, + diag::note_exits_cxx_try, + TS->getSourceRange().getBegin())); + if (Stmt *TryBlock = TS->getTryBlock()) + BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); + + // Jump from the catch into the try is not allowed either. + for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *CS = TS->getHandler(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_catch, + diag::note_exits_cxx_catch, + CS->getSourceRange().getBegin())); + BuildScopeInformation(CS->getHandlerBlock(), + (newParentScope = Scopes.size()-1)); + } + return; + } + default: break; } @@ -428,30 +451,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) continue; } - // Disallow jumps into any part of a C++ try statement. This is pretty - // much the same as for Obj-C. - if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) { - Scopes.push_back(GotoScope(ParentScope, - diag::note_protected_by_cxx_try, - diag::note_exits_cxx_try, - TS->getSourceRange().getBegin())); - if (Stmt *TryBlock = TS->getTryBlock()) - BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); - - // Jump from the catch into the try is not allowed either. - for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { - CXXCatchStmt *CS = TS->getHandler(I); - Scopes.push_back(GotoScope(ParentScope, - diag::note_protected_by_cxx_catch, - diag::note_exits_cxx_catch, - CS->getSourceRange().getBegin())); - BuildScopeInformation(CS->getHandlerBlock(), - (newParentScope = Scopes.size()-1)); - } - - continue; - } - // Disallow jumps into the protected statement of an @autoreleasepool. if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){ // Recursively walk the AST for the @autoreleasepool part, protected by a new diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index 78228c0dc5..8fd23f4efe 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-unreachable-code -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++11 %s -Wno-unreachable-code +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions %s -Wno-unreachable-code +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions -std=gnu++11 %s -Wno-unreachable-code namespace test0 { struct D { ~D(); }; @@ -260,3 +260,17 @@ namespace test14 { goto *ip; } } + +// PR14225 +namespace test15 { + void f1() try { + goto x; // expected-error {{goto into protected scope}} + } catch(...) { // expected-note {{jump bypasses initialization of catch block}} + x: ; + } + void f2() try { // expected-note {{jump bypasses initialization of try block}} + x: ; + } catch(...) { + goto x; // expected-error {{goto into protected scope}} + } +} |