[clang] [ubsan] Add -fsanitize-merge (and -fno-sanitize-merge) (PR #120464)
Thurston Dang via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 18 15:08:22 PST 2024
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 <thurston at google.com>
Date: Wed, 18 Dec 2024 18:37:11 +0000
Subject: [PATCH 01/17] [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 <thurston at google.com>
Date: Wed, 18 Dec 2024 18:58:19 +0000
Subject: [PATCH 02/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 18:58:38 +0000
Subject: [PATCH 03/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 18:59:13 +0000
Subject: [PATCH 04/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 18:59:39 +0000
Subject: [PATCH 05/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 19:07:48 +0000
Subject: [PATCH 06/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 19:09:47 +0000
Subject: [PATCH 07/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 19:23:28 +0000
Subject: [PATCH 08/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 20:53:42 +0000
Subject: [PATCH 09/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 21:56:51 +0000
Subject: [PATCH 10/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 22:22:09 +0000
Subject: [PATCH 11/17] 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 <thurston at google.com>
Date: Wed, 18 Dec 2024 22:24:21 +0000
Subject: [PATCH 12/17] 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.
>From 8dbb32ab37f3255b579498db549ddd24bf6813e0 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 18 Dec 2024 22:30:35 +0000
Subject: [PATCH 13/17] clang-format
---
clang/lib/Driver/SanitizerArgs.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 30aa98db4a7169..3ae287016b2fc2 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -699,7 +699,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Parse -f(no-)?sanitize-nonmerged-handlers flags
SanitizerMask AlwaysMerge; // Empty
- SanitizerMask NeverMerge; // Empty
+ SanitizerMask NeverMerge; // Empty
SanitizerMask MergeKinds = parseSanitizeArgs(
D, Args, DiagnoseErrors, MergeDefault, AlwaysMerge,
NeverMerge, options::OPT_fsanitize_merge_handlers_EQ,
>From 0914e93a0f70926c890a6f744a387e3cd302f6f2 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 18 Dec 2024 22:49:28 +0000
Subject: [PATCH 14/17] Improve tests for flag parsing
---
clang/test/Driver/fsanitize.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index ff790191104501..6719f4afca6b4e 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -9,17 +9,35 @@
// 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 %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
+// The trailing -fsanitize-merge takes precedence
+// 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
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge -fsanitize-merge %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=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 -fno-sanitize-merge=undefined -fsanitize-merge=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=signed-integer-overflow -fsanitize-merge %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=signed-integer-overflow -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-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
+// The trailing arguments (-fsanitize-merge -fno-sanitize-merge=signed-integer-overflow) take precedence
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -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 -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
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge -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 -fno-sanitize-merge -fsanitize-merge=undefined -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 -fno-sanitize-merge=signed-integer-overflow -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 -fno-sanitize-merge=signed-integer-overflow -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
-// 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
+// The trailing -fno-sanitize-merge takes precedence
+// 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
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge -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 -fsanitize-merge -fno-sanitize-merge=undefined %s -### 2>&1 | not FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE3
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=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 -fsanitize-merge=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
>From 62bbb52054e36667b70bbb5f5a241a3485e726bd Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 18 Dec 2024 22:56:01 +0000
Subject: [PATCH 15/17] clang-format
---
clang/lib/Driver/SanitizerArgs.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 3ae287016b2fc2..097c8207d7f959 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -700,10 +700,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Parse -f(no-)?sanitize-nonmerged-handlers flags
SanitizerMask AlwaysMerge; // Empty
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);
+ SanitizerMask MergeKinds =
+ parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, AlwaysMerge,
+ NeverMerge, options::OPT_fsanitize_merge_handlers_EQ,
+ options::OPT_fno_sanitize_merge_handlers_EQ);
MergeKinds |= AlwaysMerge; // No-op
MergeKinds &= ~NeverMerge; // No-op
MergeKinds &= Kinds;
@@ -1289,8 +1289,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
if (!MergeHandlers.empty())
- CmdArgs.push_back(Args.MakeArgString("-fsanitize-merge=" +
- toString(MergeHandlers)));
+ CmdArgs.push_back(
+ Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
addSpecialCaseListOpt(Args, CmdArgs,
"-fsanitize-ignorelist=", UserIgnorelistFiles);
>From 1fa770ca6caec2c4c682d11ef06f248b28bf24ae Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 18 Dec 2024 23:01:07 +0000
Subject: [PATCH 16/17] Add parsing test case for "-fsanitize-merge
-fno-sanitize-merge=alignment,null"
---
clang/test/Driver/fsanitize.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index 6719f4afca6b4e..7375e12fc47ad6 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -40,6 +40,16 @@
// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=undefined %s -### 2>&1 | not FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE3
// CHECK-UNDEFINED-MERGE3: "-fsanitize-merge"
+// The trailing arguments (-fsanitize-merge -fno-sanitize-merge=alignment,null) take precedence
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fsanitize-merge=undefined -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge -fsanitize-merge -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge -fsanitize-merge=undefined -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=signed-integer-overflow -fsanitize-merge -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-trap=undefined -fno-sanitize-merge=signed-integer-overflow -fsanitize-merge=undefined -fno-sanitize-merge=alignment,null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-MERGE4
+// CHECK-UNDEFINED-MERGE4: "-fsanitize-merge=array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,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 %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 ac0d0bb1ee455ad3edb143b36c7e5aff1ea9a435 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Wed, 18 Dec 2024 23:03:05 +0000
Subject: [PATCH 17/17] Remove AlwaysMerge and NeverMerge per Vitaly's feedback
---
clang/lib/Driver/SanitizerArgs.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 097c8207d7f959..625077e9346f99 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -698,14 +698,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds &= ~TrappingKinds;
// Parse -f(no-)?sanitize-nonmerged-handlers flags
- SanitizerMask AlwaysMerge; // Empty
- SanitizerMask NeverMerge; // Empty
SanitizerMask MergeKinds =
- parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, AlwaysMerge,
- NeverMerge, options::OPT_fsanitize_merge_handlers_EQ,
+ parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {},
+ {}, options::OPT_fsanitize_merge_handlers_EQ,
options::OPT_fno_sanitize_merge_handlers_EQ);
- MergeKinds |= AlwaysMerge; // No-op
- MergeKinds &= ~NeverMerge; // No-op
MergeKinds &= Kinds;
// Setup ignorelist files.
More information about the cfe-commits
mailing list