forked from OSchip/llvm-project
Correctly reject gotos in function-level try blocks. PR14225.
llvm-svn: 167184
This commit is contained in:
parent
d9c2370b33
commit
1e95d4bb1e
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue