Commit fb882976 authored by Nico Weber's avatar Nico Weber
Browse files

[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
parent 503d061d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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<
+11 −3
Original line number Diff line number Diff line
@@ -175,8 +175,9 @@ public:
  /// 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 @@ public:

  void setHasCXXTry(SourceLocation TryLoc) {
    setHasBranchProtectedScope();
    FirstCXXTryLoc = TryLoc;
    FirstCXXOrObjCTryLoc = TryLoc;
    FirstTryType = TryLocIsCXX;
  }

  void setHasObjCTry(SourceLocation TryLoc) {
    setHasBranchProtectedScope();
    FirstCXXOrObjCTryLoc = TryLoc;
    FirstTryType = TryLocIsObjC;
  }

  void setHasSEHTry(SourceLocation TryLoc) {
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ void FunctionScopeInfo::Clear() {
  ObjCIsSecondaryInit = false;
  ObjCWarnForNoInitDelegation = false;
  FirstReturnLoc = SourceLocation();
  FirstCXXTryLoc = SourceLocation();
  FirstCXXOrObjCTryLoc = SourceLocation();
  FirstSEHTryLoc = SourceLocation();

  // Coroutine state
+15 −5
Original line number Diff line number Diff line
@@ -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'");
    }
  }

+25 −0
Original line number Diff line number Diff line
// 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 {
  }
}