SEH: Diagnose use of C++ EH and SEH in the same function

This check does not apply when Borland extensions are enabled, as they
have a checked in test case indicating that mixed usage of SEH and C++
is supported.

llvm-svn: 227876
This commit is contained in:
Reid Kleckner 2015-02-02 22:15:31 +00:00
parent 78b7d5fab2
commit e71759103e
5 changed files with 65 additions and 9 deletions

View File

@ -5447,6 +5447,10 @@ def err_exceptions_disabled : Error<
"cannot use '%0' with exceptions disabled">;
def err_objc_exceptions_disabled : Error<
"cannot use '%0' with Objective-C exceptions disabled">;
def err_mixing_cxx_try_seh_try : Error<
"cannot use C++ 'try' in the same function as SEH '__try'">;
def note_conflicting_try_here : Note<
"conflicting %0 here">;
def warn_non_virtual_dtor : Warning<
"%0 has virtual functions but non-virtual destructor">,
InGroup<NonVirtualDtor>, DefaultIgnore;

View File

@ -124,6 +124,12 @@ public:
/// false if there is an invocation of an initializer on 'self'.
bool ObjCWarnForNoInitDelegation;
/// First C++ 'try' statement in the current function.
SourceLocation FirstCXXTryLoc;
/// First SEH '__try' statement in the current function.
SourceLocation FirstSEHTryLoc;
/// \brief Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
@ -321,6 +327,16 @@ public:
HasDroppedStmt = true;
}
void setHasCXXTry(SourceLocation TryLoc) {
setHasBranchProtectedScope();
FirstCXXTryLoc = TryLoc;
}
void setHasSEHTry(SourceLocation TryLoc) {
setHasBranchProtectedScope();
FirstSEHTryLoc = TryLoc;
}
bool NeedsScopeChecking() const {
return !HasDroppedStmt &&
(HasIndirectGoto ||

View File

@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() {
ObjCWarnForNoDesignatedInitChain = false;
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
FirstCXXTryLoc = SourceLocation();
FirstSEHTryLoc = SourceLocation();
SwitchStack.clear();
Returns.clear();

View File

@ -3303,6 +3303,13 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
// C++ try is incompatible with SEH __try.
if (!getLangOpts().Borland && getCurFunction()->FirstSEHTryLoc.isValid()) {
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
Diag(getCurFunction()->FirstSEHTryLoc, diag::note_conflicting_try_here)
<< "'__try'";
}
const unsigned NumHandlers = Handlers.size();
assert(NumHandlers > 0 &&
"The parser shouldn't call this if there are no handlers.");
@ -3345,7 +3352,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
}
}
getCurFunction()->setHasBranchProtectedScope();
getCurFunction()->setHasCXXTry(TryLoc);
// FIXME: We should detect handlers that cannot catch anything because an
// earlier handler catches a superclass. Need to find a method that is not
@ -3356,16 +3363,21 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
}
StmtResult
Sema::ActOnSEHTryBlock(bool IsCXXTry,
SourceLocation TryLoc,
Stmt *TryBlock,
Stmt *Handler) {
StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
Stmt *TryBlock, Stmt *Handler) {
assert(TryBlock && Handler);
getCurFunction()->setHasBranchProtectedScope();
// SEH __try is incompatible with C++ try. Borland appears to support this,
// however.
if (!getLangOpts().Borland && getCurFunction()->FirstCXXTryLoc.isValid()) {
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
Diag(getCurFunction()->FirstCXXTryLoc, diag::note_conflicting_try_here)
<< "'try'";
}
return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler);
getCurFunction()->setHasSEHTry(TryLoc);
return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
}
StmtResult

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
// Basic usage should work.
int safe_div(int n, int d) {
@ -46,3 +46,25 @@ void inject_builtins() {
func_template<void *, __exception_info>();
func_template<unsigned long, __exception_code>();
}
void use_seh_after_cxx() {
try { // expected-note {{conflicting 'try' here}}
might_crash();
} catch (int) {
}
__try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}}
might_crash();
} __except(1) {
}
}
void use_cxx_after_seh() {
__try { // expected-note {{conflicting '__try' here}}
might_crash();
} __except(1) {
}
try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}}
might_crash();
} catch (int) {
}
}