[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Driver / SanitizerArgs.cpp
blobad68c086b71790cbf4927e691e7687a5e901ffd7
1 //===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "clang/Driver/SanitizerArgs.h"
9 #include "ToolChains/CommonArgs.h"
10 #include "clang/Basic/Sanitizers.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/Driver/DriverDiagnostic.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/ToolChain.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/SpecialCaseList.h"
20 #include "llvm/Support/VirtualFileSystem.h"
21 #include "llvm/TargetParser/AArch64TargetParser.h"
22 #include "llvm/TargetParser/RISCVTargetParser.h"
23 #include "llvm/TargetParser/TargetParser.h"
24 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
25 #include <memory>
27 using namespace clang;
28 using namespace clang::driver;
29 using namespace llvm::opt;
31 static const SanitizerMask NeedsUbsanRt =
32 SanitizerKind::Undefined | SanitizerKind::Integer |
33 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
34 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
35 SanitizerKind::ObjCCast;
36 static const SanitizerMask NeedsUbsanCxxRt =
37 SanitizerKind::Vptr | SanitizerKind::CFI;
38 static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
39 static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;
40 static const SanitizerMask NotAllowedWithExecuteOnly =
41 SanitizerKind::Function | SanitizerKind::KCFI;
42 static const SanitizerMask RequiresPIE =
43 SanitizerKind::DataFlow | SanitizerKind::Scudo;
44 static const SanitizerMask NeedsUnwindTables =
45 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
46 SanitizerKind::Memory | SanitizerKind::DataFlow;
47 static const SanitizerMask SupportsCoverage =
48 SanitizerKind::Address | SanitizerKind::HWAddress |
49 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
50 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
51 SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
52 SanitizerKind::KernelMemory | SanitizerKind::Leak |
53 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
54 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
55 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
56 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
57 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
58 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
59 static const SanitizerMask RecoverableByDefault =
60 SanitizerKind::Undefined | SanitizerKind::Integer |
61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
63 static const SanitizerMask Unrecoverable =
64 SanitizerKind::Unreachable | SanitizerKind::Return;
65 static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |
66 SanitizerKind::KernelHWAddress |
67 SanitizerKind::KCFI;
68 static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
69 static const SanitizerMask TrappingSupported =
70 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |
71 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
72 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
73 SanitizerKind::ObjCCast;
74 static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
75 static const SanitizerMask CFIClasses =
76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
78 SanitizerKind::CFIUnrelatedCast;
79 static const SanitizerMask CompatibleWithMinimalRuntime =
80 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
84 enum CoverageFeature {
85 CoverageFunc = 1 << 0,
86 CoverageBB = 1 << 1,
87 CoverageEdge = 1 << 2,
88 CoverageIndirCall = 1 << 3,
89 CoverageTraceBB = 1 << 4, // Deprecated.
90 CoverageTraceCmp = 1 << 5,
91 CoverageTraceDiv = 1 << 6,
92 CoverageTraceGep = 1 << 7,
93 Coverage8bitCounters = 1 << 8, // Deprecated.
94 CoverageTracePC = 1 << 9,
95 CoverageTracePCGuard = 1 << 10,
96 CoverageNoPrune = 1 << 11,
97 CoverageInline8bitCounters = 1 << 12,
98 CoveragePCTable = 1 << 13,
99 CoverageStackDepth = 1 << 14,
100 CoverageInlineBoolFlag = 1 << 15,
101 CoverageTraceLoads = 1 << 16,
102 CoverageTraceStores = 1 << 17,
103 CoverageControlFlow = 1 << 18,
106 enum BinaryMetadataFeature {
107 BinaryMetadataCovered = 1 << 0,
108 BinaryMetadataAtomics = 1 << 1,
109 BinaryMetadataUAR = 1 << 2,
112 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
113 /// invalid components. Returns a SanitizerMask.
114 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
115 bool DiagnoseErrors);
117 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
118 /// components. Returns OR of members of \c CoverageFeature enumeration.
119 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
120 bool DiagnoseErrors);
122 /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
123 /// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
124 static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
125 bool DiagnoseErrors);
127 /// Produce an argument string from ArgList \p Args, which shows how it
128 /// provides some sanitizer kind from \p Mask. For example, the argument list
129 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
130 /// would produce "-fsanitize=vptr".
131 static std::string lastArgumentForMask(const Driver &D,
132 const llvm::opt::ArgList &Args,
133 SanitizerMask Mask);
135 /// Produce an argument string from argument \p A, which shows how it provides
136 /// a value in \p Mask. For instance, the argument
137 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
138 /// "-fsanitize=alignment".
139 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
140 SanitizerMask Mask);
142 /// Produce a string containing comma-separated names of sanitizers in \p
143 /// Sanitizers set.
144 static std::string toString(const clang::SanitizerSet &Sanitizers);
146 /// Return true if an execute-only target disallows data access to code
147 /// sections.
148 static bool isExecuteOnlyTarget(const llvm::Triple &Triple,
149 const llvm::opt::ArgList &Args) {
150 if (Triple.isPS5())
151 return true;
152 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
153 options::OPT_mno_execute_only, false);
156 static void validateSpecialCaseListFormat(const Driver &D,
157 std::vector<std::string> &SCLFiles,
158 unsigned MalformedSCLErrorDiagID,
159 bool DiagnoseErrors) {
160 if (SCLFiles.empty())
161 return;
163 std::string BLError;
164 std::unique_ptr<llvm::SpecialCaseList> SCL(
165 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
166 if (!SCL.get() && DiagnoseErrors)
167 D.Diag(MalformedSCLErrorDiagID) << BLError;
170 static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
171 std::vector<std::string> &IgnorelistFiles,
172 bool DiagnoseErrors) {
173 struct Ignorelist {
174 const char *File;
175 SanitizerMask Mask;
176 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
177 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
178 {"memtag_ignorelist.txt", SanitizerKind::MemTag},
179 {"msan_ignorelist.txt", SanitizerKind::Memory},
180 {"tsan_ignorelist.txt", SanitizerKind::Thread},
181 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
182 {"cfi_ignorelist.txt", SanitizerKind::CFI},
183 {"ubsan_ignorelist.txt",
184 SanitizerKind::Undefined | SanitizerKind::Integer |
185 SanitizerKind::Nullability |
186 SanitizerKind::FloatDivideByZero}};
188 for (auto BL : Ignorelists) {
189 if (!(Kinds & BL.Mask))
190 continue;
192 clang::SmallString<64> Path(D.ResourceDir);
193 llvm::sys::path::append(Path, "share", BL.File);
194 if (D.getVFS().exists(Path))
195 IgnorelistFiles.push_back(std::string(Path.str()));
196 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
197 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
198 // should fail.
199 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
201 validateSpecialCaseListFormat(
202 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
203 DiagnoseErrors);
206 /// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
207 /// diagnosing any invalid file paths and validating special case list format.
208 static void parseSpecialCaseListArg(const Driver &D,
209 const llvm::opt::ArgList &Args,
210 std::vector<std::string> &SCLFiles,
211 llvm::opt::OptSpecifier SCLOptionID,
212 llvm::opt::OptSpecifier NoSCLOptionID,
213 unsigned MalformedSCLErrorDiagID,
214 bool DiagnoseErrors) {
215 for (const auto *Arg : Args) {
216 // Match -fsanitize-(coverage-)?(allow|ignore)list.
217 if (Arg->getOption().matches(SCLOptionID)) {
218 Arg->claim();
219 std::string SCLPath = Arg->getValue();
220 if (D.getVFS().exists(SCLPath)) {
221 SCLFiles.push_back(SCLPath);
222 } else if (DiagnoseErrors) {
223 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
225 // Match -fno-sanitize-ignorelist.
226 } else if (Arg->getOption().matches(NoSCLOptionID)) {
227 Arg->claim();
228 SCLFiles.clear();
231 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,
232 DiagnoseErrors);
235 /// Sets group bits for every group that has at least one representative already
236 /// enabled in \p Kinds.
237 static SanitizerMask setGroupBits(SanitizerMask Kinds) {
238 #define SANITIZER(NAME, ID)
239 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
240 if (Kinds & SanitizerKind::ID) \
241 Kinds |= SanitizerKind::ID##Group;
242 #include "clang/Basic/Sanitizers.def"
243 return Kinds;
246 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
247 const llvm::opt::ArgList &Args,
248 bool DiagnoseErrors) {
249 SanitizerMask TrapRemove; // During the loop below, the accumulated set of
250 // sanitizers disabled by the current sanitizer
251 // argument or any argument after it.
252 SanitizerMask TrappingKinds;
253 SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
255 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
256 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
257 Arg->claim();
258 SanitizerMask Add = parseArgValues(D, Arg, true);
259 Add &= ~TrapRemove;
260 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
261 if (InvalidValues && DiagnoseErrors) {
262 SanitizerSet S;
263 S.Mask = InvalidValues;
264 D.Diag(diag::err_drv_unsupported_option_argument)
265 << Arg->getSpelling() << toString(S);
267 TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
268 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
269 Arg->claim();
270 TrapRemove |=
271 expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
275 // Apply default trapping behavior.
276 TrappingKinds |= TrappingDefault & ~TrapRemove;
278 return TrappingKinds;
281 bool SanitizerArgs::needsFuzzerInterceptors() const {
282 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
285 bool SanitizerArgs::needsUbsanRt() const {
286 // All of these include ubsan.
287 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
288 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
289 (needsScudoRt() && !requiresMinimalRuntime()))
290 return false;
292 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
293 CoverageFeatures;
296 bool SanitizerArgs::needsCfiRt() const {
297 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
298 CfiCrossDso && !ImplicitCfiRuntime;
301 bool SanitizerArgs::needsCfiDiagRt() const {
302 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
303 CfiCrossDso && !ImplicitCfiRuntime;
306 bool SanitizerArgs::requiresPIE() const {
307 return NeedPIE || (Sanitizers.Mask & RequiresPIE);
310 bool SanitizerArgs::needsUnwindTables() const {
311 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
314 bool SanitizerArgs::needsLTO() const {
315 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
318 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
319 const llvm::opt::ArgList &Args,
320 bool DiagnoseErrors) {
321 SanitizerMask AllRemove; // During the loop below, the accumulated set of
322 // sanitizers disabled by the current sanitizer
323 // argument or any argument after it.
324 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
325 // -fsanitize= flags (directly or via group
326 // expansion), some of which may be disabled
327 // later. Used to carefully prune
328 // unused-argument diagnostics.
329 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
330 // Used to deduplicate diagnostics.
331 SanitizerMask Kinds;
332 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
334 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
335 options::OPT_fno_sanitize_cfi_cross_dso, false);
337 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
339 const Driver &D = TC.getDriver();
340 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);
341 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
343 MinimalRuntime =
344 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
345 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
347 // The object size sanitizer should not be enabled at -O0.
348 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
349 bool RemoveObjectSizeAtO0 =
350 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
352 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
353 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
354 Arg->claim();
355 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
357 if (RemoveObjectSizeAtO0) {
358 AllRemove |= SanitizerKind::ObjectSize;
360 // The user explicitly enabled the object size sanitizer. Warn
361 // that this does nothing at -O0.
362 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
363 D.Diag(diag::warn_drv_object_size_disabled_O0)
364 << Arg->getAsString(Args);
367 AllAddedKinds |= expandSanitizerGroups(Add);
369 // Avoid diagnosing any sanitizer which is disabled later.
370 Add &= ~AllRemove;
371 // At this point we have not expanded groups, so any unsupported
372 // sanitizers in Add are those which have been explicitly enabled.
373 // Diagnose them.
374 if (SanitizerMask KindsToDiagnose =
375 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
376 if (DiagnoseErrors) {
377 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
378 D.Diag(diag::err_drv_argument_not_allowed_with)
379 << Desc << "-fsanitize-trap=undefined";
381 DiagnosedKinds |= KindsToDiagnose;
383 Add &= ~InvalidTrappingKinds;
385 if (MinimalRuntime) {
386 if (SanitizerMask KindsToDiagnose =
387 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
388 if (DiagnoseErrors) {
389 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
390 D.Diag(diag::err_drv_argument_not_allowed_with)
391 << Desc << "-fsanitize-minimal-runtime";
393 DiagnosedKinds |= KindsToDiagnose;
395 Add &= ~NotAllowedWithMinimalRuntime;
398 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
399 StringRef CM = A->getValue();
400 if (CM != "small" &&
401 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
402 if (DiagnoseErrors)
403 D.Diag(diag::err_drv_argument_only_allowed_with)
404 << "-fsanitize=function"
405 << "-mcmodel=small";
406 Add &= ~SanitizerKind::Function;
407 DiagnosedKinds |= SanitizerKind::Function;
410 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
411 // calls to load a type hash before the function label. Therefore, an
412 // execute-only target doesn't support the function and kcfi sanitizers.
413 const llvm::Triple &Triple = TC.getTriple();
414 if (isExecuteOnlyTarget(Triple, Args)) {
415 if (SanitizerMask KindsToDiagnose =
416 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {
417 if (DiagnoseErrors) {
418 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
419 D.Diag(diag::err_drv_argument_not_allowed_with)
420 << Desc << Triple.str();
422 DiagnosedKinds |= KindsToDiagnose;
424 Add &= ~NotAllowedWithExecuteOnly;
427 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
428 // There are currently two problems:
429 // - Virtual function call checks need to pass a pointer to the function
430 // address to llvm.type.test and a pointer to the address point to the
431 // diagnostic function. Currently we pass the same pointer to both
432 // places.
433 // - Non-virtual function call checks may need to check multiple type
434 // identifiers.
435 // Fixing both of those may require changes to the cross-DSO CFI
436 // interface.
437 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
438 if (DiagnoseErrors)
439 D.Diag(diag::err_drv_argument_not_allowed_with)
440 << "-fsanitize=cfi-mfcall"
441 << "-fsanitize-cfi-cross-dso";
442 Add &= ~SanitizerKind::CFIMFCall;
443 DiagnosedKinds |= SanitizerKind::CFIMFCall;
446 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
447 if (DiagnoseErrors) {
448 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
449 D.Diag(diag::err_drv_unsupported_opt_for_target)
450 << Desc << TC.getTriple().str();
452 DiagnosedKinds |= KindsToDiagnose;
454 Add &= Supported;
456 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
457 // so we don't error out if -fno-rtti and -fsanitize=undefined were
458 // passed.
459 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
460 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
461 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
462 "RTTI disabled without -fno-rtti option?");
463 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
464 // the vptr sanitizer requires RTTI, so this is a user error.
465 if (DiagnoseErrors)
466 D.Diag(diag::err_drv_argument_not_allowed_with)
467 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
468 } else {
469 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
470 // default). Warn that the vptr sanitizer is being disabled.
471 if (DiagnoseErrors)
472 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
475 // Take out the Vptr sanitizer from the enabled sanitizers
476 AllRemove |= SanitizerKind::Vptr;
479 Add = expandSanitizerGroups(Add);
480 // Group expansion may have enabled a sanitizer which is disabled later.
481 Add &= ~AllRemove;
482 // Silently discard any unsupported sanitizers implicitly enabled through
483 // group expansion.
484 Add &= ~InvalidTrappingKinds;
485 if (MinimalRuntime) {
486 Add &= ~NotAllowedWithMinimalRuntime;
488 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
489 // target if implicitly enabled through group expansion.
490 if (isExecuteOnlyTarget(Triple, Args))
491 Add &= ~NotAllowedWithExecuteOnly;
492 if (CfiCrossDso)
493 Add &= ~SanitizerKind::CFIMFCall;
494 Add &= Supported;
496 if (Add & SanitizerKind::Fuzzer)
497 Add |= SanitizerKind::FuzzerNoLink;
499 // Enable coverage if the fuzzing flag is set.
500 if (Add & SanitizerKind::FuzzerNoLink) {
501 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
502 CoverageTraceCmp | CoveragePCTable;
503 // Due to TLS differences, stack depth tracking is only enabled on Linux
504 if (TC.getTriple().isOSLinux())
505 CoverageFeatures |= CoverageStackDepth;
508 Kinds |= Add;
509 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
510 Arg->claim();
511 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
512 AllRemove |= expandSanitizerGroups(Remove);
516 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
517 std::make_pair(SanitizerKind::Address,
518 SanitizerKind::Thread | SanitizerKind::Memory),
519 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
520 std::make_pair(SanitizerKind::Leak,
521 SanitizerKind::Thread | SanitizerKind::Memory),
522 std::make_pair(SanitizerKind::KernelAddress,
523 SanitizerKind::Address | SanitizerKind::Leak |
524 SanitizerKind::Thread | SanitizerKind::Memory),
525 std::make_pair(SanitizerKind::HWAddress,
526 SanitizerKind::Address | SanitizerKind::Thread |
527 SanitizerKind::Memory | SanitizerKind::KernelAddress),
528 std::make_pair(SanitizerKind::Scudo,
529 SanitizerKind::Address | SanitizerKind::HWAddress |
530 SanitizerKind::Leak | SanitizerKind::Thread |
531 SanitizerKind::Memory | SanitizerKind::KernelAddress),
532 std::make_pair(SanitizerKind::SafeStack,
533 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
534 : SanitizerKind::Leak) |
535 SanitizerKind::Address | SanitizerKind::HWAddress |
536 SanitizerKind::Thread | SanitizerKind::Memory |
537 SanitizerKind::KernelAddress),
538 std::make_pair(SanitizerKind::KernelHWAddress,
539 SanitizerKind::Address | SanitizerKind::HWAddress |
540 SanitizerKind::Leak | SanitizerKind::Thread |
541 SanitizerKind::Memory | SanitizerKind::KernelAddress |
542 SanitizerKind::SafeStack),
543 std::make_pair(SanitizerKind::KernelMemory,
544 SanitizerKind::Address | SanitizerKind::HWAddress |
545 SanitizerKind::Leak | SanitizerKind::Thread |
546 SanitizerKind::Memory | SanitizerKind::KernelAddress |
547 SanitizerKind::Scudo | SanitizerKind::SafeStack),
548 std::make_pair(SanitizerKind::MemTag,
549 SanitizerKind::Address | SanitizerKind::KernelAddress |
550 SanitizerKind::HWAddress |
551 SanitizerKind::KernelHWAddress),
552 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
553 // Enable toolchain specific default sanitizers if not explicitly disabled.
554 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
556 // Disable default sanitizers that are incompatible with explicitly requested
557 // ones.
558 for (auto G : IncompatibleGroups) {
559 SanitizerMask Group = G.first;
560 if ((Default & Group) && (Kinds & G.second))
561 Default &= ~Group;
564 Kinds |= Default;
566 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
567 // is disabled.
568 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
569 Kinds &= ~SanitizerKind::Vptr;
572 // Check that LTO is enabled if we need it.
573 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
574 D.Diag(diag::err_drv_argument_only_allowed_with)
575 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
578 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
579 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
580 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
581 D.Diag(diag::err_drv_argument_only_allowed_with)
582 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
583 << "-ffixed-x18";
586 // Report error if there are non-trapping sanitizers that require
587 // c++abi-specific parts of UBSan runtime, and they are not provided by the
588 // toolchain. We don't have a good way to check the latter, so we just
589 // check if the toolchan supports vptr.
590 if (~Supported & SanitizerKind::Vptr) {
591 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
592 // The runtime library supports the Microsoft C++ ABI, but only well enough
593 // for CFI. FIXME: Remove this once we support vptr on Windows.
594 if (TC.getTriple().isOSWindows())
595 KindsToDiagnose &= ~SanitizerKind::CFI;
596 if (KindsToDiagnose) {
597 SanitizerSet S;
598 S.Mask = KindsToDiagnose;
599 if (DiagnoseErrors)
600 D.Diag(diag::err_drv_unsupported_opt_for_target)
601 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
602 Kinds &= ~KindsToDiagnose;
606 // Warn about incompatible groups of sanitizers.
607 for (auto G : IncompatibleGroups) {
608 SanitizerMask Group = G.first;
609 if (Kinds & Group) {
610 if (SanitizerMask Incompatible = Kinds & G.second) {
611 if (DiagnoseErrors)
612 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
613 << lastArgumentForMask(D, Args, Group)
614 << lastArgumentForMask(D, Args, Incompatible);
615 Kinds &= ~Incompatible;
619 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
620 // -fsanitize=address. Perhaps it should print an error, or perhaps
621 // -f(-no)sanitize=leak should change whether leak detection is enabled by
622 // default in ASan?
624 // Parse -f(no-)?sanitize-recover flags.
625 SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
626 SanitizerMask DiagnosedUnrecoverableKinds;
627 SanitizerMask DiagnosedAlwaysRecoverableKinds;
628 for (const auto *Arg : Args) {
629 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
630 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
631 // Report error if user explicitly tries to recover from unrecoverable
632 // sanitizer.
633 if (SanitizerMask KindsToDiagnose =
634 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
635 SanitizerSet SetToDiagnose;
636 SetToDiagnose.Mask |= KindsToDiagnose;
637 if (DiagnoseErrors)
638 D.Diag(diag::err_drv_unsupported_option_argument)
639 << Arg->getSpelling() << toString(SetToDiagnose);
640 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
642 RecoverableKinds |= expandSanitizerGroups(Add);
643 Arg->claim();
644 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
645 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
646 // Report error if user explicitly tries to disable recovery from
647 // always recoverable sanitizer.
648 if (SanitizerMask KindsToDiagnose =
649 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
650 SanitizerSet SetToDiagnose;
651 SetToDiagnose.Mask |= KindsToDiagnose;
652 if (DiagnoseErrors)
653 D.Diag(diag::err_drv_unsupported_option_argument)
654 << Arg->getSpelling() << toString(SetToDiagnose);
655 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
657 RecoverableKinds &= ~expandSanitizerGroups(Remove);
658 Arg->claim();
661 RecoverableKinds &= Kinds;
662 RecoverableKinds &= ~Unrecoverable;
664 TrappingKinds &= Kinds;
665 RecoverableKinds &= ~TrappingKinds;
667 // Setup ignorelist files.
668 // Add default ignorelist from resource directory for activated sanitizers,
669 // and validate special case lists format.
670 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
671 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
673 // Parse -f(no-)?sanitize-ignorelist options.
674 // This also validates special case lists format.
675 parseSpecialCaseListArg(
676 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
677 options::OPT_fno_sanitize_ignorelist,
678 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
680 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
681 if (AllAddedKinds & SanitizerKind::Memory) {
682 if (Arg *A =
683 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
684 options::OPT_fno_sanitize_memory_track_origins)) {
685 if (!A->getOption().matches(
686 options::OPT_fno_sanitize_memory_track_origins)) {
687 StringRef S = A->getValue();
688 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
689 MsanTrackOrigins > 2) {
690 if (DiagnoseErrors)
691 D.Diag(clang::diag::err_drv_invalid_value)
692 << A->getAsString(Args) << S;
696 MsanUseAfterDtor = Args.hasFlag(
697 options::OPT_fsanitize_memory_use_after_dtor,
698 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
699 MsanParamRetval = Args.hasFlag(
700 options::OPT_fsanitize_memory_param_retval,
701 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
702 NeedPIE |= !(TC.getTriple().isOSLinux() &&
703 TC.getTriple().getArch() == llvm::Triple::x86_64);
704 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
705 MsanUseAfterDtor = false;
706 MsanParamRetval = Args.hasFlag(
707 options::OPT_fsanitize_memory_param_retval,
708 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
709 } else {
710 MsanUseAfterDtor = false;
711 MsanParamRetval = false;
714 if (AllAddedKinds & SanitizerKind::MemTag) {
715 StringRef S =
716 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
717 if (S == "async" || S == "sync") {
718 MemtagMode = S.str();
719 } else {
720 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
721 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
722 MemtagMode = "sync";
726 if (AllAddedKinds & SanitizerKind::Thread) {
727 TsanMemoryAccess = Args.hasFlag(
728 options::OPT_fsanitize_thread_memory_access,
729 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
730 TsanFuncEntryExit = Args.hasFlag(
731 options::OPT_fsanitize_thread_func_entry_exit,
732 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
733 TsanAtomics =
734 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
735 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
738 if (AllAddedKinds & SanitizerKind::CFI) {
739 // Without PIE, external function address may resolve to a PLT record, which
740 // can not be verified by the target module.
741 NeedPIE |= CfiCrossDso;
742 CfiICallGeneralizePointers =
743 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
745 CfiICallNormalizeIntegers =
746 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
748 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
749 D.Diag(diag::err_drv_argument_not_allowed_with)
750 << "-fsanitize-cfi-cross-dso"
751 << "-fsanitize-cfi-icall-generalize-pointers";
753 CfiCanonicalJumpTables =
754 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
755 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
758 if (AllAddedKinds & SanitizerKind::KCFI) {
759 CfiICallNormalizeIntegers =
760 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
762 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
763 D.Diag(diag::err_drv_argument_not_allowed_with)
764 << "-fsanitize=kcfi"
765 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
768 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
769 options::OPT_fno_sanitize_stats, false);
771 if (MinimalRuntime) {
772 SanitizerMask IncompatibleMask =
773 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
774 if (IncompatibleMask && DiagnoseErrors)
775 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
776 << "-fsanitize-minimal-runtime"
777 << lastArgumentForMask(D, Args, IncompatibleMask);
779 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
780 if (NonTrappingCfi && DiagnoseErrors)
781 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
782 << "fsanitize-minimal-runtime"
783 << "fsanitize-trap=cfi";
786 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
787 // enabled sanitizers.
788 for (const auto *Arg : Args) {
789 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
790 int LegacySanitizeCoverage;
791 if (Arg->getNumValues() == 1 &&
792 !StringRef(Arg->getValue(0))
793 .getAsInteger(0, LegacySanitizeCoverage)) {
794 CoverageFeatures = 0;
795 Arg->claim();
796 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
797 D.Diag(diag::warn_drv_deprecated_arg)
798 << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
800 continue;
802 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
804 // Disable coverage and not claim the flags if there is at least one
805 // non-supporting sanitizer.
806 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
807 Arg->claim();
808 } else {
809 CoverageFeatures = 0;
811 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
812 Arg->claim();
813 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
816 // Choose at most one coverage type: function, bb, or edge.
817 if (DiagnoseErrors) {
818 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
819 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
820 << "-fsanitize-coverage=func"
821 << "-fsanitize-coverage=bb";
822 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
823 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
824 << "-fsanitize-coverage=func"
825 << "-fsanitize-coverage=edge";
826 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
827 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
828 << "-fsanitize-coverage=bb"
829 << "-fsanitize-coverage=edge";
830 // Basic block tracing and 8-bit counters require some type of coverage
831 // enabled.
832 if (CoverageFeatures & CoverageTraceBB)
833 D.Diag(clang::diag::warn_drv_deprecated_arg)
834 << "-fsanitize-coverage=trace-bb"
835 << "-fsanitize-coverage=trace-pc-guard";
836 if (CoverageFeatures & Coverage8bitCounters)
837 D.Diag(clang::diag::warn_drv_deprecated_arg)
838 << "-fsanitize-coverage=8bit-counters"
839 << "-fsanitize-coverage=trace-pc-guard";
842 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
843 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
844 CoverageInline8bitCounters | CoverageTraceLoads |
845 CoverageTraceStores | CoverageInlineBoolFlag |
846 CoverageControlFlow;
847 if ((CoverageFeatures & InsertionPointTypes) &&
848 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
849 D.Diag(clang::diag::warn_drv_deprecated_arg)
850 << "-fsanitize-coverage=[func|bb|edge]"
851 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
852 "control-flow]";
855 // trace-pc w/o func/bb/edge implies edge.
856 if (!(CoverageFeatures & InsertionPointTypes)) {
857 if (CoverageFeatures &
858 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
859 CoverageInlineBoolFlag | CoverageControlFlow))
860 CoverageFeatures |= CoverageEdge;
862 if (CoverageFeatures & CoverageStackDepth)
863 CoverageFeatures |= CoverageFunc;
866 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
867 // This also validates special case lists format.
868 // Here, OptSpecifier() acts as a never-matching command-line argument.
869 // So, there is no way to clear coverage lists but you can append to them.
870 if (CoverageFeatures) {
871 parseSpecialCaseListArg(
872 D, Args, CoverageAllowlistFiles,
873 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
874 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
875 DiagnoseErrors);
876 parseSpecialCaseListArg(
877 D, Args, CoverageIgnorelistFiles,
878 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
879 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
880 DiagnoseErrors);
883 // Parse -f(no-)?sanitize-metadata.
884 for (const auto *Arg :
885 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
886 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
887 if (Arg->getOption().matches(
888 options::OPT_fexperimental_sanitize_metadata_EQ)) {
889 Arg->claim();
890 BinaryMetadataFeatures |=
891 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
892 } else {
893 Arg->claim();
894 BinaryMetadataFeatures &=
895 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
899 // Parse -fsanitize-metadata-ignorelist option if enabled.
900 if (BinaryMetadataFeatures) {
901 parseSpecialCaseListArg(
902 D, Args, BinaryMetadataIgnorelistFiles,
903 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
904 OptSpecifier(), // Cannot clear ignore list, only append.
905 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
906 DiagnoseErrors);
909 SharedRuntime =
910 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
911 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
912 TC.getTriple().isOSDarwin());
914 ImplicitCfiRuntime = TC.getTriple().isAndroid();
916 if (AllAddedKinds & SanitizerKind::Address) {
917 NeedPIE |= TC.getTriple().isOSFuchsia();
918 if (Arg *A =
919 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
920 StringRef S = A->getValue();
921 // Legal values are 0 and 1, 2, but in future we may add more levels.
922 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
923 AsanFieldPadding > 2) &&
924 DiagnoseErrors) {
925 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
929 if (Arg *WindowsDebugRTArg =
930 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
931 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
932 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
933 switch (WindowsDebugRTArg->getOption().getID()) {
934 case options::OPT__SLASH_MTd:
935 case options::OPT__SLASH_MDd:
936 case options::OPT__SLASH_LDd:
937 if (DiagnoseErrors) {
938 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
939 << WindowsDebugRTArg->getAsString(Args)
940 << lastArgumentForMask(D, Args, SanitizerKind::Address);
941 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
946 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
947 options::OPT_fno_sanitize_stable_abi, false);
949 AsanUseAfterScope = Args.hasFlag(
950 options::OPT_fsanitize_address_use_after_scope,
951 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
953 AsanPoisonCustomArrayCookie = Args.hasFlag(
954 options::OPT_fsanitize_address_poison_custom_array_cookie,
955 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
956 AsanPoisonCustomArrayCookie);
958 AsanOutlineInstrumentation =
959 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
960 options::OPT_fno_sanitize_address_outline_instrumentation,
961 AsanOutlineInstrumentation);
963 AsanGlobalsDeadStripping = Args.hasFlag(
964 options::OPT_fsanitize_address_globals_dead_stripping,
965 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
967 // Enable ODR indicators which allow better handling of mixed instrumented
968 // and uninstrumented globals. Disable them for Windows where weak odr
969 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
970 // errors in the absence of -lldmingw.
971 AsanUseOdrIndicator =
972 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
973 options::OPT_fno_sanitize_address_use_odr_indicator,
974 !TC.getTriple().isOSWindows());
976 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
977 AsanInvalidPointerCmp = true;
980 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
981 AsanInvalidPointerSub = true;
984 if (TC.getTriple().isOSDarwin() &&
985 (Args.hasArg(options::OPT_mkernel) ||
986 Args.hasArg(options::OPT_fapple_kext))) {
987 AsanDtorKind = llvm::AsanDtorKind::None;
990 if (const auto *Arg =
991 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
992 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
993 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
994 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
995 << Arg->getSpelling() << Arg->getValue();
997 AsanDtorKind = parsedAsanDtorKind;
1000 if (const auto *Arg = Args.getLastArg(
1001 options::OPT_sanitize_address_use_after_return_EQ)) {
1002 auto parsedAsanUseAfterReturn =
1003 AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
1004 if (parsedAsanUseAfterReturn ==
1005 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1006 DiagnoseErrors) {
1007 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1008 << Arg->getSpelling() << Arg->getValue();
1010 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1013 } else {
1014 AsanUseAfterScope = false;
1015 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1016 SanitizerMask DetectInvalidPointerPairs =
1017 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1018 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1019 DiagnoseErrors) {
1020 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1021 << lastArgumentForMask(D, Args,
1022 SanitizerKind::PointerCompare |
1023 SanitizerKind::PointerSubtract)
1024 << "-fsanitize=address";
1028 if (AllAddedKinds & SanitizerKind::HWAddress) {
1029 if (Arg *HwasanAbiArg =
1030 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1031 HwasanAbi = HwasanAbiArg->getValue();
1032 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1033 DiagnoseErrors)
1034 D.Diag(clang::diag::err_drv_invalid_value)
1035 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1036 } else {
1037 HwasanAbi = "interceptor";
1039 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1040 HwasanUseAliases = Args.hasFlag(
1041 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1042 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1043 HwasanUseAliases);
1046 if (AllAddedKinds & SanitizerKind::SafeStack) {
1047 // SafeStack runtime is built into the system on Android and Fuchsia.
1048 SafeStackRuntime =
1049 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1052 LinkRuntimes =
1053 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1054 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1056 // Parse -link-cxx-sanitizer flag.
1057 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1058 options::OPT_fno_sanitize_link_cxx_runtime,
1059 LinkCXXRuntimes) ||
1060 D.CCCIsCXX();
1062 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1063 options::OPT_fmemory_profile_EQ,
1064 options::OPT_fno_memory_profile, false);
1066 // Finally, initialize the set of available and recoverable sanitizers.
1067 Sanitizers.Mask |= Kinds;
1068 RecoverableSanitizers.Mask |= RecoverableKinds;
1069 TrapSanitizers.Mask |= TrappingKinds;
1070 assert(!(RecoverableKinds & TrappingKinds) &&
1071 "Overlap between recoverable and trapping sanitizers");
1074 static std::string toString(const clang::SanitizerSet &Sanitizers) {
1075 std::string Res;
1076 #define SANITIZER(NAME, ID) \
1077 if (Sanitizers.has(SanitizerKind::ID)) { \
1078 if (!Res.empty()) \
1079 Res += ","; \
1080 Res += NAME; \
1082 #include "clang/Basic/Sanitizers.def"
1083 return Res;
1086 static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1087 llvm::opt::ArgStringList &CmdArgs,
1088 const char *SCLOptFlag,
1089 const std::vector<std::string> &SCLFiles) {
1090 for (const auto &SCLPath : SCLFiles) {
1091 SmallString<64> SCLOpt(SCLOptFlag);
1092 SCLOpt += SCLPath;
1093 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1097 static void addIncludeLinkerOption(const ToolChain &TC,
1098 const llvm::opt::ArgList &Args,
1099 llvm::opt::ArgStringList &CmdArgs,
1100 StringRef SymbolName) {
1101 SmallString<64> LinkerOptionFlag;
1102 LinkerOptionFlag = "--linker-option=/include:";
1103 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1104 // Win32 mangles C function names with a '_' prefix.
1105 LinkerOptionFlag += '_';
1107 LinkerOptionFlag += SymbolName;
1108 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1111 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1112 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1113 ++Start) {
1114 auto It = std::find(Start, End, StringRef("+mte"));
1115 if (It == End)
1116 break;
1117 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1118 return true;
1119 Start = It;
1121 return false;
1124 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1125 llvm::opt::ArgStringList &CmdArgs,
1126 types::ID InputType) const {
1127 // NVPTX doesn't currently support sanitizers. Bailing out here means
1128 // that e.g. -fsanitize=address applies only to host code, which is what we
1129 // want for now.
1130 if (TC.getTriple().isNVPTX())
1131 return;
1132 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1133 bool GPUSanitize = false;
1134 if (TC.getTriple().isAMDGPU()) {
1135 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1136 true))
1137 return;
1138 GPUSanitize = true;
1141 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1142 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1143 // sanitizers.
1144 std::pair<int, const char *> CoverageFlags[] = {
1145 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1146 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1147 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1148 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1149 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1150 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1151 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1152 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1153 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1154 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1155 std::make_pair(CoverageTracePCGuard,
1156 "-fsanitize-coverage-trace-pc-guard"),
1157 std::make_pair(CoverageInline8bitCounters,
1158 "-fsanitize-coverage-inline-8bit-counters"),
1159 std::make_pair(CoverageInlineBoolFlag,
1160 "-fsanitize-coverage-inline-bool-flag"),
1161 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1162 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1163 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1164 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1165 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1166 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1167 for (auto F : CoverageFlags) {
1168 if (CoverageFeatures & F.first)
1169 CmdArgs.push_back(F.second);
1171 addSpecialCaseListOpt(
1172 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1173 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1174 CoverageIgnorelistFiles);
1176 if (!GPUSanitize) {
1177 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1178 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1179 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1180 std::make_pair(BinaryMetadataCovered, "covered"),
1181 std::make_pair(BinaryMetadataAtomics, "atomics"),
1182 std::make_pair(BinaryMetadataUAR, "uar")};
1183 for (const auto &F : BinaryMetadataFlags) {
1184 if (BinaryMetadataFeatures & F.first)
1185 CmdArgs.push_back(
1186 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1188 addSpecialCaseListOpt(Args, CmdArgs,
1189 "-fexperimental-sanitize-metadata-ignorelist=",
1190 BinaryMetadataIgnorelistFiles);
1193 if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
1194 // Instruct the code generator to embed linker directives in the object file
1195 // that cause the required runtime libraries to be linked.
1196 CmdArgs.push_back(
1197 Args.MakeArgString("--dependent-lib=" +
1198 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1199 if (types::isCXX(InputType))
1200 CmdArgs.push_back(Args.MakeArgString(
1201 "--dependent-lib=" +
1202 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1204 if (TC.getTriple().isOSWindows() && needsStatsRt()) {
1205 CmdArgs.push_back(Args.MakeArgString(
1206 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1208 // The main executable must export the stats runtime.
1209 // FIXME: Only exporting from the main executable (e.g. based on whether the
1210 // translation unit defines main()) would save a little space, but having
1211 // multiple copies of the runtime shouldn't hurt.
1212 CmdArgs.push_back(Args.MakeArgString(
1213 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1214 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1217 if (Sanitizers.empty())
1218 return;
1219 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1221 if (!RecoverableSanitizers.empty())
1222 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1223 toString(RecoverableSanitizers)));
1225 if (!TrapSanitizers.empty())
1226 CmdArgs.push_back(
1227 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1229 addSpecialCaseListOpt(Args, CmdArgs,
1230 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1231 addSpecialCaseListOpt(Args, CmdArgs,
1232 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1234 if (MsanTrackOrigins)
1235 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1236 Twine(MsanTrackOrigins)));
1238 if (MsanUseAfterDtor)
1239 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1241 if (!MsanParamRetval)
1242 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1244 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1245 if (!TsanMemoryAccess) {
1246 CmdArgs.push_back("-mllvm");
1247 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1248 CmdArgs.push_back("-mllvm");
1249 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1251 if (!TsanFuncEntryExit) {
1252 CmdArgs.push_back("-mllvm");
1253 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1255 if (!TsanAtomics) {
1256 CmdArgs.push_back("-mllvm");
1257 CmdArgs.push_back("-tsan-instrument-atomics=0");
1260 if (HwasanUseAliases) {
1261 CmdArgs.push_back("-mllvm");
1262 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1265 if (CfiCrossDso)
1266 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1268 if (CfiICallGeneralizePointers)
1269 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1271 if (CfiICallNormalizeIntegers)
1272 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1274 if (CfiCanonicalJumpTables)
1275 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1277 if (Stats)
1278 CmdArgs.push_back("-fsanitize-stats");
1280 if (MinimalRuntime)
1281 CmdArgs.push_back("-fsanitize-minimal-runtime");
1283 if (AsanFieldPadding)
1284 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1285 Twine(AsanFieldPadding)));
1287 if (AsanUseAfterScope)
1288 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1290 if (AsanPoisonCustomArrayCookie)
1291 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1293 if (AsanGlobalsDeadStripping)
1294 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1296 if (!AsanUseOdrIndicator)
1297 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1299 if (AsanInvalidPointerCmp) {
1300 CmdArgs.push_back("-mllvm");
1301 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1304 if (AsanInvalidPointerSub) {
1305 CmdArgs.push_back("-mllvm");
1306 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1309 if (AsanOutlineInstrumentation) {
1310 CmdArgs.push_back("-mllvm");
1311 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1314 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1315 // inlining shadow memory poisoning. While this is a big performance burden
1316 // for now it allows full abstraction from implementation details.
1317 if (StableABI) {
1318 CmdArgs.push_back("-mllvm");
1319 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1320 CmdArgs.push_back("-mllvm");
1321 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1322 CmdArgs.push_back("-mllvm");
1323 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1326 // Only pass the option to the frontend if the user requested,
1327 // otherwise the frontend will just use the codegen default.
1328 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1329 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1330 AsanDtorKindToString(AsanDtorKind)));
1333 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1334 CmdArgs.push_back(Args.MakeArgString(
1335 "-fsanitize-address-use-after-return=" +
1336 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1339 if (!HwasanAbi.empty()) {
1340 CmdArgs.push_back("-default-function-attr");
1341 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1344 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1345 CmdArgs.push_back("-target-feature");
1346 CmdArgs.push_back("+tagged-globals");
1349 // MSan: Workaround for PR16386.
1350 // ASan: This is mainly to help LSan with cases such as
1351 // https://github.com/google/sanitizers/issues/373
1352 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1353 // affect compilation.
1354 if (Sanitizers.has(SanitizerKind::Memory) ||
1355 Sanitizers.has(SanitizerKind::Address))
1356 CmdArgs.push_back("-fno-assume-sane-operator-new");
1358 // libFuzzer wants to intercept calls to certain library functions, so the
1359 // following -fno-builtin-* flags force the compiler to emit interposable
1360 // libcalls to these functions. Other sanitizers effectively do the same thing
1361 // by marking all library call sites with NoBuiltin attribute in their LLVM
1362 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1363 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1364 CmdArgs.push_back("-fno-builtin-bcmp");
1365 CmdArgs.push_back("-fno-builtin-memcmp");
1366 CmdArgs.push_back("-fno-builtin-strncmp");
1367 CmdArgs.push_back("-fno-builtin-strcmp");
1368 CmdArgs.push_back("-fno-builtin-strncasecmp");
1369 CmdArgs.push_back("-fno-builtin-strcasecmp");
1370 CmdArgs.push_back("-fno-builtin-strstr");
1371 CmdArgs.push_back("-fno-builtin-strcasestr");
1372 CmdArgs.push_back("-fno-builtin-memmem");
1375 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1376 // enabled.
1377 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1378 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1379 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1380 << lastArgumentForMask(TC.getDriver(), Args,
1381 Sanitizers.Mask & CFIClasses)
1382 << "-fvisibility=";
1385 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1386 !hasTargetFeatureMTE(CmdArgs))
1387 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1390 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1391 bool DiagnoseErrors) {
1392 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1393 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1394 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1395 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1396 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1397 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1398 "Invalid argument in parseArgValues!");
1399 SanitizerMask Kinds;
1400 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1401 const char *Value = A->getValue(i);
1402 SanitizerMask Kind;
1403 // Special case: don't accept -fsanitize=all.
1404 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1405 0 == strcmp("all", Value))
1406 Kind = SanitizerMask();
1407 else
1408 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1410 if (Kind)
1411 Kinds |= Kind;
1412 else if (DiagnoseErrors)
1413 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1414 << A->getSpelling() << Value;
1416 return Kinds;
1419 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1420 bool DiagnoseErrors) {
1421 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1422 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1423 int Features = 0;
1424 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1425 const char *Value = A->getValue(i);
1426 int F = llvm::StringSwitch<int>(Value)
1427 .Case("func", CoverageFunc)
1428 .Case("bb", CoverageBB)
1429 .Case("edge", CoverageEdge)
1430 .Case("indirect-calls", CoverageIndirCall)
1431 .Case("trace-bb", CoverageTraceBB)
1432 .Case("trace-cmp", CoverageTraceCmp)
1433 .Case("trace-div", CoverageTraceDiv)
1434 .Case("trace-gep", CoverageTraceGep)
1435 .Case("8bit-counters", Coverage8bitCounters)
1436 .Case("trace-pc", CoverageTracePC)
1437 .Case("trace-pc-guard", CoverageTracePCGuard)
1438 .Case("no-prune", CoverageNoPrune)
1439 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1440 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1441 .Case("pc-table", CoveragePCTable)
1442 .Case("stack-depth", CoverageStackDepth)
1443 .Case("trace-loads", CoverageTraceLoads)
1444 .Case("trace-stores", CoverageTraceStores)
1445 .Case("control-flow", CoverageControlFlow)
1446 .Default(0);
1447 if (F == 0 && DiagnoseErrors)
1448 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1449 << A->getSpelling() << Value;
1450 Features |= F;
1452 return Features;
1455 int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1456 bool DiagnoseErrors) {
1457 assert(
1458 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1459 A->getOption().matches(
1460 options::OPT_fno_experimental_sanitize_metadata_EQ));
1461 int Features = 0;
1462 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1463 const char *Value = A->getValue(i);
1464 int F = llvm::StringSwitch<int>(Value)
1465 .Case("covered", BinaryMetadataCovered)
1466 .Case("atomics", BinaryMetadataAtomics)
1467 .Case("uar", BinaryMetadataUAR)
1468 .Case("all", ~0)
1469 .Default(0);
1470 if (F == 0 && DiagnoseErrors)
1471 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1472 << A->getSpelling() << Value;
1473 Features |= F;
1475 return Features;
1478 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1479 SanitizerMask Mask) {
1480 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1481 E = Args.rend();
1482 I != E; ++I) {
1483 const auto *Arg = *I;
1484 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1485 SanitizerMask AddKinds =
1486 expandSanitizerGroups(parseArgValues(D, Arg, false));
1487 if (AddKinds & Mask)
1488 return describeSanitizeArg(Arg, Mask);
1489 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1490 SanitizerMask RemoveKinds =
1491 expandSanitizerGroups(parseArgValues(D, Arg, false));
1492 Mask &= ~RemoveKinds;
1495 llvm_unreachable("arg list didn't provide expected value");
1498 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1499 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1500 "Invalid argument in describeSanitizerArg!");
1502 std::string Sanitizers;
1503 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1504 if (expandSanitizerGroups(
1505 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1506 Mask) {
1507 if (!Sanitizers.empty())
1508 Sanitizers += ",";
1509 Sanitizers += A->getValue(i);
1513 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1514 return "-fsanitize=" + Sanitizers;