forked from OSchip/llvm-project
Re-land r228258 and make clang-cl's /EHs- disable -fexceptions again
After r228258, Clang started emitting C++ EH IR that LLVM wasn't ready to deal with, even when exceptions were disabled with /EHs-. This time, make /EHs- turn off -fexceptions while still emitting exceptional constructs in functions using __try. Since Sema rejects C++ exception handling constructs before CodeGen, landingpads should only appear in such functions as the result of a __try. llvm-svn: 228329
This commit is contained in:
parent
c9dd02066c
commit
deeddeced3
|
@ -1482,6 +1482,9 @@ private:
|
|||
bool IsLateTemplateParsed : 1;
|
||||
bool IsConstexpr : 1;
|
||||
|
||||
/// \brief Indicates if the function uses __try.
|
||||
bool UsesSEHTry : 1;
|
||||
|
||||
/// \brief Indicates if the function was a definition but its body was
|
||||
/// skipped.
|
||||
unsigned HasSkippedBody : 1;
|
||||
|
@ -1570,8 +1573,8 @@ protected:
|
|||
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
|
||||
IsDefaulted(false), IsExplicitlyDefaulted(false),
|
||||
HasImplicitReturnZero(false), IsLateTemplateParsed(false),
|
||||
IsConstexpr(isConstexprSpecified), HasSkippedBody(false),
|
||||
EndRangeLoc(NameInfo.getEndLoc()),
|
||||
IsConstexpr(isConstexprSpecified), UsesSEHTry(false),
|
||||
HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()),
|
||||
TemplateOrSpecialization(),
|
||||
DNLoc(NameInfo.getInfo()) {}
|
||||
|
||||
|
@ -1751,6 +1754,10 @@ public:
|
|||
bool isConstexpr() const { return IsConstexpr; }
|
||||
void setConstexpr(bool IC) { IsConstexpr = IC; }
|
||||
|
||||
/// Whether this is a (C++11) constexpr function or constexpr constructor.
|
||||
bool usesSEHTry() const { return UsesSEHTry; }
|
||||
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
|
||||
|
||||
/// \brief Whether this function has been deleted.
|
||||
///
|
||||
/// A function that is "deleted" (via the C++0x "= delete" syntax)
|
||||
|
|
|
@ -5466,6 +5466,8 @@ 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_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'">;
|
||||
def note_conflicting_try_here : Note<
|
||||
|
|
|
@ -128,7 +128,12 @@ namespace {
|
|||
// This function must have prototype void(void*).
|
||||
const char *CatchallRethrowFn;
|
||||
|
||||
static const EHPersonality &get(CodeGenModule &CGM);
|
||||
static const EHPersonality &get(CodeGenModule &CGM,
|
||||
const FunctionDecl *FD);
|
||||
static const EHPersonality &get(CodeGenFunction &CGF) {
|
||||
return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
|
||||
}
|
||||
|
||||
static const EHPersonality GNU_C;
|
||||
static const EHPersonality GNU_C_SJLJ;
|
||||
static const EHPersonality GNU_C_SEH;
|
||||
|
@ -141,6 +146,7 @@ namespace {
|
|||
static const EHPersonality GNU_CPlusPlus_SEH;
|
||||
static const EHPersonality MSVC_except_handler;
|
||||
static const EHPersonality MSVC_C_specific_handler;
|
||||
static const EHPersonality MSVC_CxxFrameHandler3;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -167,6 +173,8 @@ const EHPersonality
|
|||
EHPersonality::MSVC_except_handler = { "_except_handler3", nullptr };
|
||||
const EHPersonality
|
||||
EHPersonality::MSVC_C_specific_handler = { "__C_specific_handler", nullptr };
|
||||
const EHPersonality
|
||||
EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr };
|
||||
|
||||
/// On Win64, use libgcc's SEH personality function. We fall back to dwarf on
|
||||
/// other platforms, unless the user asked for SjLj exceptions.
|
||||
|
@ -239,35 +247,27 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
|
|||
llvm_unreachable("bad runtime kind");
|
||||
}
|
||||
|
||||
static const EHPersonality &getCPersonalityMSVC(const llvm::Triple &T,
|
||||
const LangOptions &L) {
|
||||
if (L.SjLjExceptions)
|
||||
return EHPersonality::GNU_C_SJLJ;
|
||||
|
||||
static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) {
|
||||
if (T.getArch() == llvm::Triple::x86)
|
||||
return EHPersonality::MSVC_except_handler;
|
||||
return EHPersonality::MSVC_C_specific_handler;
|
||||
}
|
||||
|
||||
static const EHPersonality &getCXXPersonalityMSVC(const llvm::Triple &T,
|
||||
const LangOptions &L) {
|
||||
if (L.SjLjExceptions)
|
||||
return EHPersonality::GNU_CPlusPlus_SJLJ;
|
||||
// FIXME: Implement C++ exceptions.
|
||||
return getCPersonalityMSVC(T, L);
|
||||
}
|
||||
|
||||
const EHPersonality &EHPersonality::get(CodeGenModule &CGM) {
|
||||
const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
|
||||
const FunctionDecl *FD) {
|
||||
const llvm::Triple &T = CGM.getTarget().getTriple();
|
||||
const LangOptions &L = CGM.getLangOpts();
|
||||
|
||||
// Try to pick a personality function that is compatible with MSVC if we're
|
||||
// not compiling Obj-C. Obj-C users better have an Obj-C runtime that supports
|
||||
// the GCC-style personality function.
|
||||
if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
|
||||
if (L.CPlusPlus)
|
||||
return getCXXPersonalityMSVC(T, L);
|
||||
if (L.SjLjExceptions)
|
||||
return EHPersonality::GNU_CPlusPlus_SJLJ;
|
||||
else if (FD && FD->usesSEHTry())
|
||||
return getSEHPersonalityMSVC(T);
|
||||
else
|
||||
return getCPersonalityMSVC(T, L);
|
||||
return EHPersonality::MSVC_CxxFrameHandler3;
|
||||
}
|
||||
|
||||
if (L.CPlusPlus && L.ObjC1)
|
||||
|
@ -354,7 +354,7 @@ void CodeGenModule::SimplifyPersonality() {
|
|||
if (!LangOpts.ObjCRuntime.isNeXTFamily())
|
||||
return;
|
||||
|
||||
const EHPersonality &ObjCXX = EHPersonality::get(*this);
|
||||
const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr);
|
||||
const EHPersonality &CXX =
|
||||
getCXXPersonality(getTarget().getTriple(), LangOpts);
|
||||
if (&ObjCXX == &CXX)
|
||||
|
@ -737,8 +737,16 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
|
|||
assert(EHStack.requiresLandingPad());
|
||||
assert(!EHStack.empty());
|
||||
|
||||
if (!CGM.getLangOpts().Exceptions)
|
||||
// If exceptions are disabled, there are usually no landingpads. However, when
|
||||
// SEH is enabled, functions using SEH still get landingpads.
|
||||
const LangOptions &LO = CGM.getLangOpts();
|
||||
if (!LO.Exceptions) {
|
||||
if (!LO.Borland && !LO.MicrosoftExt)
|
||||
return nullptr;
|
||||
const auto *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
|
||||
if (!FD || !FD->usesSEHTry())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check the innermost scope for a cached landing pad. If this is
|
||||
// a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
|
||||
|
@ -778,7 +786,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
|
|||
CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
|
||||
auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation);
|
||||
|
||||
const EHPersonality &personality = EHPersonality::get(CGM);
|
||||
const EHPersonality &personality = EHPersonality::get(*this);
|
||||
|
||||
// Create and configure the landing pad.
|
||||
llvm::BasicBlock *lpad = createBasicBlock("lpad");
|
||||
|
@ -1595,7 +1603,7 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
|
|||
Builder.SetInsertPoint(TerminateLandingPad);
|
||||
|
||||
// Tell the backend that this is a landing pad.
|
||||
const EHPersonality &Personality = EHPersonality::get(CGM);
|
||||
const EHPersonality &Personality = EHPersonality::get(*this);
|
||||
llvm::LandingPadInst *LPadInst =
|
||||
Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr),
|
||||
getOpaquePersonalityFn(CGM, Personality), 0);
|
||||
|
@ -1654,7 +1662,7 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
|
|||
EHResumeBlock = createBasicBlock("eh.resume");
|
||||
Builder.SetInsertPoint(EHResumeBlock);
|
||||
|
||||
const EHPersonality &Personality = EHPersonality::get(CGM);
|
||||
const EHPersonality &Personality = EHPersonality::get(*this);
|
||||
|
||||
// This can always be a call because we necessarily didn't find
|
||||
// anything on the EH stack which needs our help.
|
||||
|
|
|
@ -4877,10 +4877,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
|
|||
const Driver &D = getToolChain().getDriver();
|
||||
EHFlags EH = parseClangCLEHFlags(D, Args);
|
||||
// FIXME: Do something with NoExceptC.
|
||||
if (EH.Synch || EH.Asynch)
|
||||
if (EH.Synch || EH.Asynch) {
|
||||
CmdArgs.push_back("-fcxx-exceptions");
|
||||
// Always add -fexceptions to allow SEH __try.
|
||||
CmdArgs.push_back("-fexceptions");
|
||||
}
|
||||
|
||||
// /EP should expand to -E -P.
|
||||
if (Args.hasArg(options::OPT__SLASH_EP)) {
|
||||
|
|
|
@ -3303,11 +3303,12 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
|
|||
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
|
||||
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
|
||||
|
||||
sema::FunctionScopeInfo *FSI = getCurFunction();
|
||||
|
||||
// C++ try is incompatible with SEH __try.
|
||||
if (!getLangOpts().Borland && getCurFunction()->FirstSEHTryLoc.isValid()) {
|
||||
if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) {
|
||||
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
|
||||
Diag(getCurFunction()->FirstSEHTryLoc, diag::note_conflicting_try_here)
|
||||
<< "'__try'";
|
||||
Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'";
|
||||
}
|
||||
|
||||
const unsigned NumHandlers = Handlers.size();
|
||||
|
@ -3352,7 +3353,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
|
|||
}
|
||||
}
|
||||
|
||||
getCurFunction()->setHasCXXTry(TryLoc);
|
||||
FSI->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
|
||||
|
@ -3367,15 +3368,29 @@ StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc,
|
|||
Stmt *TryBlock, Stmt *Handler) {
|
||||
assert(TryBlock && Handler);
|
||||
|
||||
sema::FunctionScopeInfo *FSI = getCurFunction();
|
||||
|
||||
// SEH __try is incompatible with C++ try. Borland appears to support this,
|
||||
// however.
|
||||
if (!getLangOpts().Borland && getCurFunction()->FirstCXXTryLoc.isValid()) {
|
||||
if (!getLangOpts().Borland) {
|
||||
if (FSI->FirstCXXTryLoc.isValid()) {
|
||||
Diag(TryLoc, diag::err_mixing_cxx_try_seh_try);
|
||||
Diag(getCurFunction()->FirstCXXTryLoc, diag::note_conflicting_try_here)
|
||||
<< "'try'";
|
||||
Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'";
|
||||
}
|
||||
}
|
||||
|
||||
getCurFunction()->setHasSEHTry(TryLoc);
|
||||
FSI->setHasSEHTry(TryLoc);
|
||||
|
||||
// Reject __try in Obj-C methods, blocks, and captured decls, since we don't
|
||||
// track if they use SEH.
|
||||
DeclContext *DC = CurContext;
|
||||
while (DC && !DC->isFunctionOrMethod())
|
||||
DC = DC->getParent();
|
||||
FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DC);
|
||||
if (FD)
|
||||
FD->setUsesSEHTry(true);
|
||||
else
|
||||
Diag(TryLoc, diag::err_seh_try_outside_functions);
|
||||
|
||||
return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fexceptions -fms-extensions -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
|
||||
|
||||
void abort(void) __attribute__((noreturn));
|
||||
void might_crash(void);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: not %clang_cc1 -triple x86_64-pc-win32 -fexceptions -fms-extensions -emit-llvm -o - %s 2>&1 | FileCheck %s
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - %s 2>&1 | FileCheck %s
|
||||
|
||||
// This is a codegen test because we only emit the diagnostic when we start
|
||||
// generating code.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fexceptions -fms-extensions -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// FIXME: Perform this outlining automatically CodeGen.
|
||||
void try_body(int numerator, int denominator, int *myres) {
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
|
||||
// RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
|
||||
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
|
||||
// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
|
||||
// RUN: -o - -mconstructor-aliases | \
|
||||
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
|
||||
|
||||
extern "C" void might_throw();
|
||||
|
||||
struct HasCleanup {
|
||||
HasCleanup();
|
||||
~HasCleanup();
|
||||
int padding;
|
||||
};
|
||||
|
||||
extern "C" void use_cxx() {
|
||||
HasCleanup x;
|
||||
might_throw();
|
||||
}
|
||||
|
||||
// Make sure we use __CxxFrameHandler3 for C++ EH.
|
||||
|
||||
// CXXEH-LABEL: define void @use_cxx()
|
||||
// CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
|
||||
// CXXEH: invoke void @might_throw()
|
||||
// CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
|
||||
//
|
||||
// CXXEH: [[cont]]
|
||||
// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
|
||||
// CXXEH: ret void
|
||||
//
|
||||
// CXXEH: [[lpad]]
|
||||
// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||
// CXXEH-NEXT: cleanup
|
||||
// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
|
||||
// CXXEH: br label %[[resume:[^ ]*]]
|
||||
//
|
||||
// CXXEH: [[resume]]
|
||||
// CXXEH: resume
|
||||
|
||||
// NOCXX-LABEL: define void @use_cxx()
|
||||
// NOCXX-NOT: invoke
|
||||
// NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
|
||||
// NOCXX-NOT: invoke
|
||||
// NOCXX: call void @might_throw()
|
||||
// NOCXX-NOT: invoke
|
||||
// NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
|
||||
// NOCXX-NOT: invoke
|
||||
// NOCXX: ret void
|
||||
|
||||
extern "C" void use_seh() {
|
||||
__try {
|
||||
might_throw();
|
||||
} __except(1) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we use __C_specific_handler for SEH.
|
||||
|
||||
// CHECK-LABEL: define void @use_seh()
|
||||
// CHECK: invoke void @might_throw()
|
||||
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
|
||||
//
|
||||
// CHECK: [[cont]]
|
||||
// CHECK: br label %[[ret:[^ ]*]]
|
||||
//
|
||||
// CHECK: [[lpad]]
|
||||
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
|
||||
// CHECK-NEXT: catch i8*
|
||||
//
|
||||
// CHECK: br label %[[ret]]
|
||||
//
|
||||
// CHECK: [[ret]]
|
||||
// CHECK: ret void
|
||||
|
||||
void use_seh_in_lambda() {
|
||||
([]() {
|
||||
__try {
|
||||
might_throw();
|
||||
} __except(1) {
|
||||
}
|
||||
})();
|
||||
HasCleanup x;
|
||||
might_throw();
|
||||
}
|
||||
|
||||
// CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
|
||||
// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
|
||||
|
||||
// NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
|
||||
// NOCXX-NOT: invoke
|
||||
// NOCXX: ret void
|
||||
|
||||
// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this)
|
||||
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
// RUN: %clang_cl /c /EHs-c- -### -- %s 2>&1 | FileCheck -check-prefix=EHs_c_ %s
|
||||
// EHs_c_-NOT: "-fcxx-exceptions"
|
||||
// EHs_c_: "-fexceptions"
|
||||
// EHs_c_-NOT: "-fexceptions"
|
||||
|
||||
// RUN: %clang_cl /c /EHs- /EHc- -### -- %s 2>&1 | FileCheck -check-prefix=EHs_EHc_ %s
|
||||
// EHs_EHc_-NOT: "-fcxx-exceptions"
|
||||
// EHs_EHc_: "-fexceptions"
|
||||
// EHs_EHc_-NOT: "-fexceptions"
|
||||
|
||||
// RUN: %clang_cl /c /EHs- /EHs -### -- %s 2>&1 | FileCheck -check-prefix=EHs_EHs %s
|
||||
// EHs_EHs: "-fcxx-exceptions"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
|
||||
// RUN: %clang_cc1 -std=c++03 -fblocks -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fblocks -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) {
|
||||
|
@ -37,6 +38,7 @@ void instantiate_bad_scope_tmpl() {
|
|||
bad_builtin_scope_template<might_crash>();
|
||||
}
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// FIXME: Diagnose this case. For now we produce undef in codegen.
|
||||
template <typename T, T FN()>
|
||||
T func_template() {
|
||||
|
@ -46,6 +48,7 @@ void inject_builtins() {
|
|||
func_template<void *, __exception_info>();
|
||||
func_template<unsigned long, __exception_code>();
|
||||
}
|
||||
#endif
|
||||
|
||||
void use_seh_after_cxx() {
|
||||
try { // expected-note {{conflicting 'try' here}}
|
||||
|
@ -68,3 +71,45 @@ void use_cxx_after_seh() {
|
|||
} catch (int) {
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
void use_seh_in_lambda() {
|
||||
([]() {
|
||||
__try {
|
||||
might_crash();
|
||||
} __except(1) {
|
||||
}
|
||||
})();
|
||||
try {
|
||||
might_crash();
|
||||
} catch (int) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void use_seh_in_block() {
|
||||
void (^b)() = ^{
|
||||
__try { // expected-error {{cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls}}
|
||||
might_crash();
|
||||
} __except(1) {
|
||||
}
|
||||
};
|
||||
try {
|
||||
b();
|
||||
} catch (int) {
|
||||
}
|
||||
}
|
||||
|
||||
void (^use_seh_in_global_block)() = ^{
|
||||
__try { // expected-error {{cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls}}
|
||||
might_crash();
|
||||
} __except(1) {
|
||||
}
|
||||
};
|
||||
|
||||
void (^use_cxx_in_global_block)() = ^{
|
||||
try {
|
||||
might_crash();
|
||||
} catch(int) {
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue