Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -124,7 +124,9 @@ LANGOPT(Exceptions , 1, 0, "exception handling") LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") +LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") +LANGOPT(SEHExceptions , 1, 0, "structured exception handling") LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -800,8 +800,12 @@ def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group, Flags<[CoreOption]>; def fexceptions : Flag<["-"], "fexceptions">, Group, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; +def fdwarf_exceptions : Flag<["-"], "fdwarf-exceptions">, Group, + Flags<[CC1Option]>, HelpText<"Use DWARF style exceptions">; def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group, Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">; +def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group, + Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group; def : Flag<["-"], "fexpensive-optimizations">, Group; Index: include/clang/Driver/ToolChain.h =================================================================== --- include/clang/Driver/ToolChain.h +++ include/clang/Driver/ToolChain.h @@ -396,6 +396,11 @@ return false; } + /// UseSEHExceptions - Does this tool chain use SEH exceptions. + virtual bool UseSEHExceptions(const llvm::opt::ArgList &Args) const { + return getTriple().isOSWindows() && getArch() == llvm::Triple::x86_64; + } + /// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode. virtual bool SupportsEmbeddedBitcode() const { return false; Index: lib/Basic/Targets/X86.h =================================================================== --- lib/Basic/Targets/X86.h +++ lib/Basic/Targets/X86.h @@ -899,10 +899,6 @@ DefineStd(Builder, "WIN64", Opts); Builder.defineMacro("__MINGW64__"); addMinGWDefines(Opts, Builder); - - // GCC defines this macro when it is using __gxx_personality_seh0. - if (!Opts.SjLjExceptions) - Builder.defineMacro("__SEH__"); } }; @@ -925,10 +921,6 @@ DefineStd(Builder, "unix", Opts); if (Opts.CPlusPlus) Builder.defineMacro("_GNU_SOURCE"); - - // GCC defines this macro when it is using __gxx_personality_seh0. - if (!Opts.SjLjExceptions) - Builder.defineMacro("__SEH__"); } }; Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -423,6 +423,10 @@ if (LangOpts.SjLjExceptions) Options.ExceptionModel = llvm::ExceptionHandling::SjLj; + if (LangOpts.SEHExceptions) + Options.ExceptionModel = llvm::ExceptionHandling::WinEH; + if (LangOpts.DWARFExceptions) + Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; Index: lib/CodeGen/CGException.cpp =================================================================== --- lib/CodeGen/CGException.cpp +++ lib/CodeGen/CGException.cpp @@ -112,17 +112,11 @@ 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. -static bool useLibGCCSEHPersonality(const llvm::Triple &T) { - return T.isOSWindows() && T.getArch() == llvm::Triple::x86_64; -} - static const EHPersonality &getCPersonality(const llvm::Triple &T, const LangOptions &L) { if (L.SjLjExceptions) return EHPersonality::GNU_C_SJLJ; - else if (useLibGCCSEHPersonality(T)) + if (L.SEHExceptions) return EHPersonality::GNU_C_SEH; return EHPersonality::GNU_C; } @@ -144,7 +138,7 @@ case ObjCRuntime::ObjFW: if (L.SjLjExceptions) return EHPersonality::GNU_ObjC_SJLJ; - else if (useLibGCCSEHPersonality(T)) + if (L.SEHExceptions) return EHPersonality::GNU_ObjC_SEH; return EHPersonality::GNU_ObjC; } @@ -155,7 +149,7 @@ const LangOptions &L) { if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; - else if (useLibGCCSEHPersonality(T)) + if (L.SEHExceptions) return EHPersonality::GNU_CPlusPlus_SEH; return EHPersonality::GNU_CPlusPlus; } @@ -211,6 +205,10 @@ if (T.isWindowsMSVCEnvironment() && !L.ObjC1) { if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; + if (L.SEHExceptions) + return EHPersonality::GNU_CPlusPlus_SEH; + if (L.DWARFExceptions) + return EHPersonality::GNU_CPlusPlus; else return EHPersonality::MSVC_CxxFrameHandler3; } @@ -330,7 +328,7 @@ // Nothing to do if it's unused. if (!Fn || Fn->use_empty()) return; - + // Can't do the optimization if it has non-C++ uses. if (!PersonalityHasOnlyCXXUses(Fn)) return; @@ -438,7 +436,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { if (!CGM.getLangOpts().CXXExceptions) return; - + const FunctionDecl* FD = dyn_cast_or_null(D); if (!FD) { // Check if CapturedDecl is nothrow and create terminate scope for it. Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -4165,9 +4165,22 @@ addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime, CmdArgs); - if (Args.hasArg(options::OPT_fsjlj_exceptions) || - getToolChain().UseSjLjExceptions(Args)) - CmdArgs.push_back("-fsjlj-exceptions"); + // Handle exception personalities + Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, + options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions); + if (A) { + const Option &Opt = A->getOption(); + if (Opt.matches(options::OPT_fsjlj_exceptions)) + CmdArgs.push_back("-fsjlj-exceptions"); + if (Opt.matches(options::OPT_fseh_exceptions)) + CmdArgs.push_back("-fseh-exceptions"); + if (Opt.matches(options::OPT_fdwarf_exceptions)) + CmdArgs.push_back("-fdwarf-exceptions"); + } else if (getToolChain().UseSjLjExceptions(Args)) + CmdArgs.push_back("-fsjlj-exceptions"); + else if (getToolChain().UseSEHExceptions(Args)) + CmdArgs.push_back("-fseh-exceptions"); // C++ "sane" operator new. if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, Index: lib/Driver/ToolChains/MinGW.h =================================================================== --- lib/Driver/ToolChains/MinGW.h +++ lib/Driver/ToolChains/MinGW.h @@ -64,7 +64,6 @@ bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; - bool UseSEHExceptions() const; void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, Index: lib/Driver/ToolChains/MinGW.cpp =================================================================== --- lib/Driver/ToolChains/MinGW.cpp +++ lib/Driver/ToolChains/MinGW.cpp @@ -367,10 +367,6 @@ return getArch() == llvm::Triple::x86_64; } -bool toolchains::MinGW::UseSEHExceptions() const { - return getArch() == llvm::Triple::x86_64; -} - void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2133,7 +2133,18 @@ Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); - Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + + // Handle exception personalities + Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, + options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions); + if (A) { + const Option &Opt = A->getOption(); + Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); + Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); + Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); + } + Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp +++ lib/Frontend/InitPreprocessor.cpp @@ -679,6 +679,8 @@ Builder.defineMacro("__GXX_RTTI"); if (LangOpts.SjLjExceptions) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); + if (LangOpts.SEHExceptions) + Builder.defineMacro("__SEH__"); if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); Index: test/CodeGenCXX/mingw-w64-exceptions.c =================================================================== --- /dev/null +++ test/CodeGenCXX/mingw-w64-exceptions.c @@ -0,0 +1,22 @@ +// RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SEH +// RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DWARF + +// RUN: %clang -target x86_64-windows-gnu -fsjlj-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SJLJ + +// RUN: %clang -target x86_64-windows-gnu -fdwarf-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-DWARF + +// RUN: %clang -target x86_64-windows-gnu -fsjlj-exceptions -fseh-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SEH + +// RUN: %clang -target x86_64-windows-gnu -fseh-exceptions -fsjlj-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-SJLJ + +// RUN: %clang -target x86_64-windows-gnu -fseh-exceptions -fdwarf-exceptions -c %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-DWARF + +// CHECK-SEH: "-fseh-exceptions" +// CHECK-SJLJ: "-fsjlj-exceptions" +// CHECK-DWARF-NOT: "-fsjlj-exceptions" +// CHECK-DWARF-NOT: "-fseh-exceptions" Index: test/CodeGenCXX/mingw-w64-seh-exceptions.cpp =================================================================== --- test/CodeGenCXX/mingw-w64-seh-exceptions.cpp +++ test/CodeGenCXX/mingw-w64-seh-exceptions.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s --check-prefix=X64 -// RUN: %clang_cc1 %s -fexceptions -emit-llvm -triple i686-w64-windows-gnu -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -fexceptions -fseh-exceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 %s -fexceptions -fdwarf-exceptions -emit-llvm -triple i686-w64-windows-gnu -o - | FileCheck %s --check-prefix=X86 extern "C" void foo(); extern "C" void bar();