diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 33 |
2 files changed, 46 insertions, 31 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 28f7449deec..f94a380c210 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -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) @@ -772,7 +772,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"); @@ -1589,7 +1589,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); @@ -1648,7 +1648,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. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index d17cf227011..4761c32f78d 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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()) { - Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); - Diag(getCurFunction()->FirstCXXTryLoc, diag::note_conflicting_try_here) - << "'try'"; + 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'"; + } } - 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); } |