Skip to content

[clang] Move ExceptionHandling from LangOptions to CodeGenOptions #148982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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() ==
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
19 changes: 0 additions & 19 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2176,10 +2176,10 @@ def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group<f_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<LangOpts<"ExceptionHandling">, "None">;
Values<"dwarf,sjlj,seh,wasm,none">,
NormalizedValuesScope<"CodeGenOptions::ExceptionHandlingKind">,
NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "None"]>,
MarshallingInfoEnum<CodeGenOpts<"ExceptionHandling">, "None">;
def exception_model_EQ : Joined<["-"], "exception-model=">,
Visibility<[CC1Option]>, Alias<exception_model>;
def fignore_exceptions : Flag<["-"], "fignore-exceptions">, Group<f_Group>,
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
51 changes: 27 additions & 24 deletions clang/lib/CodeGen/CGException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,28 +131,29 @@ 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())
return EHPersonality::MSVC_CxxFrameHandler3;

switch (L.ObjCRuntime.getKind()) {
case ObjCRuntime::FragileMacOSX:
return getCPersonality(Target, L);
return getCPersonality(Target, CGOpts);
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
case ObjCRuntime::WatchOS:
Expand All @@ -165,29 +166,29 @@ 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;
}
llvm_unreachable("bad runtime kind");
}

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;
Expand All @@ -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;
Expand All @@ -205,15 +207,15 @@ 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
// function on targets using (backend-driven) SJLJ EH.
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
Expand All @@ -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");
}
Expand All @@ -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();

Expand All @@ -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) {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
45 changes: 3 additions & 42 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<unsigned>(LangOpts.getExceptionHandling()) << T.str();
<< static_cast<unsigned>(CodeGenOpts.getExceptionHandling()) << T.str();

if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
Diags.Report(diag::warn_c_kext);
Expand Down Expand Up @@ -3713,23 +3713,6 @@ static StringRef GetInputKindName(InputKind IK) {
llvm_unreachable("unknown input language");
}

static StringRef getExceptionHandlingName(unsigned EHK) {
switch (static_cast<LangOptions::ExceptionHandlingKind>(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,
Expand All @@ -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;
}
Expand Down Expand Up @@ -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<LangOptions::ExceptionHandlingKind> EMValue =
llvm::StringSwitch<std::optional<LangOptions::ExceptionHandlingKind>>(
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<unsigned>(*EMValue);
} else {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
}
}

return Diags.getNumErrors() == NumErrorsBefore;
}

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down