I reverted this for a bit in r228262. On Tue, Feb 3, 2015 at 2:52 PM, Reid Kleckner <[email protected]> wrote:
> Author: rnk > Date: Tue Feb 3 16:52:35 2015 > New Revision: 228058 > > URL: http://llvm.org/viewvc/llvm-project?rev=228058&view=rev > Log: > SEH: Track users of __try so we can pick a per-func EH personality > > There are four major kinds of declarations that cause code generation: > - FunctionDecl (includes CXXMethodDecl etc) > - ObjCMethodDecl > - BlockDecl > - CapturedDecl > > This patch tracks __try usage on FunctionDecls and diagnoses __try usage > in other decls. If someone wants to use __try from ObjC, they can use it > from a free function, since the ObjC code will need an ObjC-style EH > personality. > > Eventually we will want to look through CapturedDecls and track SEH > usage on the parent FunctionDecl, if present. > > Added: > cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp > Modified: > cfe/trunk/include/clang/AST/Decl.h > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/CodeGen/CGException.cpp > cfe/trunk/lib/Sema/SemaStmt.cpp > cfe/trunk/test/SemaCXX/exceptions-seh.cpp > > Modified: cfe/trunk/include/clang/AST/Decl.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=228058&r1=228057&r2=228058&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/Decl.h (original) > +++ cfe/trunk/include/clang/AST/Decl.h Tue Feb 3 16:52:35 2015 > @@ -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) > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=228058&r1=228057&r2=228058&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 3 > 16:52:35 2015 > @@ -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< > > Modified: cfe/trunk/lib/CodeGen/CGException.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=228058&r1=228057&r2=228058&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGException.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Feb 3 16:52:35 2015 > @@ -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 &getObjCXXPer > 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::EmitL > 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::getTe > 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::getEH > 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. > > Modified: cfe/trunk/lib/Sema/SemaStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=228058&r1=228057&r2=228058&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Feb 3 16:52:35 2015 > @@ -3303,11 +3303,12 @@ StmtResult Sema::ActOnCXXTryBlock(Source > 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(Source > } > } > > - 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 I > 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); > } > > Added: cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp?rev=228058&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp Tue Feb 3 16:52:35 2015 > @@ -0,0 +1,76 @@ > +// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s > -triple=x86_64-windows-msvc -emit-llvm -o - -fcxx-exceptions -fexceptions > -mconstructor-aliases | FileCheck %s > + > +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. > + > +// CHECK-LABEL: define void @use_cxx() > +// CHECK: call %struct.HasCleanup* > @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* > %{{.*}}) > +// CHECK: invoke void @might_throw() > +// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > +// > +// CHECK: [[cont]] > +// CHECK: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* > %{{.*}}) > +// CHECK: ret void > +// > +// CHECK: [[lpad]] > +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__CxxFrameHandler3 to i8*) > +// CHECK-NEXT: cleanup > +// CHECK: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* > %{{.*}}) > +// CHECK: br label %[[resume:[^ ]*]] > +// > +// CHECK: [[resume]] > +// CHECK: resume > + > +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(); > +} > + > +// CHECK-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"() > +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__CxxFrameHandler3 to i8*) > + > +// 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*) > > Modified: cfe/trunk/test/SemaCXX/exceptions-seh.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/exceptions-seh.cpp?rev=228058&r1=228057&r2=228058&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/exceptions-seh.cpp (original) > +++ cfe/trunk/test/SemaCXX/exceptions-seh.cpp Tue Feb 3 16:52:35 2015 > @@ -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) { > + } > +}; > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
