r228058 - SEH: Track users of __try so we can pick a per-func EH personality
Nico Weber
thakis at chromium.org
Wed Feb 4 18:10:48 PST 2015
I reverted this for a bit in r228262.
On Tue, Feb 3, 2015 at 2:52 PM, Reid Kleckner <reid at kleckner.net> 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 at XZ"(%struct.HasCleanup*
> %{{.*}})
> +// CHECK: invoke void @might_throw()
> +// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
> +//
> +// CHECK: [[cont]]
> +// CHECK: call void @"\01??1HasCleanup@@QEAA at 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 at 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 at 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150204/f2cf6564/attachment.html>
More information about the cfe-commits
mailing list