[clang] fb88297 - [clang] Disallow mixing SEH and Objective-C exceptions
Nico Weber via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 20 11:18:34 PDT 2021
Author: Nico Weber
Date: 2021-10-20T14:18:12-04:00
New Revision: fb8829768d774689c368c49cb3ca17339378cd91
URL: https://github.com/llvm/llvm-project/commit/fb8829768d774689c368c49cb3ca17339378cd91
DIFF: https://github.com/llvm/llvm-project/commit/fb8829768d774689c368c49cb3ca17339378cd91.diff
LOG: [clang] Disallow mixing SEH and Objective-C exceptions
We already disallow mixing SEH and C++ exceptions, and
mixing SEH and Objective-C exceptions seems to not work (see PR52233).
Emitting an error is friendlier than crashing.
Differential Revision: https://reviews.llvm.org/D112157
Added:
clang/test/SemaCXX/exceptions-seh.mm
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/ScopeInfo.h
clang/lib/Sema/ScopeInfo.cpp
clang/lib/Sema/SemaStmt.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e0c36961a9124..13f8fc3de03ca 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7516,7 +7516,8 @@ def note_throw_in_function : Note<"function declared non-throwing here">;
def err_seh_try_outside_functions : Error<
"cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
def err_mixing_cxx_try_seh_try : Error<
- "cannot use C++ 'try' in the same function as SEH '__try'">;
+ "cannot use %select{C++ 'try'|Objective-C '@try'}0 "
+ "in the same function as SEH '__try'">;
def err_seh_try_unsupported : Error<
"SEH '__try' is not supported on this target">;
def note_conflicting_try_here : Note<
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 5c3bfe7e80cdc..ccd15ea6a818f 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -175,8 +175,9 @@ class FunctionScopeInfo {
/// First 'return' statement in the current function.
SourceLocation FirstReturnLoc;
- /// First C++ 'try' statement in the current function.
- SourceLocation FirstCXXTryLoc;
+ /// First C++ 'try' or ObjC @try statement in the current function.
+ SourceLocation FirstCXXOrObjCTryLoc;
+ enum { TryLocIsCXX, TryLocIsObjC, Unknown } FirstTryType = Unknown;
/// First SEH '__try' statement in the current function.
SourceLocation FirstSEHTryLoc;
@@ -446,7 +447,14 @@ class FunctionScopeInfo {
void setHasCXXTry(SourceLocation TryLoc) {
setHasBranchProtectedScope();
- FirstCXXTryLoc = TryLoc;
+ FirstCXXOrObjCTryLoc = TryLoc;
+ FirstTryType = TryLocIsCXX;
+ }
+
+ void setHasObjCTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstCXXOrObjCTryLoc = TryLoc;
+ FirstTryType = TryLocIsObjC;
}
void setHasSEHTry(SourceLocation TryLoc) {
diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp
index 4857346018ae4..cc7de16de2fdb 100644
--- a/clang/lib/Sema/ScopeInfo.cpp
+++ b/clang/lib/Sema/ScopeInfo.cpp
@@ -37,7 +37,7 @@ void FunctionScopeInfo::Clear() {
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
FirstReturnLoc = SourceLocation();
- FirstCXXTryLoc = SourceLocation();
+ FirstCXXOrObjCTryLoc = SourceLocation();
FirstSEHTryLoc = SourceLocation();
// Coroutine state
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index c83ada89d2e07..dc564e318d82d 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -4187,7 +4187,14 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
if (!getLangOpts().ObjCExceptions)
Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
- setFunctionHasBranchProtectedScope();
+ // Objective-C try is incompatible with SEH __try.
+ sema::FunctionScopeInfo *FSI = getCurFunction();
+ if (FSI->FirstSEHTryLoc.isValid()) {
+ Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1;
+ Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
+ }
+
+ FSI->setHasObjCTry(AtLoc);
unsigned NumCatchStmts = CatchStmts.size();
return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
@@ -4423,7 +4430,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
// C++ try is incompatible with SEH __try.
if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) {
- Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
+ Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << 0;
Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
}
@@ -4507,9 +4514,12 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
// SEH __try is incompatible with C++ try. Borland appears to support this,
// however.
if (!getLangOpts().Borland) {
- if (FSI->FirstCXXTryLoc.isValid()) {
- Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
- Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'";
+ if (FSI->FirstCXXOrObjCTryLoc.isValid()) {
+ Diag(TryLoc, diag::err_mixing_cxx_try_seh_try) << FSI->FirstTryType;
+ Diag(FSI->FirstCXXOrObjCTryLoc, diag::note_conflicting_try_here)
+ << (FSI->FirstTryType == sema::FunctionScopeInfo::TryLocIsCXX
+ ? "'try'"
+ : "'@try'");
}
}
diff --git a/clang/test/SemaCXX/exceptions-seh.mm b/clang/test/SemaCXX/exceptions-seh.mm
new file mode 100644
index 0000000000000..5efa3c3d91f82
--- /dev/null
+++ b/clang/test/SemaCXX/exceptions-seh.mm
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fobjc-exceptions -verify %s
+
+void might_crash();
+
+void use_seh_after_objc() {
+ @try { // expected-note {{conflicting '@try' here}}
+ might_crash();
+ } @finally {
+ }
+ __try { // expected-error {{cannot use Objective-C '@try' in the same function as SEH '__try'}}
+ might_crash();
+ } __except(1) {
+ }
+}
+
+void use_objc_after_seh() {
+ __try { // expected-note {{conflicting '__try' here}}
+ might_crash();
+ } __except(1) {
+ }
+ @try { // expected-error {{cannot use Objective-C '@try' in the same function as SEH '__try'}}
+ might_crash();
+ } @finally {
+ }
+}
More information about the cfe-commits
mailing list