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 { + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits