Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit dd4fdbe

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227876 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 00d7f4c commit dd4fdbe

File tree

5 files changed

+65
-9
lines changed

5 files changed

+65
-9
lines changed

Diff for: include/clang/Basic/DiagnosticSemaKinds.td

+4
Original file line numberDiff line numberDiff line change
@@ -5447,6 +5447,10 @@ def err_exceptions_disabled : Error<
54475447
"cannot use '%0' with exceptions disabled">;
54485448
def err_objc_exceptions_disabled : Error<
54495449
"cannot use '%0' with Objective-C exceptions disabled">;
5450+
def err_mixing_cxx_try_seh_try : Error<
5451+
"cannot use C++ 'try' in the same function as SEH '__try'">;
5452+
def note_conflicting_try_here : Note<
5453+
"conflicting %0 here">;
54505454
def warn_non_virtual_dtor : Warning<
54515455
"%0 has virtual functions but non-virtual destructor">,
54525456
InGroup<NonVirtualDtor>, DefaultIgnore;

Diff for: include/clang/Sema/ScopeInfo.h

+16
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ class FunctionScopeInfo {
124124
/// false if there is an invocation of an initializer on 'self'.
125125
bool ObjCWarnForNoInitDelegation;
126126

127+
/// First C++ 'try' statement in the current function.
128+
SourceLocation FirstCXXTryLoc;
129+
130+
/// First SEH '__try' statement in the current function.
131+
SourceLocation FirstSEHTryLoc;
132+
127133
/// \brief Used to determine if errors occurred in this function or block.
128134
DiagnosticErrorTrap ErrorTrap;
129135

@@ -321,6 +327,16 @@ class FunctionScopeInfo {
321327
HasDroppedStmt = true;
322328
}
323329

330+
void setHasCXXTry(SourceLocation TryLoc) {
331+
setHasBranchProtectedScope();
332+
FirstCXXTryLoc = TryLoc;
333+
}
334+
335+
void setHasSEHTry(SourceLocation TryLoc) {
336+
setHasBranchProtectedScope();
337+
FirstSEHTryLoc = TryLoc;
338+
}
339+
324340
bool NeedsScopeChecking() const {
325341
return !HasDroppedStmt &&
326342
(HasIndirectGoto ||

Diff for: lib/Sema/ScopeInfo.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() {
3333
ObjCWarnForNoDesignatedInitChain = false;
3434
ObjCIsSecondaryInit = false;
3535
ObjCWarnForNoInitDelegation = false;
36+
FirstCXXTryLoc = SourceLocation();
37+
FirstSEHTryLoc = SourceLocation();
3638

3739
SwitchStack.clear();
3840
Returns.clear();

Diff for: lib/Sema/SemaStmt.cpp

+20-8
Original file line numberDiff line numberDiff line change
@@ -3303,6 +3303,13 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
33033303
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
33043304
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
33053305

3306+
// C++ try is incompatible with SEH __try.
3307+
if (!getLangOpts().Borland && getCurFunction()->FirstSEHTryLoc.isValid()) {
3308+
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
3309+
Diag(getCurFunction()->FirstSEHTryLoc, diag::note_conflicting_try_here)
3310+
<< "'__try'";
3311+
}
3312+
33063313
const unsigned NumHandlers = Handlers.size();
33073314
assert(NumHandlers > 0 &&
33083315
"The parser shouldn't call this if there are no handlers.");
@@ -3345,7 +3352,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
33453352
}
33463353
}
33473354

3348-
getCurFunction()->setHasBranchProtectedScope();
3355+
getCurFunction()->setHasCXXTry(TryLoc);
33493356

33503357
// FIXME: We should detect handlers that cannot catch anything because an
33513358
// earlier handler catches a superclass. Need to find a method that is not
@@ -3356,16 +3363,21 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
33563363
return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers);
33573364
}
33583365

3359-
StmtResult
3360-
Sema::ActOnSEHTryBlock(bool IsCXXTry,
3361-
SourceLocation TryLoc,
3362-
Stmt *TryBlock,
3363-
Stmt *Handler) {
3366+
StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
3367+
Stmt *TryBlock, Stmt *Handler) {
33643368
assert(TryBlock && Handler);
33653369

3366-
getCurFunction()->setHasBranchProtectedScope();
3370+
// SEH __try is incompatible with C++ try. Borland appears to support this,
3371+
// however.
3372+
if (!getLangOpts().Borland && getCurFunction()->FirstCXXTryLoc.isValid()) {
3373+
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
3374+
Diag(getCurFunction()->FirstCXXTryLoc, diag::note_conflicting_try_here)
3375+
<< "'try'";
3376+
}
3377+
3378+
getCurFunction()->setHasSEHTry(TryLoc);
33673379

3368-
return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler);
3380+
return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
33693381
}
33703382

33713383
StmtResult

Diff for: test/SemaCXX/exceptions-seh.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
22

33
// Basic usage should work.
44
int safe_div(int n, int d) {
@@ -46,3 +46,25 @@ void inject_builtins() {
4646
func_template<void *, __exception_info>();
4747
func_template<unsigned long, __exception_code>();
4848
}
49+
50+
void use_seh_after_cxx() {
51+
try { // expected-note {{conflicting 'try' here}}
52+
might_crash();
53+
} catch (int) {
54+
}
55+
__try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}}
56+
might_crash();
57+
} __except(1) {
58+
}
59+
}
60+
61+
void use_cxx_after_seh() {
62+
__try { // expected-note {{conflicting '__try' here}}
63+
might_crash();
64+
} __except(1) {
65+
}
66+
try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}}
67+
might_crash();
68+
} catch (int) {
69+
}
70+
}

0 commit comments

Comments
 (0)