diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index a11e12d495cd2..cfffeb71f09d1 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -56,6 +56,8 @@ CODEGENOPT(XCOFFReadOnlyPointers, 1, 0, Benign) ///< Set for -mxcoff-roptr. CODEGENOPT(AllTocData, 1, 0, Benign) ///< AIX -mtocdata ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None, Benign) /// frame-pointer: all,non-leaf,reserved,none +ENUM_CODEGENOPT(ExceptionHandling, ExceptionHandlingKind, 3, ExceptionHandlingKind::None, NotCompatible) + CODEGENOPT(ClearASTBeforeBackend , 1, 0, Benign) ///< Free the AST before running backend code generation. Only works with -disable-free. CODEGENOPT(DisableFree , 1, 0, Benign) ///< Don't free memory. CODEGENOPT(DiscardValueNames , 1, 0, Benign) ///< Discard Value Names from the IR (LLVMContext flag) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index df4403ace5fe3..cdeedd5b4eac6 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -176,6 +176,9 @@ class CodeGenOptions : public CodeGenOptionsBase { llvm_unreachable("invalid FramePointerKind"); } + /// Possible exception handling behavior. + enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; + enum class SwiftAsyncFramePointerKind { Auto, // Choose Swift async extended frame info based on deployment target. Always, // Unconditionally emit Swift async extended frame info. @@ -552,6 +555,22 @@ class CodeGenOptions : public CodeGenOptionsBase { return NoBuiltinFuncs; } + bool hasSjLjExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::SjLj; + } + + bool hasSEHExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::WinEH; + } + + bool hasDWARFExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI; + } + + bool hasWasmExceptions() const { + return getExceptionHandling() == ExceptionHandlingKind::Wasm; + } + /// Check if Clang profile instrumenation is on. bool hasProfileClangInstr() const { return getProfileInstr() == diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 6c47107796236..6ac8d496f1494 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -98,8 +98,6 @@ LANGOPT(Exceptions , 1, 0, NotCompatible, "exception handling") LANGOPT(ObjCExceptions , 1, 0, NotCompatible, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, NotCompatible, "C++ exceptions") LANGOPT(EHAsynch , 1, 0, NotCompatible, "C/C++ EH Asynch exceptions") -ENUM_LANGOPT(ExceptionHandling, ExceptionHandlingKind, 3, - ExceptionHandlingKind::None, NotCompatible, "exception handling") LANGOPT(IgnoreExceptions , 1, 0, NotCompatible, "ignore exceptions") LANGOPT(ExternCNoUnwind , 1, 0, NotCompatible, "Assume extern C functions don't unwind") LANGOPT(AssumeNothrowExceptionDtor , 1, 0, NotCompatible, "Assume exception object's destructor is nothrow") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 4c642c9e10c91..937cbff4e3ea3 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -337,9 +337,6 @@ class LangOptionsBase { enum ExcessPrecisionKind { FPP_Standard, FPP_Fast, FPP_None }; - /// Possible exception handling behavior. - enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; - enum class LaxVectorConversionKind { /// Permit no implicit vector bitcasts. None, @@ -788,22 +785,6 @@ class LangOptions : public LangOptionsBase { return getSignReturnAddressScope() == SignReturnAddressScopeKind::All; } - bool hasSjLjExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::SjLj; - } - - bool hasSEHExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::WinEH; - } - - bool hasDWARFExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI; - } - - bool hasWasmExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::Wasm; - } - bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; } bool hasDefaultVisibilityExportMapping() const { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index bce29a76f3ac7..a8c1b5dd8ab3b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2176,10 +2176,10 @@ def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group, HelpText<"Use WebAssembly style exceptions">; def exception_model : Separate<["-"], "exception-model">, Visibility<[CC1Option]>, HelpText<"The exception model">, - Values<"dwarf,sjlj,seh,wasm">, - NormalizedValuesScope<"LangOptions::ExceptionHandlingKind">, - NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm"]>, - MarshallingInfoEnum, "None">; + Values<"dwarf,sjlj,seh,wasm,none">, + NormalizedValuesScope<"CodeGenOptions::ExceptionHandlingKind">, + NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "None"]>, + MarshallingInfoEnum, "None">; def exception_model_EQ : Joined<["-"], "exception-model=">, Visibility<[CC1Option]>, Alias; def fignore_exceptions : Flag<["-"], "fignore-exceptions">, Group, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 2f6d4c414e737..1b7257857dd3b 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -407,13 +407,13 @@ static bool initTargetOptions(const CompilerInstance &CI, // Set EABI version. Options.EABIVersion = TargetOpts.EABIVersion; - if (LangOpts.hasSjLjExceptions()) + if (CodeGenOpts.hasSjLjExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::SjLj; - if (LangOpts.hasSEHExceptions()) + if (CodeGenOpts.hasSEHExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::WinEH; - if (LangOpts.hasDWARFExceptions()) + if (CodeGenOpts.hasDWARFExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; - if (LangOpts.hasWasmExceptions()) + if (CodeGenOpts.hasWasmExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::Wasm; Options.NoInfsFPMath = LangOpts.NoHonorInfs; diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index ad138b9876e8c..f86af4581c345 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -131,20 +131,21 @@ const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2", nullptr}; static const EHPersonality &getCPersonality(const TargetInfo &Target, - const LangOptions &L) { + const CodeGenOptions &CGOpts) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_C_SJLJ; - if (L.hasDWARFExceptions()) + if (CGOpts.hasDWARFExceptions()) return EHPersonality::GNU_C; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_C_SEH; return EHPersonality::GNU_C; } static const EHPersonality &getObjCPersonality(const TargetInfo &Target, + const CodeGenOptions &CGOpts, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) @@ -152,7 +153,7 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, switch (L.ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: - return getCPersonality(Target, L); + return getCPersonality(Target, CGOpts); case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: @@ -165,9 +166,9 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, [[fallthrough]]; case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_ObjC_SJLJ; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_ObjC_SEH; return EHPersonality::GNU_ObjC; } @@ -175,19 +176,19 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, } static const EHPersonality &getCXXPersonality(const TargetInfo &Target, - const LangOptions &L) { + const CodeGenOptions &CGOpts) { const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; if (T.isOSAIX()) return EHPersonality::XL_CPlusPlus; - if (L.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) return EHPersonality::GNU_CPlusPlus_SJLJ; - if (L.hasDWARFExceptions()) + if (CGOpts.hasDWARFExceptions()) return EHPersonality::GNU_CPlusPlus; - if (L.hasSEHExceptions()) + if (CGOpts.hasSEHExceptions()) return EHPersonality::GNU_CPlusPlus_SEH; - if (L.hasWasmExceptions()) + if (CGOpts.hasWasmExceptions()) return EHPersonality::GNU_Wasm_CPlusPlus; if (T.isOSzOS()) return EHPersonality::ZOS_CPlusPlus; @@ -197,6 +198,7 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target, /// Determines the personality function to use when both C++ /// and Objective-C exceptions are being caught. static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, + const CodeGenOptions &CGOpts, const LangOptions &L) { if (Target.getTriple().isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; @@ -205,7 +207,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, // In the fragile ABI, just use C++ exception handling and hope // they're not doing crazy exception mixing. case ObjCRuntime::FragileMacOSX: - return getCXXPersonality(Target, L); + return getCXXPersonality(Target, CGOpts); // The ObjC personality defers to the C++ personality for non-ObjC // handlers. Unlike the C++ case, we use the same personality @@ -213,7 +215,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: - return getObjCPersonality(Target, L); + return getObjCPersonality(Target, CGOpts, L); case ObjCRuntime::GNUstep: return Target.getTriple().isOSCygMing() ? EHPersonality::GNU_CPlusPlus_SEH @@ -223,7 +225,7 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, // mixed EH. Use the ObjC personality just to avoid returning null. case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: - return getObjCPersonality(Target, L); + return getObjCPersonality(Target, CGOpts, L); } llvm_unreachable("bad runtime kind"); } @@ -237,6 +239,7 @@ static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) { const EHPersonality &EHPersonality::get(CodeGenModule &CGM, const FunctionDecl *FD) { const llvm::Triple &T = CGM.getTarget().getTriple(); + const CodeGenOptions &CGOpts = CGM.getCodeGenOpts(); const LangOptions &L = CGM.getLangOpts(); const TargetInfo &Target = CGM.getTarget(); @@ -245,10 +248,10 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM, return getSEHPersonalityMSVC(T); if (L.ObjC) - return L.CPlusPlus ? getObjCXXPersonality(Target, L) - : getObjCPersonality(Target, L); - return L.CPlusPlus ? getCXXPersonality(Target, L) - : getCPersonality(Target, L); + return L.CPlusPlus ? getObjCXXPersonality(Target, CGOpts, L) + : getObjCPersonality(Target, CGOpts, L); + return L.CPlusPlus ? getCXXPersonality(Target, CGOpts) + : getCPersonality(Target, CGOpts); } const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { @@ -344,7 +347,7 @@ void CodeGenModule::SimplifyPersonality() { return; const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr); - const EHPersonality &CXX = getCXXPersonality(getTarget(), LangOpts); + const EHPersonality &CXX = getCXXPersonality(getTarget(), CodeGenOpts); if (&ObjCXX == &CXX) return; @@ -500,7 +503,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { // In Wasm EH we currently treat 'throw()' in the same way as 'noexcept'. In // case of throw with types, we ignore it and print a warning for now. // TODO Correctly handle exception specification in Wasm EH - if (CGM.getLangOpts().hasWasmExceptions()) { + if (CGM.getCodeGenOpts().hasWasmExceptions()) { if (EST == EST_DynamicNone) EHStack.pushTerminate(); else @@ -515,8 +518,8 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { // throw with types. // TODO Correctly handle exception specification in Emscripten EH if (getTarget().getCXXABI() == TargetCXXABI::WebAssembly && - CGM.getLangOpts().getExceptionHandling() == - LangOptions::ExceptionHandlingKind::None && + CGM.getCodeGenOpts().getExceptionHandling() == + CodeGenOptions::ExceptionHandlingKind::None && EST == EST_Dynamic) CGM.getDiags().Report(D->getLocation(), diag::warn_wasm_dynamic_exception_spec_ignored) @@ -604,7 +607,7 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { // In wasm we currently treat 'throw()' in the same way as 'noexcept'. In // case of throw with types, we ignore it and print a warning for now. // TODO Correctly handle exception specification in wasm - if (CGM.getLangOpts().hasWasmExceptions()) { + if (CGM.getCodeGenOpts().hasWasmExceptions()) { if (EST == EST_DynamicNone) EHStack.popTerminate(); return; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 56d10ceb986b3..6ab36d8675966 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -593,11 +593,11 @@ static bool FixupInvocation(CompilerInvocation &Invocation, CodeGenOpts.CodeModel = TargetOpts.CodeModel; CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold; - if (LangOpts.getExceptionHandling() != - LangOptions::ExceptionHandlingKind::None && + if (CodeGenOpts.getExceptionHandling() != + CodeGenOptions::ExceptionHandlingKind::None && T.isWindowsMSVCEnvironment()) Diags.Report(diag::err_fe_invalid_exception_model) - << static_cast(LangOpts.getExceptionHandling()) << T.str(); + << static_cast(CodeGenOpts.getExceptionHandling()) << T.str(); if (LangOpts.AppleKext && !LangOpts.CPlusPlus) Diags.Report(diag::warn_c_kext); @@ -3713,23 +3713,6 @@ static StringRef GetInputKindName(InputKind IK) { llvm_unreachable("unknown input language"); } -static StringRef getExceptionHandlingName(unsigned EHK) { - switch (static_cast(EHK)) { - case LangOptions::ExceptionHandlingKind::None: - return "none"; - case LangOptions::ExceptionHandlingKind::DwarfCFI: - return "dwarf"; - case LangOptions::ExceptionHandlingKind::SjLj: - return "sjlj"; - case LangOptions::ExceptionHandlingKind::WinEH: - return "seh"; - case LangOptions::ExceptionHandlingKind::Wasm: - return "wasm"; - } - - llvm_unreachable("covered switch"); -} - void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, ArgumentConsumer Consumer, const llvm::Triple &T, @@ -3745,10 +3728,6 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_pic_is_pie); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); - if (Opts.ExceptionHandling) { - GenerateArg(Consumer, OPT_exception_model, - getExceptionHandlingName(Opts.ExceptionHandling)); - } return; } @@ -4057,24 +4036,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), Diags, Opts.Sanitize); - if (const Arg *A = Args.getLastArg(options::OPT_exception_model)) { - std::optional EMValue = - llvm::StringSwitch>( - A->getValue()) - .Case("dwarf", LangOptions::ExceptionHandlingKind::DwarfCFI) - .Case("sjlj", LangOptions::ExceptionHandlingKind::SjLj) - .Case("seh", LangOptions::ExceptionHandlingKind::WinEH) - .Case("wasm", LangOptions::ExceptionHandlingKind::Wasm) - .Case("none", LangOptions::ExceptionHandlingKind::None) - .Default(std::nullopt); - if (EMValue) { - Opts.ExceptionHandling = static_cast(*EMValue); - } else { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); - } - } - return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 136bc55847cc1..38b2e0cf1ca59 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1032,14 +1032,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.GNUCVersion && LangOpts.RTTI) Builder.defineMacro("__GXX_RTTI"); - if (LangOpts.hasSjLjExceptions()) + if (CGOpts.hasSjLjExceptions()) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); - else if (LangOpts.hasSEHExceptions()) + else if (CGOpts.hasSEHExceptions()) Builder.defineMacro("__SEH__"); - else if (LangOpts.hasDWARFExceptions() && + else if (CGOpts.hasDWARFExceptions() && (TI.getTriple().isThumb() || TI.getTriple().isARM())) Builder.defineMacro("__ARM_DWARF_EH__"); - else if (LangOpts.hasWasmExceptions() && TI.getTriple().isWasm()) + else if (CGOpts.hasWasmExceptions() && TI.getTriple().isWasm()) Builder.defineMacro("__WASM_EXCEPTIONS__"); if (LangOpts.Deprecated)