https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/120464
>From 2c0da9aa6f58900387fa91cdc6bcb41e0235d94c Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 18:37:11 +0000 Subject: [PATCH 01/12] [ubsan] Add -fsanitize-nonmerged-handlers (and -fno-sanitize-nonmerged-handlers) '-mllvm -ubsan-unique-traps' (https://github.com/llvm/llvm-project/pull/65972) applies to all UBSan checks. This patch introduces -fsanitize-nonmerged-handlers and -fno-sanitize-nonmerged-handlers, which allows selectively applying non-merged handlers to a subset of UBSan checks. N.B. we use "non-merged handlers" instead of "unique traps", since https://github.com/llvm/llvm-project/pull/119302 has generalized it to work for non-trap mode as well (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-non-merged-handlers. --- clang/include/clang/Basic/CodeGenOptions.h | 4 ++++ clang/include/clang/Driver/Options.td | 4 ++++ clang/include/clang/Driver/SanitizerArgs.h | 1 + clang/lib/CodeGen/CGExpr.cpp | 26 +++++++++++++--------- clang/lib/CodeGen/CodeGenFunction.h | 2 +- clang/lib/Driver/SanitizerArgs.cpp | 24 +++++++++++++++++++- clang/lib/Frontend/CompilerInvocation.cpp | 6 +++++ 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 2dcf98b465661e..9b97adce42cc2a 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -380,6 +380,10 @@ class CodeGenOptions : public CodeGenOptionsBase { /// Set of sanitizer checks that trap rather than diagnose. SanitizerSet SanitizeTrap; + /// Set of sanitizer checks that have non-merged handlers (better + /// debuggability at the expense of code size). + SanitizerSet SanitizeNonMergedHandlers; + /// List of backend command-line options for -fembed-bitcode. std::vector<uint8_t> CmdArgs; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7b544d2534d469..1a09f08890edad 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2548,6 +2548,10 @@ def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Gro def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Disable trapping for specified sanitizers">; +def fsanitize_nonmerged_handlers_EQ : CommaJoined<["-"], "fsanitize-nonmerged-handlers=">, Group<f_clang_Group>, + HelpText<"Enable non-merged handlers for specified sanitizers">; +def fno_sanitize_nonmerged_handlers_EQ : CommaJoined<["-"], "fno-sanitize-nonmerged-handlers=">, Group<f_clang_Group>, + HelpText<"Disable non-merged handlers for specified sanitizers">; def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, HelpText<"Enable trapping for all sanitizers">; diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 4f08ea2b260179..28cfe72d6a34bd 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -25,6 +25,7 @@ class SanitizerArgs { SanitizerSet Sanitizers; SanitizerSet RecoverableSanitizers; SanitizerSet TrapSanitizers; + SanitizerSet NonMergedHandlers; std::vector<std::string> UserIgnorelistFiles; std::vector<std::string> SystemIgnorelistFiles; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 79955f55714164..9c4dfaa393966b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3546,7 +3546,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, ArrayRef<llvm::Value *> FnArgs, SanitizerHandler CheckHandler, CheckRecoverableKind RecoverKind, bool IsFatal, - llvm::BasicBlock *ContBB) { + llvm::BasicBlock *ContBB, bool NoMerge) { assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable); std::optional<ApplyDebugLocation> DL; if (!CGF.Builder.getCurrentDebugLocation()) { @@ -3581,7 +3581,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, llvm::AttributeList::FunctionIndex, B), /*Local=*/true); llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); - bool NoMerge = + NoMerge = NoMerge || ClSanitizeDebugDeoptimization || !CGF.CGM.getCodeGenOpts().OptimizationLevel || (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); @@ -3608,6 +3608,7 @@ void CodeGenFunction::EmitCheck( llvm::Value *FatalCond = nullptr; llvm::Value *RecoverableCond = nullptr; llvm::Value *TrapCond = nullptr; + bool NoMerge = false; for (int i = 0, n = Checked.size(); i < n; ++i) { llvm::Value *Check = Checked[i].first; // -fsanitize-trap= overrides -fsanitize-recover=. @@ -3618,6 +3619,9 @@ void CodeGenFunction::EmitCheck( ? RecoverableCond : FatalCond; Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; + + if (CGM.getCodeGenOpts().SanitizeNonMergedHandlers.has(Checked[i].second)) + NoMerge = true; } if (ClSanitizeGuardChecks) { @@ -3632,7 +3636,7 @@ void CodeGenFunction::EmitCheck( } if (TrapCond) - EmitTrapCheck(TrapCond, CheckHandler); + EmitTrapCheck(TrapCond, CheckHandler, NoMerge); if (!FatalCond && !RecoverableCond) return; @@ -3698,7 +3702,7 @@ void CodeGenFunction::EmitCheck( // Simple case: we need to generate a single handler call, either // fatal, or non-fatal. emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, - (FatalCond != nullptr), Cont); + (FatalCond != nullptr), Cont, NoMerge); } else { // Emit two handler calls: first one for set of unrecoverable checks, // another one for recoverable. @@ -3708,10 +3712,10 @@ void CodeGenFunction::EmitCheck( Builder.CreateCondBr(FatalCond, NonFatalHandlerBB, FatalHandlerBB); EmitBlock(FatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, true, - NonFatalHandlerBB); + NonFatalHandlerBB, NoMerge); EmitBlock(NonFatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, false, - Cont); + Cont, NoMerge); } EmitBlock(Cont); @@ -3901,7 +3905,8 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { } void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, - SanitizerHandler CheckHandlerID) { + SanitizerHandler CheckHandlerID, + bool NoMerge) { llvm::BasicBlock *Cont = createBasicBlock("cont"); // If we're optimizing, collapse all calls to trap down to just one per @@ -3911,9 +3916,10 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - bool NoMerge = ClSanitizeDebugDeoptimization || - !CGM.getCodeGenOpts().OptimizationLevel || - (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || + ClSanitizeDebugDeoptimization || + !CGM.getCodeGenOpts().OptimizationLevel || + (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (TrapBB && !NoMerge) { auto Call = TrapBB->begin(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 092d55355a0a17..c8e17b943c35f0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5166,7 +5166,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. - void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID); + void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge = false); /// Emit a call to trap or debugtrap and attach function attribute /// "trap-func-name" if specified. diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 81f94f23873661..6cd8267aaef1f5 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -68,6 +68,9 @@ static const SanitizerMask TrappingSupported = SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::LocalBounds | SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; +static const SanitizerMask NonMergedDefault; +static const SanitizerMask NonMergedSupported = + (SanitizerKind::Undefined & ~SanitizerKind::Vptr); static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | @@ -696,6 +699,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, TrappingKinds &= Kinds; RecoverableKinds &= ~TrappingKinds; + // Parse -f(no-)?sanitize-nonmerged-handlers flags + SanitizerMask AlwaysNonMerged; // Empty + SanitizerMask NeverNonMerged = ~(setGroupBits(NonMergedSupported)); + SanitizerMask NonMergedKinds = parseSanitizeArgs( + D, Args, DiagnoseErrors, NonMergedDefault, AlwaysNonMerged, + NeverNonMerged, options::OPT_fsanitize_nonmerged_handlers_EQ, + options::OPT_fno_sanitize_nonmerged_handlers_EQ); + RecoverableKinds |= AlwaysNonMerged; + RecoverableKinds &= ~NeverNonMerged; + RecoverableKinds &= Kinds; + // Setup ignorelist files. // Add default ignorelist from resource directory for activated sanitizers, // and validate special case lists format. @@ -1113,6 +1127,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, TrapSanitizers.Mask |= TrappingKinds; assert(!(RecoverableKinds & TrappingKinds) && "Overlap between recoverable and trapping sanitizers"); + + NonMergedHandlers.Mask |= NonMergedKinds; } static std::string toString(const clang::SanitizerSet &Sanitizers) { @@ -1274,6 +1290,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back( Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers))); + if (!NonMergedHandlers.empty()) + CmdArgs.push_back(Args.MakeArgString("-fsanitize-nonmerged-handlers=" + + toString(NonMergedHandlers))); + addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-ignorelist=", UserIgnorelistFiles); addSpecialCaseListOpt(Args, CmdArgs, @@ -1446,7 +1466,9 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, A->getOption().matches(options::OPT_fsanitize_recover_EQ) || A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options::OPT_fsanitize_trap_EQ) || - A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) && + A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) || + A->getOption().matches(options::OPT_fsanitize_nonmerged_handlers_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_nonmerged_handlers_EQ)) && "Invalid argument in parseArgValues!"); SanitizerMask Kinds; for (int i = 0, n = A->getNumValues(); i != n; ++i) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 298fafc21588a1..fbd736822ca085 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1792,6 +1792,9 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap)) GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer); + for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeNonMergedHandlers)) + GenerateArg(Consumer, OPT_fsanitize_nonmerged_handlers_EQ, Sanitizer); + if (!Opts.EmitVersionIdentMetadata) GenerateArg(Consumer, OPT_Qn); @@ -2269,6 +2272,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, parseSanitizerKinds("-fsanitize-trap=", Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, Opts.SanitizeTrap); + parseSanitizerKinds("-fsanitize-nonmerged-handlers=", + Args.getAllArgValues(OPT_fsanitize_nonmerged_handlers_EQ), Diags, + Opts.SanitizeNonMergedHandlers); Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); >From 97b27688ea0b9cae6ac7e496379a7afb2c018d3f Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 18:58:19 +0000 Subject: [PATCH 02/12] Fix args parsing --- clang/lib/Driver/SanitizerArgs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 6cd8267aaef1f5..741a4e5651f6d9 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -706,9 +706,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, D, Args, DiagnoseErrors, NonMergedDefault, AlwaysNonMerged, NeverNonMerged, options::OPT_fsanitize_nonmerged_handlers_EQ, options::OPT_fno_sanitize_nonmerged_handlers_EQ); - RecoverableKinds |= AlwaysNonMerged; - RecoverableKinds &= ~NeverNonMerged; - RecoverableKinds &= Kinds; + NonMergedKinds |= AlwaysNonMerged; + NonMergedKinds &= ~NeverNonMerged; + NonMergedKinds &= Kinds; // Setup ignorelist files. // Add default ignorelist from resource directory for activated sanitizers, >From 1f0f148f878a657272a63036b702906243b8975f Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 18:58:38 +0000 Subject: [PATCH 03/12] Add test --- clang/test/Driver/fsanitize.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index bb692b2aeea1d3..efb73fba087c88 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -9,6 +9,11 @@ // CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" // CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined -fno-sanitize-nonmerged-handlers=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED2 +// CHECK-UNDEFINED-NONMERGED: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound,vptr" +// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound,vptr" + // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED // CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} >From 2cd43c73a77a192e07812011a3f102ede9c21991 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 18:59:13 +0000 Subject: [PATCH 04/12] clang-format --- clang/include/clang/Driver/Options.td | 12 ++++++++---- clang/lib/CodeGen/CGExpr.cpp | 16 +++++++--------- clang/lib/CodeGen/CodeGenFunction.h | 3 ++- clang/lib/Driver/SanitizerArgs.cpp | 20 +++++++++++--------- clang/lib/Frontend/CompilerInvocation.cpp | 7 ++++--- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1a09f08890edad..e9fd59df3f9111 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2548,10 +2548,14 @@ def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Gro def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Disable trapping for specified sanitizers">; -def fsanitize_nonmerged_handlers_EQ : CommaJoined<["-"], "fsanitize-nonmerged-handlers=">, Group<f_clang_Group>, - HelpText<"Enable non-merged handlers for specified sanitizers">; -def fno_sanitize_nonmerged_handlers_EQ : CommaJoined<["-"], "fno-sanitize-nonmerged-handlers=">, Group<f_clang_Group>, - HelpText<"Disable non-merged handlers for specified sanitizers">; +def fsanitize_nonmerged_handlers_EQ + : CommaJoined<["-"], "fsanitize-nonmerged-handlers=">, + Group<f_clang_Group>, + HelpText<"Enable non-merged handlers for specified sanitizers">; +def fno_sanitize_nonmerged_handlers_EQ + : CommaJoined<["-"], "fno-sanitize-nonmerged-handlers=">, + Group<f_clang_Group>, + HelpText<"Disable non-merged handlers for specified sanitizers">; def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, HelpText<"Enable trapping for all sanitizers">; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9c4dfaa393966b..9c0ddda2e28d9d 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3581,10 +3581,9 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, llvm::AttributeList::FunctionIndex, B), /*Local=*/true); llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); - NoMerge = NoMerge || - ClSanitizeDebugDeoptimization || - !CGF.CGM.getCodeGenOpts().OptimizationLevel || - (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || ClSanitizeDebugDeoptimization || + !CGF.CGM.getCodeGenOpts().OptimizationLevel || + (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (NoMerge) HandlerCall->addFnAttr(llvm::Attribute::NoMerge); if (!MayReturn) { @@ -3621,7 +3620,7 @@ void CodeGenFunction::EmitCheck( Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; if (CGM.getCodeGenOpts().SanitizeNonMergedHandlers.has(Checked[i].second)) - NoMerge = true; + NoMerge = true; } if (ClSanitizeGuardChecks) { @@ -3916,10 +3915,9 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - NoMerge = NoMerge || - ClSanitizeDebugDeoptimization || - !CGM.getCodeGenOpts().OptimizationLevel || - (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || ClSanitizeDebugDeoptimization || + !CGM.getCodeGenOpts().OptimizationLevel || + (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (TrapBB && !NoMerge) { auto Call = TrapBB->begin(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index c8e17b943c35f0..99a2a44248d274 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5166,7 +5166,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. - void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge = false); + void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, + bool NoMerge = false); /// Emit a call to trap or debugtrap and attach function attribute /// "trap-func-name" if specified. diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 741a4e5651f6d9..969d112e570474 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1461,15 +1461,17 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors) { - assert((A->getOption().matches(options::OPT_fsanitize_EQ) || - A->getOption().matches(options::OPT_fno_sanitize_EQ) || - A->getOption().matches(options::OPT_fsanitize_recover_EQ) || - A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || - A->getOption().matches(options::OPT_fsanitize_trap_EQ) || - A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) || - A->getOption().matches(options::OPT_fsanitize_nonmerged_handlers_EQ) || - A->getOption().matches(options::OPT_fno_sanitize_nonmerged_handlers_EQ)) && - "Invalid argument in parseArgValues!"); + assert( + (A->getOption().matches(options::OPT_fsanitize_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_EQ) || + A->getOption().matches(options::OPT_fsanitize_recover_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || + A->getOption().matches(options::OPT_fsanitize_trap_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) || + A->getOption().matches(options::OPT_fsanitize_nonmerged_handlers_EQ) || + A->getOption().matches( + options::OPT_fno_sanitize_nonmerged_handlers_EQ)) && + "Invalid argument in parseArgValues!"); SanitizerMask Kinds; for (int i = 0, n = A->getNumValues(); i != n; ++i) { const char *Value = A->getValue(i); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index fbd736822ca085..7fa01292f532c0 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1792,7 +1792,8 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap)) GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer); - for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeNonMergedHandlers)) + for (StringRef Sanitizer : + serializeSanitizerKinds(Opts.SanitizeNonMergedHandlers)) GenerateArg(Consumer, OPT_fsanitize_nonmerged_handlers_EQ, Sanitizer); if (!Opts.EmitVersionIdentMetadata) @@ -2273,8 +2274,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, Opts.SanitizeTrap); parseSanitizerKinds("-fsanitize-nonmerged-handlers=", - Args.getAllArgValues(OPT_fsanitize_nonmerged_handlers_EQ), Diags, - Opts.SanitizeNonMergedHandlers); + Args.getAllArgValues(OPT_fsanitize_nonmerged_handlers_EQ), + Diags, Opts.SanitizeNonMergedHandlers); Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); >From ac3cedf583893433ccd87ddf2b3cfc1420adde07 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 18:59:39 +0000 Subject: [PATCH 05/12] Fix test --- clang/test/Driver/fsanitize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index efb73fba087c88..2d34ae871b6f55 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -11,8 +11,8 @@ // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined -fno-sanitize-nonmerged-handlers=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED2 -// CHECK-UNDEFINED-NONMERGED: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound,vptr" -// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound,vptr" +// CHECK-UNDEFINED-NONMERGED: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" +// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED // CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} >From 4b0d6d3eaed6b7e225b1b2ff220d0f67f84bab57 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 19:07:48 +0000 Subject: [PATCH 06/12] Update ubsan-trap-merge.c --- clang/test/CodeGen/ubsan-trap-merge.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/test/CodeGen/ubsan-trap-merge.c b/clang/test/CodeGen/ubsan-trap-merge.c index 412ec7b09744ef..865250c694fa22 100644 --- a/clang/test/CodeGen/ubsan-trap-merge.c +++ b/clang/test/CodeGen/ubsan-trap-merge.c @@ -1,11 +1,16 @@ // NOTE: Assertions have mostly been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // The most important assertion is the attributes at the end of the file, which -// shows whether -ubsan-unique-traps attaches 'nomerge' to each ubsan call. +// shows whether -ubsan-unique-traps and -fsanitize-nonmerged-handlers attach +// 'nomerge' to each ubsan call. // // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefix=TRAP // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - | FileCheck %s --check-prefix=HANDLER // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefix=MINRT // +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefix=TRAP +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - | FileCheck %s --check-prefix=HANDLER +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefix=MINRT +// // REQUIRES: x86-registered-target // TRAP-LABEL: define dso_local range(i32 -2147483523, -2147483648) i32 @f( @@ -264,6 +269,7 @@ int h(int x, int y) { int m(int x, int y) { return f(x) + g(y); } +//. // TRAP: attributes #[[ATTR4]] = { nomerge noreturn nounwind } // HANDLER: attributes #[[ATTR4]] = { nomerge noreturn nounwind } // MINRT: attributes #[[ATTR4]] = { nomerge noreturn nounwind } >From 29a1034d5daa3a18fb0e4128b8ffd5ac34188565 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 19:09:47 +0000 Subject: [PATCH 07/12] Remove unnecessary comment --- clang/test/CodeGen/ubsan-trap-merge.c | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/CodeGen/ubsan-trap-merge.c b/clang/test/CodeGen/ubsan-trap-merge.c index 865250c694fa22..3a5a551fa7afa6 100644 --- a/clang/test/CodeGen/ubsan-trap-merge.c +++ b/clang/test/CodeGen/ubsan-trap-merge.c @@ -269,7 +269,6 @@ int h(int x, int y) { int m(int x, int y) { return f(x) + g(y); } -//. // TRAP: attributes #[[ATTR4]] = { nomerge noreturn nounwind } // HANDLER: attributes #[[ATTR4]] = { nomerge noreturn nounwind } // MINRT: attributes #[[ATTR4]] = { nomerge noreturn nounwind } >From 1fb3dd94d0113299b8f78feb348c65fe1ff30674 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 19:23:28 +0000 Subject: [PATCH 08/12] Don't exclude vptr --- clang/lib/Driver/SanitizerArgs.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 969d112e570474..05ab34636930e5 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -69,8 +69,7 @@ static const SanitizerMask TrappingSupported = SanitizerKind::LocalBounds | SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask NonMergedDefault; -static const SanitizerMask NonMergedSupported = - (SanitizerKind::Undefined & ~SanitizerKind::Vptr); +static const SanitizerMask NonMergedSupported = SanitizerKind::Undefined; static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | >From 5136ad57f9e020631f7eee490903b5feb3799f86 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 20:53:42 +0000 Subject: [PATCH 09/12] Rename flag to -fsanitize-merge --- clang/include/clang/Basic/CodeGenOptions.h | 6 ++-- clang/include/clang/Driver/Options.td | 12 ++++---- clang/include/clang/Driver/SanitizerArgs.h | 2 +- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/Driver/SanitizerArgs.cpp | 35 +++++++++++----------- clang/lib/Frontend/CompilerInvocation.cpp | 10 +++---- clang/test/CodeGen/ubsan-trap-merge.c | 10 +++---- clang/test/Driver/fsanitize.c | 8 ++--- 8 files changed, 42 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9b97adce42cc2a..8097c9ef772bc7 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -380,9 +380,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// Set of sanitizer checks that trap rather than diagnose. SanitizerSet SanitizeTrap; - /// Set of sanitizer checks that have non-merged handlers (better - /// debuggability at the expense of code size). - SanitizerSet SanitizeNonMergedHandlers; + /// Set of sanitizer checks that can merge handlers (smaller code size at + /// the expense of debuggability). + SanitizerSet SanitizeMergeHandlers; /// List of backend command-line options for -fembed-bitcode. std::vector<uint8_t> CmdArgs; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e9fd59df3f9111..99e06c7ca96d88 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2548,14 +2548,14 @@ def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Gro def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Disable trapping for specified sanitizers">; -def fsanitize_nonmerged_handlers_EQ - : CommaJoined<["-"], "fsanitize-nonmerged-handlers=">, +def fsanitize_merge_handlers_EQ + : CommaJoined<["-"], "fsanitize-merge=">, Group<f_clang_Group>, - HelpText<"Enable non-merged handlers for specified sanitizers">; -def fno_sanitize_nonmerged_handlers_EQ - : CommaJoined<["-"], "fno-sanitize-nonmerged-handlers=">, + HelpText<"Allow compiler to merge handlers for specified sanitizers">; +def fno_sanitize_merge_handlers_EQ + : CommaJoined<["-"], "fno-sanitize-merge=">, Group<f_clang_Group>, - HelpText<"Disable non-merged handlers for specified sanitizers">; + HelpText<"Do not allow compiler to merge handlers for specified sanitizers">; def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, HelpText<"Enable trapping for all sanitizers">; diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 28cfe72d6a34bd..7410ad4303011c 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -25,7 +25,7 @@ class SanitizerArgs { SanitizerSet Sanitizers; SanitizerSet RecoverableSanitizers; SanitizerSet TrapSanitizers; - SanitizerSet NonMergedHandlers; + SanitizerSet MergeHandlers; std::vector<std::string> UserIgnorelistFiles; std::vector<std::string> SystemIgnorelistFiles; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9c0ddda2e28d9d..d3fa5be6777ef4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3619,7 +3619,7 @@ void CodeGenFunction::EmitCheck( : FatalCond; Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; - if (CGM.getCodeGenOpts().SanitizeNonMergedHandlers.has(Checked[i].second)) + if (!CGM.getCodeGenOpts().SanitizeMergeHandlers.has(Checked[i].second)) NoMerge = true; } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 05ab34636930e5..a1c10adaffad03 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -68,8 +68,8 @@ static const SanitizerMask TrappingSupported = SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::LocalBounds | SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; -static const SanitizerMask NonMergedDefault; -static const SanitizerMask NonMergedSupported = SanitizerKind::Undefined; +static const SanitizerMask MergeDefault = SanitizerKind::Undefined; +static const SanitizerMask MergeSupported = SanitizerKind::Undefined; static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | @@ -699,15 +699,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, RecoverableKinds &= ~TrappingKinds; // Parse -f(no-)?sanitize-nonmerged-handlers flags - SanitizerMask AlwaysNonMerged; // Empty - SanitizerMask NeverNonMerged = ~(setGroupBits(NonMergedSupported)); - SanitizerMask NonMergedKinds = parseSanitizeArgs( - D, Args, DiagnoseErrors, NonMergedDefault, AlwaysNonMerged, - NeverNonMerged, options::OPT_fsanitize_nonmerged_handlers_EQ, - options::OPT_fno_sanitize_nonmerged_handlers_EQ); - NonMergedKinds |= AlwaysNonMerged; - NonMergedKinds &= ~NeverNonMerged; - NonMergedKinds &= Kinds; + SanitizerMask AlwaysMerge; // Empty + SanitizerMask NeverMerge = ~(setGroupBits(MergeSupported)); + SanitizerMask MergeKinds = parseSanitizeArgs( + D, Args, DiagnoseErrors, MergeDefault, AlwaysMerge, + NeverMerge, options::OPT_fsanitize_merge_handlers_EQ, + options::OPT_fno_sanitize_merge_handlers_EQ); + MergeKinds |= AlwaysMerge; + MergeKinds &= ~NeverMerge; + MergeKinds &= Kinds; // Setup ignorelist files. // Add default ignorelist from resource directory for activated sanitizers, @@ -1127,7 +1127,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, assert(!(RecoverableKinds & TrappingKinds) && "Overlap between recoverable and trapping sanitizers"); - NonMergedHandlers.Mask |= NonMergedKinds; + MergeHandlers.Mask |= MergeKinds; } static std::string toString(const clang::SanitizerSet &Sanitizers) { @@ -1289,9 +1289,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back( Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers))); - if (!NonMergedHandlers.empty()) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-nonmerged-handlers=" + - toString(NonMergedHandlers))); + if (!MergeHandlers.empty()) + CmdArgs.push_back(Args.MakeArgString("-fsanitize-merge=" + + toString(MergeHandlers))); addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-ignorelist=", UserIgnorelistFiles); @@ -1467,9 +1467,8 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) || A->getOption().matches(options::OPT_fsanitize_trap_EQ) || A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) || - A->getOption().matches(options::OPT_fsanitize_nonmerged_handlers_EQ) || - A->getOption().matches( - options::OPT_fno_sanitize_nonmerged_handlers_EQ)) && + A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) && "Invalid argument in parseArgValues!"); SanitizerMask Kinds; for (int i = 0, n = A->getNumValues(); i != n; ++i) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7fa01292f532c0..348c56cc37da3f 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1793,8 +1793,8 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer); for (StringRef Sanitizer : - serializeSanitizerKinds(Opts.SanitizeNonMergedHandlers)) - GenerateArg(Consumer, OPT_fsanitize_nonmerged_handlers_EQ, Sanitizer); + serializeSanitizerKinds(Opts.SanitizeMergeHandlers)) + GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer); if (!Opts.EmitVersionIdentMetadata) GenerateArg(Consumer, OPT_Qn); @@ -2273,9 +2273,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, parseSanitizerKinds("-fsanitize-trap=", Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, Opts.SanitizeTrap); - parseSanitizerKinds("-fsanitize-nonmerged-handlers=", - Args.getAllArgValues(OPT_fsanitize_nonmerged_handlers_EQ), - Diags, Opts.SanitizeNonMergedHandlers); + parseSanitizerKinds("-fsanitize-merge=", + Args.getAllArgValues(OPT_fsanitize_merge_handlers_EQ), + Diags, Opts.SanitizeMergeHandlers); Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); diff --git a/clang/test/CodeGen/ubsan-trap-merge.c b/clang/test/CodeGen/ubsan-trap-merge.c index 3a5a551fa7afa6..df7737d66f76af 100644 --- a/clang/test/CodeGen/ubsan-trap-merge.c +++ b/clang/test/CodeGen/ubsan-trap-merge.c @@ -1,15 +1,15 @@ // NOTE: Assertions have mostly been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // The most important assertion is the attributes at the end of the file, which -// shows whether -ubsan-unique-traps and -fsanitize-nonmerged-handlers attach -// 'nomerge' to each ubsan call. +// shows whether -ubsan-unique-traps and -fno-sanitize-merge attach 'nomerge' +// to each ubsan call. // // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefix=TRAP // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - | FileCheck %s --check-prefix=HANDLER // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefix=MINRT // -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefix=TRAP -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - | FileCheck %s --check-prefix=HANDLER -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fsanitize-nonmerged-handlers=signed-integer-overflow %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefix=MINRT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefix=TRAP +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - | FileCheck %s --check-prefix=HANDLER +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefix=MINRT // // REQUIRES: x86-registered-target diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 2d34ae871b6f55..0a909beca59964 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -9,10 +9,10 @@ // CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" // CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-nonmerged-handlers=undefined -fno-sanitize-nonmerged-handlers=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED2 -// CHECK-UNDEFINED-NONMERGED: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" -// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-nonmerged-handlers=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED2 +// CHECK-UNDEFINED-NONMERGED: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" +// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED // CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} >From 61381a8f99a8d3b9e6d3109496640c4cd66c57bc Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 21:56:51 +0000 Subject: [PATCH 10/12] Add -fsanitize-merge (no =) and -fno-sanitize-merge (no =) --- clang/include/clang/Driver/Options.td | 19 +++++++++++++------ clang/test/Driver/fsanitize.c | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 99e06c7ca96d88..fc579db6c90b92 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2548,6 +2548,13 @@ def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Gro def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Disable trapping for specified sanitizers">; +def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, + Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, + HelpText<"Enable trapping for all sanitizers">; +def fno_sanitize_trap : Flag<["-"], "fno-sanitize-trap">, Group<f_clang_Group>, + Alias<fno_sanitize_trap_EQ>, AliasArgs<["all"]>, + Visibility<[ClangOption, CLOption]>, + HelpText<"Disable trapping for all sanitizers">; def fsanitize_merge_handlers_EQ : CommaJoined<["-"], "fsanitize-merge=">, Group<f_clang_Group>, @@ -2556,13 +2563,13 @@ def fno_sanitize_merge_handlers_EQ : CommaJoined<["-"], "fno-sanitize-merge=">, Group<f_clang_Group>, HelpText<"Do not allow compiler to merge handlers for specified sanitizers">; -def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, - Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, - HelpText<"Enable trapping for all sanitizers">; -def fno_sanitize_trap : Flag<["-"], "fno-sanitize-trap">, Group<f_clang_Group>, - Alias<fno_sanitize_trap_EQ>, AliasArgs<["all"]>, +def fsanitize_merge_handlers : Flag<["-"], "fsanitize-merge">, Group<f_clang_Group>, + Alias<fsanitize_merge_handlers_EQ>, AliasArgs<["all"]>, + HelpText<"Allow compiler to merge handlers for all sanitizers">; +def fno_sanitize_merge_handlers : Flag<["-"], "fno-sanitize-merge">, Group<f_clang_Group>, + Alias<fno_sanitize_merge_handlers_EQ>, AliasArgs<["all"]>, Visibility<[ClangOption, CLOption]>, - HelpText<"Disable trapping for all sanitizers">; + HelpText<"Do not allow compiler to merge handlers for any sanitizers">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["undefined"]>; diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 0a909beca59964..759ace0290d81b 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -9,10 +9,18 @@ // CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" // CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NONMERGED2 -// CHECK-UNDEFINED-NONMERGED: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" -// CHECK-UNDEFINED-NONMERGED2: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// CHECK-UNDEFINED-MERGE: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" + +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// CHECK-UNDEFINED-MERGE2: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" + +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge %s -### 2>&1 | not FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE3 +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=undefined %s -### 2>&1 | not FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE3 +// CHECK-UNDEFINED-MERGE3: "-fsanitize-merge" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED // CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} >From 5105ba95ab80546a63a4d8fe6e23d6c371f5264f Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 22:22:09 +0000 Subject: [PATCH 11/12] Fix test assertion labels --- clang/test/Driver/fsanitize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 759ace0290d81b..ff790191104501 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -14,8 +14,8 @@ // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE // CHECK-UNDEFINED-MERGE: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE2 +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=signed-integer-overflow %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE2 // CHECK-UNDEFINED-MERGE2: "-fsanitize-merge=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge %s -### 2>&1 | not FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE3 >From 20963344b537928071b55f1bda8106286df661f9 Mon Sep 17 00:00:00 2001 From: Thurston Dang <thurs...@google.com> Date: Wed, 18 Dec 2024 22:24:21 +0000 Subject: [PATCH 12/12] Remove MergeSupported --- clang/lib/Driver/SanitizerArgs.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index a1c10adaffad03..30aa98db4a7169 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -69,7 +69,6 @@ static const SanitizerMask TrappingSupported = SanitizerKind::LocalBounds | SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask MergeDefault = SanitizerKind::Undefined; -static const SanitizerMask MergeSupported = SanitizerKind::Undefined; static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | @@ -700,13 +699,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, // Parse -f(no-)?sanitize-nonmerged-handlers flags SanitizerMask AlwaysMerge; // Empty - SanitizerMask NeverMerge = ~(setGroupBits(MergeSupported)); + SanitizerMask NeverMerge; // Empty SanitizerMask MergeKinds = parseSanitizeArgs( D, Args, DiagnoseErrors, MergeDefault, AlwaysMerge, NeverMerge, options::OPT_fsanitize_merge_handlers_EQ, options::OPT_fno_sanitize_merge_handlers_EQ); - MergeKinds |= AlwaysMerge; - MergeKinds &= ~NeverMerge; + MergeKinds |= AlwaysMerge; // No-op + MergeKinds &= ~NeverMerge; // No-op MergeKinds &= Kinds; // Setup ignorelist files. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits