forked from OSchip/llvm-project
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:
parent
78b7d5fab2
commit
e71759103e
|
@ -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;
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() {
|
|||
ObjCWarnForNoDesignatedInitChain = false;
|
||||
ObjCIsSecondaryInit = false;
|
||||
ObjCWarnForNoInitDelegation = false;
|
||||
FirstCXXTryLoc = SourceLocation();
|
||||
FirstSEHTryLoc = SourceLocation();
|
||||
|
||||
SwitchStack.clear();
|
||||
Returns.clear();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue