Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ca1fabc
[sanitizer] Parse weighted sanitizer args and -fno-sanitize-top-hot
thurstond Jan 4, 2025
7701659
clang-format
thurstond Jan 4, 2025
ade9e63
Update flag description
thurstond Jan 6, 2025
6e20cf8
Plumb values through CodeGen
thurstond Jan 6, 2025
cc3a2ac
clang-format
thurstond Jan 6, 2025
9a2a0e8
using SanitizerMaskWeights = std::array<float, SanitizerKind::SO_Count>
thurstond Jan 6, 2025
bfa57c6
clang-format
thurstond Jan 6, 2025
346adc1
Rename Weights to Cutoffs
thurstond Jan 6, 2025
66dbc49
Limit changes to Driver
thurstond Jan 6, 2025
6f5e714
Reorder to make comment more logical
thurstond Jan 7, 2025
fc623f2
Refactor into parseArgCutoffs; update comment
thurstond Jan 7, 2025
00d135e
Remove unnecessary suppression
thurstond Jan 7, 2025
4d97bed
clang-format
thurstond Jan 7, 2025
1f528c5
Change Cutoffs* to Cutoffs&
thurstond Jan 7, 2025
071e10e
Remove SanitizerMask TopHot
thurstond Jan 7, 2025
c970179
Rely on RVO
thurstond Jan 7, 2025
b2bb1d6
Fix uninitialized memory
thurstond Jan 7, 2025
369e6c8
clang-format
thurstond Jan 7, 2025
c6d4e73
Allow passing -fno-sanitize-top-hot=undefined=0.0. Add more tests.
thurstond Jan 7, 2025
85b898c
Check cutoffs in parsing. Update tests.
thurstond Jan 7, 2025
6cd43bb
Change cutoffs parser to return an empty SanitizerMask (Cutoffs becom…
thurstond Jan 7, 2025
c4b6a68
Simplify parseNoSanitizeHotArgs by not relying on parseSanitizeArgs
thurstond Jan 7, 2025
57d6c59
Change parseArgCutoffs to void return
thurstond Jan 7, 2025
56ba349
Convert SanitizerMaskCutoffs to struct
thurstond Jan 7, 2025
2298f93
Omit redundant initialization
thurstond Jan 7, 2025
a5ff144
Remove unnecessary braces
thurstond Jan 7, 2025
46e90e5
Rename 'data' to 'cutoffs'
thurstond Jan 7, 2025
58550e9
Improve comment
vitalybuka Jan 7, 2025
b2f0e5d
Make SanitizerMaskCutoffs class
vitalybuka Jan 7, 2025
be0f4e8
Remove unrelated change
vitalybuka Jan 7, 2025
a21c77b
Simplify parseSanitizerWeightedValue
vitalybuka Jan 7, 2025
27fe651
Fix clamp call
vitalybuka Jan 7, 2025
45a9fa5
Whitespace
thurstond Jan 7, 2025
5ab2a2b
Fix case in comment
vitalybuka Jan 7, 2025
a9c8d58
Hide clear logic into SanitizerMaskCutoffs
vitalybuka Jan 8, 2025
b668bcb
use string::empty
vitalybuka Jan 8, 2025
9321def
Return SanitizerMaskCutoffs from parseNoSanitizeHotArgs by value
vitalybuka Jan 8, 2025
d39638d
Extract ::set
vitalybuka Jan 8, 2025
99cfdb2
return float by value
vitalybuka Jan 8, 2025
58c752b
Updates
vitalybuka Jan 8, 2025
f27eb85
Include
vitalybuka Jan 8, 2025
1aed608
Fix clamp for double
vitalybuka Jan 8, 2025
b82e48d
Format
vitalybuka Jan 8, 2025
a8e79ce
Claim matched arguments
thurstond Jan 8, 2025
d3fa04d
Change test to use -Werror and not check for error messages, per Fang…
thurstond Jan 8, 2025
55f42e7
Format
vitalybuka Jan 8, 2025
d8a3696
This reverts part of commit b82e48d83663afead2b5b0ed4c5f2fb2b32683ad.
vitalybuka Jan 8, 2025
17ecca4
rtrim('0')
vitalybuka Jan 8, 2025
b43d513
clang-format
vitalybuka Jan 8, 2025
caa4964
Rename -fno-sanitize-top-hot to -fsanitize-skip-hot-cutoff
thurstond Jan 9, 2025
9837912
clang-format
thurstond Jan 9, 2025
10e0a55
++clang
thurstond Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,14 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// the expense of debuggability).
SanitizerSet SanitizeMergeHandlers;

/// Set of thresholds: the top hottest code responsible for the given
/// fraction of PGO counters will be excluded from sanitization
/// (0.0 [default] = skip none, 1.0 = skip all).
SanitizerMaskCutoffs NoSanitizeTopHotCutoffs = {0};
/// N.B. The cutoffs contain strictly more information than the SanitizerSet,
/// but the SanitizerSet is more efficient for some calculations.
SanitizerSet NoSanitizeTopHot;

/// List of backend command-line options for -fembed-bitcode.
std::vector<uint8_t> CmdArgs;

Expand Down
16 changes: 16 additions & 0 deletions clang/include/clang/Basic/Sanitizers.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ struct SanitizerKind {
#include "clang/Basic/Sanitizers.def"
}; // SanitizerKind

using SanitizerMaskCutoffs = std::array<float, SanitizerKind::SO_Count>;

struct SanitizerSet {
/// Check if a certain (single) sanitizer is enabled.
bool has(SanitizerMask K) const {
Expand Down Expand Up @@ -186,10 +188,24 @@ struct SanitizerSet {
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);

/// Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or
/// -fno-sanitize= value list.
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
/// The relevant weight(s) are updated in the passed array.
/// Individual Cutoffs are never reset to zero unless explicitly set
/// (e.g., 'null=0.0').
SanitizerMask parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
SanitizerMaskCutoffs *Cutoffs);

/// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
void serializeSanitizerSet(SanitizerSet Set,
SmallVectorImpl<StringRef> &Values);

/// Serialize a SanitizerMaskCutoffs into values for -fsanitize= or
/// -fno-sanitize=.
void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs Cutoffs,
SmallVectorImpl<std::string> &Values);

/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
/// this group enables.
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,13 @@ def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-unde
HelpText<"Strip (or keep only, if negative) a given number of path components "
"when emitting check metadata.">,
MarshallingInfoInt<CodeGenOpts<"EmitCheckPathComponentsToStrip">, "0", "int">;
def fno_sanitize_top_hot_EQ
: CommaJoined<["-"], "fno-sanitize-top-hot=">,
Group<f_clang_Group>,
HelpText<"Exclude sanitization for the top hottest code responsible for "
"the given fraction of PGO counters "
"(0.0 [default] = skip none; 1.0 = skip all). "
"Argument format: <sanitizer1>=,<sanitizer2>=,...">;

} // end -f[no-]sanitize* flags

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/SanitizerArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class SanitizerArgs {
SanitizerSet RecoverableSanitizers;
SanitizerSet TrapSanitizers;
SanitizerSet MergeHandlers;
SanitizerSet TopHot;
SanitizerMaskCutoffs TopHotCutoffs = {0};

std::vector<std::string> UserIgnorelistFiles;
std::vector<std::string> SystemIgnorelistFiles;
Expand Down
40 changes: 40 additions & 0 deletions clang/lib/Basic/Sanitizers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,37 @@ SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
return ParsedKind;
}

SanitizerMask
clang::parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
SanitizerMaskCutoffs *Cutoffs) {
SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
#define SANITIZER(NAME, ID) .StartsWith(NAME "=", SanitizerKind::ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS) \
.StartsWith(NAME "=", \
AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
#include "clang/Basic/Sanitizers.def"
.Default(SanitizerMask());

if (ParsedKind && Cutoffs) {
size_t equalsIndex = Value.find_first_of('=');
if (equalsIndex != llvm::StringLiteral::npos) {
double arg;
if ((Value.size() > (equalsIndex + 1)) &&
!Value.substr(equalsIndex + 1).getAsDouble(arg)) {
// AllowGroups is already taken into account for ParsedKind,
// hence we unconditionally expandSanitizerGroups.
SanitizerMask ExpandedKind = expandSanitizerGroups(ParsedKind);

for (unsigned int i = 0; i < SanitizerKind::SO_Count; i++)
if (ExpandedKind & SanitizerMask::bitPosToMask(i))
(*Cutoffs)[i] = arg;
}
}
}

return ParsedKind;
}

void clang::serializeSanitizerSet(SanitizerSet Set,
SmallVectorImpl<StringRef> &Values) {
#define SANITIZER(NAME, ID) \
Expand All @@ -44,6 +75,15 @@ void clang::serializeSanitizerSet(SanitizerSet Set,
#include "clang/Basic/Sanitizers.def"
}

void clang::serializeSanitizerMaskCutoffs(
const SanitizerMaskCutoffs Cutoffs, SmallVectorImpl<std::string> &Values) {
#define SANITIZER(NAME, ID) \
if (Cutoffs[SanitizerKind::SO_##ID]) \
Values.push_back(std::string(NAME "=") + \
std::to_string(Cutoffs[SanitizerKind::SO_##ID]));
#include "clang/Basic/Sanitizers.def"
}

SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) {
#define SANITIZER(NAME, ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS) \
Expand Down
95 changes: 72 additions & 23 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ enum BinaryMetadataFeature {
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
/// invalid components. Returns a SanitizerMask.
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors);
bool DiagnoseErrors,
SanitizerMaskCutoffs *Cutoffs);

/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
/// components. Returns OR of members of \c CoverageFeature enumeration.
Expand Down Expand Up @@ -260,7 +261,7 @@ static SanitizerMask
parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
bool DiagnoseErrors, SanitizerMask Default,
SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
int OptOutID) {
int OptOutID, SanitizerMaskCutoffs *Cutoffs) {
assert(!(AlwaysIn & AlwaysOut) &&
"parseSanitizeArgs called with contradictory in/out requirements");

Expand All @@ -271,7 +272,7 @@ parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
SanitizerMask DiagnosedAlwaysOutViolations;
for (const auto *Arg : Args) {
if (Arg->getOption().matches(OptInID)) {
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors, Cutoffs);
// Report error if user explicitly tries to opt-in to an always-out
// sanitizer.
if (SanitizerMask KindsToDiagnose =
Expand All @@ -287,7 +288,7 @@ parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
Output |= expandSanitizerGroups(Add);
Arg->claim();
} else if (Arg->getOption().matches(OptOutID)) {
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors, Cutoffs);
// Report error if user explicitly tries to opt-out of an always-in
// sanitizer.
if (SanitizerMask KindsToDiagnose =
Expand Down Expand Up @@ -320,7 +321,15 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
// (not even in recover mode) in order to avoid the need for a ubsan runtime.
return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
NeverTrap, options::OPT_fsanitize_trap_EQ,
options::OPT_fno_sanitize_trap_EQ);
options::OPT_fno_sanitize_trap_EQ, nullptr);
}

static SanitizerMask parseNoSanitizeHotArgs(const Driver &D,
const llvm::opt::ArgList &Args,
bool DiagnoseErrors,
SanitizerMaskCutoffs *Cutoffs) {
return parseSanitizeArgs(D, Args, DiagnoseErrors, {}, {}, {},
options::OPT_fno_sanitize_top_hot_EQ, -1, Cutoffs);
}

bool SanitizerArgs::needsFuzzerInterceptors() const {
Expand Down Expand Up @@ -403,7 +412,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
Arg->claim();
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors, nullptr);

if (RemoveObjectSizeAtO0) {
AllRemove |= SanitizerKind::ObjectSize;
Expand Down Expand Up @@ -573,7 +582,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
Arg->claim();
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors, nullptr);
AllRemove |= expandSanitizerGroups(Remove);
}
}
Expand Down Expand Up @@ -698,7 +707,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask RecoverableKinds = parseSanitizeArgs(
D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
Unrecoverable, options::OPT_fsanitize_recover_EQ,
options::OPT_fno_sanitize_recover_EQ);
options::OPT_fno_sanitize_recover_EQ, nullptr);
RecoverableKinds |= AlwaysRecoverable;
RecoverableKinds &= ~Unrecoverable;
RecoverableKinds &= Kinds;
Expand All @@ -710,9 +719,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask MergeKinds =
parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {}, {},
options::OPT_fsanitize_merge_handlers_EQ,
options::OPT_fno_sanitize_merge_handlers_EQ);
options::OPT_fno_sanitize_merge_handlers_EQ, nullptr);
MergeKinds &= Kinds;

// Parse -fno-sanitize-top-hot flags
SanitizerMask TopHotMask =
parseNoSanitizeHotArgs(D, Args, DiagnoseErrors, &TopHotCutoffs);
(void)TopHotMask;

// Setup ignorelist files.
// Add default ignorelist from resource directory for activated sanitizers,
// and validate special case lists format.
Expand Down Expand Up @@ -1132,6 +1146,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
"Overlap between recoverable and trapping sanitizers");

MergeHandlers.Mask |= MergeKinds;

TopHotMask &= Sanitizers.Mask;
TopHot.Mask = TopHotMask;

// Zero out TopHot for unused sanitizers
for (unsigned int i = 0; i < SanitizerKind::SO_Count; i++) {
if (!(Sanitizers.Mask & SanitizerMask::bitPosToMask(i)))
TopHotCutoffs[i] = 0;
}
}

static std::string toString(const clang::SanitizerSet &Sanitizers) {
Expand All @@ -1146,6 +1169,19 @@ static std::string toString(const clang::SanitizerSet &Sanitizers) {
return Res;
}

static std::string toString(const clang::SanitizerMaskCutoffs &Cutoffs) {
std::string Res;
#define SANITIZER(NAME, ID) \
if (Cutoffs[SanitizerKind::SO_##ID]) { \
if (!Res.empty()) \
Res += ","; \
Res += std::string(NAME) + "=" + \
std::to_string(Cutoffs[SanitizerKind::SO_##ID]); \
}
#include "clang/Basic/Sanitizers.def"
return Res;
}

static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const char *SCLOptFlag,
Expand Down Expand Up @@ -1297,6 +1333,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));

std::string TopHotCutoffsStr = toString(TopHotCutoffs);
if (TopHotCutoffsStr != "")
CmdArgs.push_back(
Args.MakeArgString("-fno-sanitize-top-hot=" + TopHotCutoffsStr));

addSpecialCaseListOpt(Args, CmdArgs,
"-fsanitize-ignorelist=", UserIgnorelistFiles);
addSpecialCaseListOpt(Args, CmdArgs,
Expand Down Expand Up @@ -1463,17 +1504,18 @@ 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_merge_handlers_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
"Invalid argument in parseArgValues!");
bool DiagnoseErrors,
SanitizerMaskCutoffs *Cutoffs) {
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_merge_handlers_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_top_hot_EQ)) &&
"Invalid argument in parseArgValues!");
SanitizerMask Kinds;
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
const char *Value = A->getValue(i);
Expand All @@ -1482,8 +1524,15 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
0 == strcmp("all", Value))
Kind = SanitizerMask();
else
else if (A->getOption().matches(options::OPT_fno_sanitize_top_hot_EQ)) {
assert(
Cutoffs &&
"Null Cutoffs parameter provided for parsing fno_sanitize_top_hot!");
Kind = parseSanitizerWeightedValue(Value, /*AllowGroups=*/true, Cutoffs);
} else {
assert((!Cutoffs) && "Non-null Cutoffs parameter erroneously provided!");
Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
}

