summaryrefslogtreecommitdiff
path: root/lib/Sema/JumpDiagnostics.cpp
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2015-02-03 17:06:08 +0000
committerNico Weber <nicolasweber@gmx.de>2015-02-03 17:06:08 +0000
commit2c7b0780fa661ec22dacfb34070f578198c65806 (patch)
treeb6e30a0adba8882d66d78df0e8d5a82ac6ea45cc /lib/Sema/JumpDiagnostics.cpp
parent620d7d7b07654b3e97f3805e23e533e8142f9f66 (diff)
downloadclang-2c7b0780fa661ec22dacfb34070f578198c65806.tar.gz
Implement jump scope SEHmantic analysis.
Thou shall not jump into SEH blocks. Jumping out of SEH __try and __excepts is A-ok. Jumping out of __finally blocks is B-ok (msvc doesn't error about it, but warns that it has undefined behavior). I've checked that clang's behavior with this patch matches msvc's behavior. We don't have the warning on jumping out of a __finally yet, see the FIXME in the test. clang also currently crashes on codegen for a jump out of a __finally block, see PR22414 comment 7. I also added a few tests for the interaction of indirect jumps and SEH blocks. MSVC doesn't support indirect jumps, so there's no way to know if clang behave the same way as msvc here. clang's behavior with this patch does make sense to me, but maybe it could be argued that it should be more permissive (see FIXME in the indirect jump tests -- shout if you have an opinion on this). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/JumpDiagnostics.cpp')
-rw-r--r--lib/Sema/JumpDiagnostics.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 9a9215174b..ac8733fe19 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -338,9 +338,35 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
return;
}
- case Stmt::SEHTryStmtClass:
- // FIXME: Implement jump diagnostics for bad SEH jumps.
- break;
+ case Stmt::SEHTryStmtClass: {
+ SEHTryStmt *TS = cast<SEHTryStmt>(S);
+ unsigned newParentScope;
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_try,
+ diag::note_exits_seh_try,
+ TS->getSourceRange().getBegin()));
+ if (Stmt *TryBlock = TS->getTryBlock())
+ BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1));
+
+ // Jump from __except or __finally into the __try are not allowed either.
+ if (SEHExceptStmt *Except = TS->getExceptHandler()) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_except,
+ diag::note_exits_seh_except,
+ Except->getSourceRange().getBegin()));
+ BuildScopeInformation(Except->getBlock(),
+ (newParentScope = Scopes.size()-1));
+ } else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_seh_finally,
+ diag::note_exits_seh_finally,
+ Finally->getSourceRange().getBegin()));
+ BuildScopeInformation(Finally->getBlock(),
+ (newParentScope = Scopes.size()-1));
+ }
+
+ return;
+ }
default:
break;