if (Kind)
Kinds |= Kind;
Expand Down Expand Up @@ -1586,12 +1635,12 @@ std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
const auto *Arg = *I;
if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
SanitizerMask AddKinds =
expandSanitizerGroups(parseArgValues(D, Arg, false));
expandSanitizerGroups(parseArgValues(D, Arg, false, nullptr));
if (AddKinds & Mask)
return describeSanitizeArg(Arg, Mask);
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
SanitizerMask RemoveKinds =
expandSanitizerGroups(parseArgValues(D, Arg, false));
expandSanitizerGroups(parseArgValues(D, Arg, false, nullptr));
Mask &= ~RemoveKinds;
}
}
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,19 @@ static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {
return Values;
}

static void parseSanitizerWeightedKinds(
StringRef FlagName, const std::vector<std::string> &Sanitizers,
DiagnosticsEngine &Diags, SanitizerSet &S, SanitizerMaskCutoffs *Cutoffs) {
for (const auto &Sanitizer : Sanitizers) {
SanitizerMask K =
parseSanitizerWeightedValue(Sanitizer, /*AllowGroups=*/false, Cutoffs);
if (K == SanitizerMask())
Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
else
S.set(K, true);
}
}

static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
ArgList &Args, DiagnosticsEngine &D,
XRayInstrSet &S) {
Expand Down Expand Up @@ -1796,6 +1809,11 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
serializeSanitizerKinds(Opts.SanitizeMergeHandlers))
GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer);

SmallVector<std::string, 4> Values;
serializeSanitizerMaskCutoffs(Opts.NoSanitizeTopHotCutoffs, Values);
for (std::string Sanitizer : Values)
GenerateArg(Consumer, OPT_fno_sanitize_top_hot_EQ, Sanitizer);

if (!Opts.EmitVersionIdentMetadata)
GenerateArg(Consumer, OPT_Qn);

Expand Down Expand Up @@ -2277,6 +2295,12 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Args.getAllArgValues(OPT_fsanitize_merge_handlers_EQ),
Diags, Opts.SanitizeMergeHandlers);

// Parse -fno-sanitize-top-hot= arguments.
parseSanitizerWeightedKinds("-fno-sanitize-top-hot=",
Args.getAllArgValues(OPT_fno_sanitize_top_hot_EQ),
Diags, Opts.NoSanitizeTopHot,
&Opts.NoSanitizeTopHotCutoffs);

Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);

if (!LangOpts->CUDAIsDevice)
Expand Down
1 change: 0 additions & 1 deletion clang/test/CodeGen/allow-ubsan-check.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -mllvm -ubsan-guard-checks -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=TRAP
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -mllvm -ubsan-guard-checks -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=RECOVER


// CHECK-LABEL: define dso_local i32 @div(
// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
Expand Down
Loading
Loading