[cmake] Add minor version to library SONAME (#79376)
[llvm-project.git] / clang / lib / Driver / SanitizerArgs.cpp
blob56d497eb4c32b86e7f57b1fa2a9758d1d77121a9
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 NeedsUnwindTables =
43 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
44 SanitizerKind::Memory | SanitizerKind::DataFlow;
45 static const SanitizerMask SupportsCoverage =
46 SanitizerKind::Address | SanitizerKind::HWAddress |
47 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
48 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
49 SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
50 SanitizerKind::KernelMemory | SanitizerKind::Leak |
51 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
52 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
53 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
54 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
55 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
56 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
57 static const SanitizerMask RecoverableByDefault =
58 SanitizerKind::Undefined | SanitizerKind::Integer |
59 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
60 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
61 static const SanitizerMask Unrecoverable =
62 SanitizerKind::Unreachable | SanitizerKind::Return;
63 static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |
64 SanitizerKind::KernelHWAddress |
65 SanitizerKind::KCFI;
66 static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
67 static const SanitizerMask TrappingSupported =
68 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |
69 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
70 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
71 SanitizerKind::ObjCCast;
72 static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
73 static const SanitizerMask CFIClasses =
74 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
75 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
76 SanitizerKind::CFIUnrelatedCast;
77 static const SanitizerMask CompatibleWithMinimalRuntime =
78 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
79 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
80 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
82 enum CoverageFeature {
83 CoverageFunc = 1 << 0,
84 CoverageBB = 1 << 1,
85 CoverageEdge = 1 << 2,
86 CoverageIndirCall = 1 << 3,
87 CoverageTraceBB = 1 << 4, // Deprecated.
88 CoverageTraceCmp = 1 << 5,
89 CoverageTraceDiv = 1 << 6,
90 CoverageTraceGep = 1 << 7,
91 Coverage8bitCounters = 1 << 8, // Deprecated.
92 CoverageTracePC = 1 << 9,
93 CoverageTracePCGuard = 1 << 10,
94 CoverageNoPrune = 1 << 11,
95 CoverageInline8bitCounters = 1 << 12,
96 CoveragePCTable = 1 << 13,
97 CoverageStackDepth = 1 << 14,
98 CoverageInlineBoolFlag = 1 << 15,
99 CoverageTraceLoads = 1 << 16,
100 CoverageTraceStores = 1 << 17,
101 CoverageControlFlow = 1 << 18,
104 enum BinaryMetadataFeature {
105 BinaryMetadataCovered = 1 << 0,
106 BinaryMetadataAtomics = 1 << 1,
107 BinaryMetadataUAR = 1 << 2,
110 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
111 /// invalid components. Returns a SanitizerMask.
112 static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
113 bool DiagnoseErrors);
115 /// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
116 /// components. Returns OR of members of \c CoverageFeature enumeration.
117 static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
118 bool DiagnoseErrors);
120 /// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
121 /// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
122 static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
123 bool DiagnoseErrors);
125 /// Produce an argument string from ArgList \p Args, which shows how it
126 /// provides some sanitizer kind from \p Mask. For example, the argument list
127 /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
128 /// would produce "-fsanitize=vptr".
129 static std::string lastArgumentForMask(const Driver &D,
130 const llvm::opt::ArgList &Args,
131 SanitizerMask Mask);
133 /// Produce an argument string from argument \p A, which shows how it provides
134 /// a value in \p Mask. For instance, the argument
135 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
136 /// "-fsanitize=alignment".
137 static std::string describeSanitizeArg(const llvm::opt::Arg *A,
138 SanitizerMask Mask);
140 /// Produce a string containing comma-separated names of sanitizers in \p
141 /// Sanitizers set.
142 static std::string toString(const clang::SanitizerSet &Sanitizers);
144 /// Return true if an execute-only target disallows data access to code
145 /// sections.
146 static bool isExecuteOnlyTarget(const llvm::Triple &Triple,
147 const llvm::opt::ArgList &Args) {
148 if (Triple.isPS5())
149 return true;
150 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
151 options::OPT_mno_execute_only, false);
154 static void validateSpecialCaseListFormat(const Driver &D,
155 std::vector<std::string> &SCLFiles,
156 unsigned MalformedSCLErrorDiagID,
157 bool DiagnoseErrors) {
158 if (SCLFiles.empty())
159 return;
161 std::string BLError;
162 std::unique_ptr<llvm::SpecialCaseList> SCL(
163 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
164 if (!SCL.get() && DiagnoseErrors)
165 D.Diag(MalformedSCLErrorDiagID) << BLError;
168 static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
169 std::vector<std::string> &IgnorelistFiles,
170 bool DiagnoseErrors) {
171 struct Ignorelist {
172 const char *File;
173 SanitizerMask Mask;
174 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
175 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
176 {"memtag_ignorelist.txt", SanitizerKind::MemTag},
177 {"msan_ignorelist.txt", SanitizerKind::Memory},
178 {"tsan_ignorelist.txt", SanitizerKind::Thread},
179 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
180 {"cfi_ignorelist.txt", SanitizerKind::CFI},
181 {"ubsan_ignorelist.txt",
182 SanitizerKind::Undefined | SanitizerKind::Integer |
183 SanitizerKind::Nullability |
184 SanitizerKind::FloatDivideByZero}};
186 for (auto BL : Ignorelists) {
187 if (!(Kinds & BL.Mask))
188 continue;
190 clang::SmallString<64> Path(D.ResourceDir);
191 llvm::sys::path::append(Path, "share", BL.File);
192 if (D.getVFS().exists(Path))
193 IgnorelistFiles.push_back(std::string(Path));
194 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
195 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
196 // should fail.
197 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
199 validateSpecialCaseListFormat(
200 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
201 DiagnoseErrors);
204 /// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
205 /// diagnosing any invalid file paths and validating special case list format.
206 static void parseSpecialCaseListArg(const Driver &D,
207 const llvm::opt::ArgList &Args,
208 std::vector<std::string> &SCLFiles,
209 llvm::opt::OptSpecifier SCLOptionID,
210 llvm::opt::OptSpecifier NoSCLOptionID,
211 unsigned MalformedSCLErrorDiagID,
212 bool DiagnoseErrors) {
213 for (const auto *Arg : Args) {
214 // Match -fsanitize-(coverage-)?(allow|ignore)list.
215 if (Arg->getOption().matches(SCLOptionID)) {
216 Arg->claim();
217 std::string SCLPath = Arg->getValue();
218 if (D.getVFS().exists(SCLPath)) {
219 SCLFiles.push_back(SCLPath);
220 } else if (DiagnoseErrors) {
221 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
223 // Match -fno-sanitize-ignorelist.
224 } else if (Arg->getOption().matches(NoSCLOptionID)) {
225 Arg->claim();
226 SCLFiles.clear();
229 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,
230 DiagnoseErrors);
233 /// Sets group bits for every group that has at least one representative already
234 /// enabled in \p Kinds.
235 static SanitizerMask setGroupBits(SanitizerMask Kinds) {
236 #define SANITIZER(NAME, ID)
237 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
238 if (Kinds & SanitizerKind::ID) \
239 Kinds |= SanitizerKind::ID##Group;
240 #include "clang/Basic/Sanitizers.def"
241 return Kinds;
244 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
245 const llvm::opt::ArgList &Args,
246 bool DiagnoseErrors) {
247 SanitizerMask TrapRemove; // During the loop below, the accumulated set of
248 // sanitizers disabled by the current sanitizer
249 // argument or any argument after it.
250 SanitizerMask TrappingKinds;
251 SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
253 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
254 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
255 Arg->claim();
256 SanitizerMask Add = parseArgValues(D, Arg, true);
257 Add &= ~TrapRemove;
258 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
259 if (InvalidValues && DiagnoseErrors) {
260 SanitizerSet S;
261 S.Mask = InvalidValues;
262 D.Diag(diag::err_drv_unsupported_option_argument)
263 << Arg->getSpelling() << toString(S);
265 TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
266 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
267 Arg->claim();
268 TrapRemove |=
269 expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
273 // Apply default trapping behavior.
274 TrappingKinds |= TrappingDefault & ~TrapRemove;
276 return TrappingKinds;
279 bool SanitizerArgs::needsFuzzerInterceptors() const {
280 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
283 bool SanitizerArgs::needsUbsanRt() const {
284 // All of these include ubsan.
285 if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
286 needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
287 (needsScudoRt() && !requiresMinimalRuntime()))
288 return false;
290 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
291 CoverageFeatures;
294 bool SanitizerArgs::needsCfiRt() const {
295 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
296 CfiCrossDso && !ImplicitCfiRuntime;
299 bool SanitizerArgs::needsCfiDiagRt() const {
300 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
301 CfiCrossDso && !ImplicitCfiRuntime;
304 bool SanitizerArgs::requiresPIE() const { return NeedPIE; }
306 bool SanitizerArgs::needsUnwindTables() const {
307 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
310 bool SanitizerArgs::needsLTO() const {
311 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
314 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
315 const llvm::opt::ArgList &Args,
316 bool DiagnoseErrors) {
317 SanitizerMask AllRemove; // During the loop below, the accumulated set of
318 // sanitizers disabled by the current sanitizer
319 // argument or any argument after it.
320 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
321 // -fsanitize= flags (directly or via group
322 // expansion), some of which may be disabled
323 // later. Used to carefully prune
324 // unused-argument diagnostics.
325 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
326 // Used to deduplicate diagnostics.
327 SanitizerMask Kinds;
328 const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
330 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
331 options::OPT_fno_sanitize_cfi_cross_dso, false);
333 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
335 const Driver &D = TC.getDriver();
336 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);
337 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
339 MinimalRuntime =
340 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
341 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
343 // The object size sanitizer should not be enabled at -O0.
344 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
345 bool RemoveObjectSizeAtO0 =
346 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
348 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
349 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
350 Arg->claim();
351 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
353 if (RemoveObjectSizeAtO0) {
354 AllRemove |= SanitizerKind::ObjectSize;
356 // The user explicitly enabled the object size sanitizer. Warn
357 // that this does nothing at -O0.
358 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
359 D.Diag(diag::warn_drv_object_size_disabled_O0)
360 << Arg->getAsString(Args);
363 AllAddedKinds |= expandSanitizerGroups(Add);
365 // Avoid diagnosing any sanitizer which is disabled later.
366 Add &= ~AllRemove;
367 // At this point we have not expanded groups, so any unsupported
368 // sanitizers in Add are those which have been explicitly enabled.
369 // Diagnose them.
370 if (SanitizerMask KindsToDiagnose =
371 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
372 if (DiagnoseErrors) {
373 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
374 D.Diag(diag::err_drv_argument_not_allowed_with)
375 << Desc << "-fsanitize-trap=undefined";
377 DiagnosedKinds |= KindsToDiagnose;
379 Add &= ~InvalidTrappingKinds;
381 if (MinimalRuntime) {
382 if (SanitizerMask KindsToDiagnose =
383 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
384 if (DiagnoseErrors) {
385 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
386 D.Diag(diag::err_drv_argument_not_allowed_with)
387 << Desc << "-fsanitize-minimal-runtime";
389 DiagnosedKinds |= KindsToDiagnose;
391 Add &= ~NotAllowedWithMinimalRuntime;
394 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
395 StringRef CM = A->getValue();
396 if (CM != "small" &&
397 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
398 if (DiagnoseErrors)
399 D.Diag(diag::err_drv_argument_only_allowed_with)
400 << "-fsanitize=function"
401 << "-mcmodel=small";
402 Add &= ~SanitizerKind::Function;
403 DiagnosedKinds |= SanitizerKind::Function;
406 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
407 // calls to load a type hash before the function label. Therefore, an
408 // execute-only target doesn't support the function and kcfi sanitizers.
409 const llvm::Triple &Triple = TC.getTriple();
410 if (isExecuteOnlyTarget(Triple, Args)) {
411 if (SanitizerMask KindsToDiagnose =
412 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {
413 if (DiagnoseErrors) {
414 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
415 D.Diag(diag::err_drv_argument_not_allowed_with)
416 << Desc << Triple.str();
418 DiagnosedKinds |= KindsToDiagnose;
420 Add &= ~NotAllowedWithExecuteOnly;
423 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
424 // There are currently two problems:
425 // - Virtual function call checks need to pass a pointer to the function
426 // address to llvm.type.test and a pointer to the address point to the
427 // diagnostic function. Currently we pass the same pointer to both
428 // places.
429 // - Non-virtual function call checks may need to check multiple type
430 // identifiers.
431 // Fixing both of those may require changes to the cross-DSO CFI
432 // interface.
433 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
434 if (DiagnoseErrors)
435 D.Diag(diag::err_drv_argument_not_allowed_with)
436 << "-fsanitize=cfi-mfcall"
437 << "-fsanitize-cfi-cross-dso";
438 Add &= ~SanitizerKind::CFIMFCall;
439 DiagnosedKinds |= SanitizerKind::CFIMFCall;
442 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
443 if (DiagnoseErrors) {
444 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
445 D.Diag(diag::err_drv_unsupported_opt_for_target)
446 << Desc << TC.getTriple().str();
448 DiagnosedKinds |= KindsToDiagnose;
450 Add &= Supported;
452 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
453 // so we don't error out if -fno-rtti and -fsanitize=undefined were
454 // passed.
455 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
456 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
457 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
458 "RTTI disabled without -fno-rtti option?");
459 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
460 // the vptr sanitizer requires RTTI, so this is a user error.
461 if (DiagnoseErrors)
462 D.Diag(diag::err_drv_argument_not_allowed_with)
463 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
464 } else {
465 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
466 // default). Warn that the vptr sanitizer is being disabled.
467 if (DiagnoseErrors)
468 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
471 // Take out the Vptr sanitizer from the enabled sanitizers
472 AllRemove |= SanitizerKind::Vptr;
475 Add = expandSanitizerGroups(Add);
476 // Group expansion may have enabled a sanitizer which is disabled later.
477 Add &= ~AllRemove;
478 // Silently discard any unsupported sanitizers implicitly enabled through
479 // group expansion.
480 Add &= ~InvalidTrappingKinds;
481 if (MinimalRuntime) {
482 Add &= ~NotAllowedWithMinimalRuntime;
484 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
485 // target if implicitly enabled through group expansion.
486 if (isExecuteOnlyTarget(Triple, Args))
487 Add &= ~NotAllowedWithExecuteOnly;
488 if (CfiCrossDso)
489 Add &= ~SanitizerKind::CFIMFCall;
490 Add &= Supported;
492 if (Add & SanitizerKind::Fuzzer)
493 Add |= SanitizerKind::FuzzerNoLink;
495 // Enable coverage if the fuzzing flag is set.
496 if (Add & SanitizerKind::FuzzerNoLink) {
497 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
498 CoverageTraceCmp | CoveragePCTable;
499 // Due to TLS differences, stack depth tracking is only enabled on Linux
500 if (TC.getTriple().isOSLinux())
501 CoverageFeatures |= CoverageStackDepth;
504 Kinds |= Add;
505 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
506 Arg->claim();
507 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
508 AllRemove |= expandSanitizerGroups(Remove);
512 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
513 std::make_pair(SanitizerKind::Address,
514 SanitizerKind::Thread | SanitizerKind::Memory),
515 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
516 std::make_pair(SanitizerKind::Leak,
517 SanitizerKind::Thread | SanitizerKind::Memory),
518 std::make_pair(SanitizerKind::KernelAddress,
519 SanitizerKind::Address | SanitizerKind::Leak |
520 SanitizerKind::Thread | SanitizerKind::Memory),
521 std::make_pair(SanitizerKind::HWAddress,
522 SanitizerKind::Address | SanitizerKind::Thread |
523 SanitizerKind::Memory | SanitizerKind::KernelAddress),
524 std::make_pair(SanitizerKind::Scudo,
525 SanitizerKind::Address | SanitizerKind::HWAddress |
526 SanitizerKind::Leak | SanitizerKind::Thread |
527 SanitizerKind::Memory | SanitizerKind::KernelAddress),
528 std::make_pair(SanitizerKind::SafeStack,
529 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
530 : SanitizerKind::Leak) |
531 SanitizerKind::Address | SanitizerKind::HWAddress |
532 SanitizerKind::Thread | SanitizerKind::Memory |
533 SanitizerKind::KernelAddress),
534 std::make_pair(SanitizerKind::KernelHWAddress,
535 SanitizerKind::Address | SanitizerKind::HWAddress |
536 SanitizerKind::Leak | SanitizerKind::Thread |
537 SanitizerKind::Memory | SanitizerKind::KernelAddress |
538 SanitizerKind::SafeStack),
539 std::make_pair(SanitizerKind::KernelMemory,
540 SanitizerKind::Address | SanitizerKind::HWAddress |
541 SanitizerKind::Leak | SanitizerKind::Thread |
542 SanitizerKind::Memory | SanitizerKind::KernelAddress |
543 SanitizerKind::Scudo | SanitizerKind::SafeStack),
544 std::make_pair(SanitizerKind::MemTag,
545 SanitizerKind::Address | SanitizerKind::KernelAddress |
546 SanitizerKind::HWAddress |
547 SanitizerKind::KernelHWAddress),
548 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
549 // Enable toolchain specific default sanitizers if not explicitly disabled.
550 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
552 // Disable default sanitizers that are incompatible with explicitly requested
553 // ones.
554 for (auto G : IncompatibleGroups) {
555 SanitizerMask Group = G.first;
556 if ((Default & Group) && (Kinds & G.second))
557 Default &= ~Group;
560 Kinds |= Default;
562 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
563 // is disabled.
564 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
565 Kinds &= ~SanitizerKind::Vptr;
568 // Check that LTO is enabled if we need it.
569 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
570 D.Diag(diag::err_drv_argument_only_allowed_with)
571 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
574 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
575 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
576 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
577 D.Diag(diag::err_drv_argument_only_allowed_with)
578 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
579 << "-ffixed-x18";
582 // Report error if there are non-trapping sanitizers that require
583 // c++abi-specific parts of UBSan runtime, and they are not provided by the
584 // toolchain. We don't have a good way to check the latter, so we just
585 // check if the toolchan supports vptr.
586 if (~Supported & SanitizerKind::Vptr) {
587 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
588 // The runtime library supports the Microsoft C++ ABI, but only well enough
589 // for CFI. FIXME: Remove this once we support vptr on Windows.
590 if (TC.getTriple().isOSWindows())
591 KindsToDiagnose &= ~SanitizerKind::CFI;
592 if (KindsToDiagnose) {
593 SanitizerSet S;
594 S.Mask = KindsToDiagnose;
595 if (DiagnoseErrors)
596 D.Diag(diag::err_drv_unsupported_opt_for_target)
597 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
598 Kinds &= ~KindsToDiagnose;
602 // Warn about incompatible groups of sanitizers.
603 for (auto G : IncompatibleGroups) {
604 SanitizerMask Group = G.first;
605 if (Kinds & Group) {
606 if (SanitizerMask Incompatible = Kinds & G.second) {
607 if (DiagnoseErrors)
608 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
609 << lastArgumentForMask(D, Args, Group)
610 << lastArgumentForMask(D, Args, Incompatible);
611 Kinds &= ~Incompatible;
615 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
616 // -fsanitize=address. Perhaps it should print an error, or perhaps
617 // -f(-no)sanitize=leak should change whether leak detection is enabled by
618 // default in ASan?
620 // Parse -f(no-)?sanitize-recover flags.
621 SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
622 SanitizerMask DiagnosedUnrecoverableKinds;
623 SanitizerMask DiagnosedAlwaysRecoverableKinds;
624 for (const auto *Arg : Args) {
625 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
626 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
627 // Report error if user explicitly tries to recover from unrecoverable
628 // sanitizer.
629 if (SanitizerMask KindsToDiagnose =
630 Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
631 SanitizerSet SetToDiagnose;
632 SetToDiagnose.Mask |= KindsToDiagnose;
633 if (DiagnoseErrors)
634 D.Diag(diag::err_drv_unsupported_option_argument)
635 << Arg->getSpelling() << toString(SetToDiagnose);
636 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
638 RecoverableKinds |= expandSanitizerGroups(Add);
639 Arg->claim();
640 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
641 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
642 // Report error if user explicitly tries to disable recovery from
643 // always recoverable sanitizer.
644 if (SanitizerMask KindsToDiagnose =
645 Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
646 SanitizerSet SetToDiagnose;
647 SetToDiagnose.Mask |= KindsToDiagnose;
648 if (DiagnoseErrors)
649 D.Diag(diag::err_drv_unsupported_option_argument)
650 << Arg->getSpelling() << toString(SetToDiagnose);
651 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
653 RecoverableKinds &= ~expandSanitizerGroups(Remove);
654 Arg->claim();
657 RecoverableKinds &= Kinds;
658 RecoverableKinds &= ~Unrecoverable;
660 TrappingKinds &= Kinds;
661 RecoverableKinds &= ~TrappingKinds;
663 // Setup ignorelist files.
664 // Add default ignorelist from resource directory for activated sanitizers,
665 // and validate special case lists format.
666 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
667 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
669 // Parse -f(no-)?sanitize-ignorelist options.
670 // This also validates special case lists format.
671 parseSpecialCaseListArg(
672 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
673 options::OPT_fno_sanitize_ignorelist,
674 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
676 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
677 if (AllAddedKinds & SanitizerKind::Memory) {
678 if (Arg *A =
679 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
680 options::OPT_fno_sanitize_memory_track_origins)) {
681 if (!A->getOption().matches(
682 options::OPT_fno_sanitize_memory_track_origins)) {
683 StringRef S = A->getValue();
684 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
685 MsanTrackOrigins > 2) {
686 if (DiagnoseErrors)
687 D.Diag(clang::diag::err_drv_invalid_value)
688 << A->getAsString(Args) << S;
692 MsanUseAfterDtor = Args.hasFlag(
693 options::OPT_fsanitize_memory_use_after_dtor,
694 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
695 MsanParamRetval = Args.hasFlag(
696 options::OPT_fsanitize_memory_param_retval,
697 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
698 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
699 MsanUseAfterDtor = false;
700 MsanParamRetval = Args.hasFlag(
701 options::OPT_fsanitize_memory_param_retval,
702 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
703 } else {
704 MsanUseAfterDtor = false;
705 MsanParamRetval = false;
708 if (AllAddedKinds & SanitizerKind::MemTag) {
709 StringRef S =
710 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
711 if (S == "async" || S == "sync") {
712 MemtagMode = S.str();
713 } else {
714 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
715 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
716 MemtagMode = "sync";
720 if (AllAddedKinds & SanitizerKind::Thread) {
721 TsanMemoryAccess = Args.hasFlag(
722 options::OPT_fsanitize_thread_memory_access,
723 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
724 TsanFuncEntryExit = Args.hasFlag(
725 options::OPT_fsanitize_thread_func_entry_exit,
726 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
727 TsanAtomics =
728 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
729 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
732 if (AllAddedKinds & SanitizerKind::CFI) {
733 // Without PIE, external function address may resolve to a PLT record, which
734 // can not be verified by the target module.
735 NeedPIE |= CfiCrossDso;
736 CfiICallGeneralizePointers =
737 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
739 CfiICallNormalizeIntegers =
740 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
742 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
743 D.Diag(diag::err_drv_argument_not_allowed_with)
744 << "-fsanitize-cfi-cross-dso"
745 << "-fsanitize-cfi-icall-generalize-pointers";
747 CfiCanonicalJumpTables =
748 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
749 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
752 if (AllAddedKinds & SanitizerKind::KCFI) {
753 CfiICallNormalizeIntegers =
754 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
756 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
757 D.Diag(diag::err_drv_argument_not_allowed_with)
758 << "-fsanitize=kcfi"
759 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
762 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
763 options::OPT_fno_sanitize_stats, false);
765 if (MinimalRuntime) {
766 SanitizerMask IncompatibleMask =
767 Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);
768 if (IncompatibleMask && DiagnoseErrors)
769 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
770 << "-fsanitize-minimal-runtime"
771 << lastArgumentForMask(D, Args, IncompatibleMask);
773 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
774 if (NonTrappingCfi && DiagnoseErrors)
775 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
776 << "fsanitize-minimal-runtime"
777 << "fsanitize-trap=cfi";
780 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
781 // enabled sanitizers.
782 for (const auto *Arg : Args) {
783 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
784 int LegacySanitizeCoverage;
785 if (Arg->getNumValues() == 1 &&
786 !StringRef(Arg->getValue(0))
787 .getAsInteger(0, LegacySanitizeCoverage)) {
788 CoverageFeatures = 0;
789 Arg->claim();
790 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
791 D.Diag(diag::warn_drv_deprecated_arg)
792 << Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
794 continue;
796 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
798 // Disable coverage and not claim the flags if there is at least one
799 // non-supporting sanitizer.
800 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
801 Arg->claim();
802 } else {
803 CoverageFeatures = 0;
805 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
806 Arg->claim();
807 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
810 // Choose at most one coverage type: function, bb, or edge.
811 if (DiagnoseErrors) {
812 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
813 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
814 << "-fsanitize-coverage=func"
815 << "-fsanitize-coverage=bb";
816 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
817 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
818 << "-fsanitize-coverage=func"
819 << "-fsanitize-coverage=edge";
820 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
821 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
822 << "-fsanitize-coverage=bb"
823 << "-fsanitize-coverage=edge";
824 // Basic block tracing and 8-bit counters require some type of coverage
825 // enabled.
826 if (CoverageFeatures & CoverageTraceBB)
827 D.Diag(clang::diag::warn_drv_deprecated_arg)
828 << "-fsanitize-coverage=trace-bb"
829 << "-fsanitize-coverage=trace-pc-guard";
830 if (CoverageFeatures & Coverage8bitCounters)
831 D.Diag(clang::diag::warn_drv_deprecated_arg)
832 << "-fsanitize-coverage=8bit-counters"
833 << "-fsanitize-coverage=trace-pc-guard";
836 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
837 int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
838 CoverageInline8bitCounters | CoverageTraceLoads |
839 CoverageTraceStores | CoverageInlineBoolFlag |
840 CoverageControlFlow;
841 if ((CoverageFeatures & InsertionPointTypes) &&
842 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
843 D.Diag(clang::diag::warn_drv_deprecated_arg)
844 << "-fsanitize-coverage=[func|bb|edge]"
845 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
846 "control-flow]";
849 // trace-pc w/o func/bb/edge implies edge.
850 if (!(CoverageFeatures & InsertionPointTypes)) {
851 if (CoverageFeatures &
852 (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
853 CoverageInlineBoolFlag | CoverageControlFlow))
854 CoverageFeatures |= CoverageEdge;
856 if (CoverageFeatures & CoverageStackDepth)
857 CoverageFeatures |= CoverageFunc;
860 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
861 // This also validates special case lists format.
862 // Here, OptSpecifier() acts as a never-matching command-line argument.
863 // So, there is no way to clear coverage lists but you can append to them.
864 if (CoverageFeatures) {
865 parseSpecialCaseListArg(
866 D, Args, CoverageAllowlistFiles,
867 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
868 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
869 DiagnoseErrors);
870 parseSpecialCaseListArg(
871 D, Args, CoverageIgnorelistFiles,
872 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
873 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
874 DiagnoseErrors);
877 // Parse -f(no-)?sanitize-metadata.
878 for (const auto *Arg :
879 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
880 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
881 if (Arg->getOption().matches(
882 options::OPT_fexperimental_sanitize_metadata_EQ)) {
883 Arg->claim();
884 BinaryMetadataFeatures |=
885 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
886 } else {
887 Arg->claim();
888 BinaryMetadataFeatures &=
889 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
893 // Parse -fsanitize-metadata-ignorelist option if enabled.
894 if (BinaryMetadataFeatures) {
895 parseSpecialCaseListArg(
896 D, Args, BinaryMetadataIgnorelistFiles,
897 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
898 OptSpecifier(), // Cannot clear ignore list, only append.
899 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
900 DiagnoseErrors);
903 SharedRuntime =
904 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
905 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
906 TC.getTriple().isOSDarwin());
908 ImplicitCfiRuntime = TC.getTriple().isAndroid();
910 if (AllAddedKinds & SanitizerKind::Address) {
911 NeedPIE |= TC.getTriple().isOSFuchsia();
912 if (Arg *A =
913 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
914 StringRef S = A->getValue();
915 // Legal values are 0 and 1, 2, but in future we may add more levels.
916 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
917 AsanFieldPadding > 2) &&
918 DiagnoseErrors) {
919 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
923 if (Arg *WindowsDebugRTArg =
924 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
925 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
926 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
927 switch (WindowsDebugRTArg->getOption().getID()) {
928 case options::OPT__SLASH_MTd:
929 case options::OPT__SLASH_MDd:
930 case options::OPT__SLASH_LDd:
931 if (DiagnoseErrors) {
932 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
933 << WindowsDebugRTArg->getAsString(Args)
934 << lastArgumentForMask(D, Args, SanitizerKind::Address);
935 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
940 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
941 options::OPT_fno_sanitize_stable_abi, false);
943 AsanUseAfterScope = Args.hasFlag(
944 options::OPT_fsanitize_address_use_after_scope,
945 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
947 AsanPoisonCustomArrayCookie = Args.hasFlag(
948 options::OPT_fsanitize_address_poison_custom_array_cookie,
949 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
950 AsanPoisonCustomArrayCookie);
952 AsanOutlineInstrumentation =
953 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
954 options::OPT_fno_sanitize_address_outline_instrumentation,
955 AsanOutlineInstrumentation);
957 AsanGlobalsDeadStripping = Args.hasFlag(
958 options::OPT_fsanitize_address_globals_dead_stripping,
959 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
961 // Enable ODR indicators which allow better handling of mixed instrumented
962 // and uninstrumented globals. Disable them for Windows where weak odr
963 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
964 // errors in the absence of -lldmingw.
965 AsanUseOdrIndicator =
966 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
967 options::OPT_fno_sanitize_address_use_odr_indicator,
968 !TC.getTriple().isOSWindows());
970 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
971 AsanInvalidPointerCmp = true;
974 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
975 AsanInvalidPointerSub = true;
978 if (TC.getTriple().isOSDarwin() &&
979 (Args.hasArg(options::OPT_mkernel) ||
980 Args.hasArg(options::OPT_fapple_kext))) {
981 AsanDtorKind = llvm::AsanDtorKind::None;
984 if (const auto *Arg =
985 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
986 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
987 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
988 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
989 << Arg->getSpelling() << Arg->getValue();
991 AsanDtorKind = parsedAsanDtorKind;
994 if (const auto *Arg = Args.getLastArg(
995 options::OPT_sanitize_address_use_after_return_EQ)) {
996 auto parsedAsanUseAfterReturn =
997 AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
998 if (parsedAsanUseAfterReturn ==
999 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1000 DiagnoseErrors) {
1001 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1002 << Arg->getSpelling() << Arg->getValue();
1004 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1007 } else {
1008 AsanUseAfterScope = false;
1009 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1010 SanitizerMask DetectInvalidPointerPairs =
1011 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1012 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1013 DiagnoseErrors) {
1014 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1015 << lastArgumentForMask(D, Args,
1016 SanitizerKind::PointerCompare |
1017 SanitizerKind::PointerSubtract)
1018 << "-fsanitize=address";
1022 if (AllAddedKinds & SanitizerKind::HWAddress) {
1023 if (Arg *HwasanAbiArg =
1024 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1025 HwasanAbi = HwasanAbiArg->getValue();
1026 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1027 DiagnoseErrors)
1028 D.Diag(clang::diag::err_drv_invalid_value)
1029 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1030 } else {
1031 HwasanAbi = "interceptor";
1033 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1034 HwasanUseAliases = Args.hasFlag(
1035 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1036 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1037 HwasanUseAliases);
1040 if (AllAddedKinds & SanitizerKind::SafeStack) {
1041 // SafeStack runtime is built into the system on Android and Fuchsia.
1042 SafeStackRuntime =
1043 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1046 LinkRuntimes =
1047 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1048 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1050 // Parse -link-cxx-sanitizer flag.
1051 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1052 options::OPT_fno_sanitize_link_cxx_runtime,
1053 LinkCXXRuntimes) ||
1054 D.CCCIsCXX();
1056 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1057 options::OPT_fmemory_profile_EQ,
1058 options::OPT_fno_memory_profile, false);
1060 // Finally, initialize the set of available and recoverable sanitizers.
1061 Sanitizers.Mask |= Kinds;
1062 RecoverableSanitizers.Mask |= RecoverableKinds;
1063 TrapSanitizers.Mask |= TrappingKinds;
1064 assert(!(RecoverableKinds & TrappingKinds) &&
1065 "Overlap between recoverable and trapping sanitizers");
1068 static std::string toString(const clang::SanitizerSet &Sanitizers) {
1069 std::string Res;
1070 #define SANITIZER(NAME, ID) \
1071 if (Sanitizers.has(SanitizerKind::ID)) { \
1072 if (!Res.empty()) \
1073 Res += ","; \
1074 Res += NAME; \
1076 #include "clang/Basic/Sanitizers.def"
1077 return Res;
1080 static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1081 llvm::opt::ArgStringList &CmdArgs,
1082 const char *SCLOptFlag,
1083 const std::vector<std::string> &SCLFiles) {
1084 for (const auto &SCLPath : SCLFiles) {
1085 SmallString<64> SCLOpt(SCLOptFlag);
1086 SCLOpt += SCLPath;
1087 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1091 static void addIncludeLinkerOption(const ToolChain &TC,
1092 const llvm::opt::ArgList &Args,
1093 llvm::opt::ArgStringList &CmdArgs,
1094 StringRef SymbolName) {
1095 SmallString<64> LinkerOptionFlag;
1096 LinkerOptionFlag = "--linker-option=/include:";
1097 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1098 // Win32 mangles C function names with a '_' prefix.
1099 LinkerOptionFlag += '_';
1101 LinkerOptionFlag += SymbolName;
1102 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1105 static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1106 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1107 ++Start) {
1108 auto It = std::find(Start, End, StringRef("+mte"));
1109 if (It == End)
1110 break;
1111 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1112 return true;
1113 Start = It;
1115 return false;
1118 void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1119 llvm::opt::ArgStringList &CmdArgs,
1120 types::ID InputType) const {
1121 // NVPTX doesn't currently support sanitizers. Bailing out here means
1122 // that e.g. -fsanitize=address applies only to host code, which is what we
1123 // want for now.
1124 if (TC.getTriple().isNVPTX())
1125 return;
1126 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1127 bool GPUSanitize = false;
1128 if (TC.getTriple().isAMDGPU()) {
1129 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1130 true))
1131 return;
1132 GPUSanitize = true;
1135 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1136 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1137 // sanitizers.
1138 std::pair<int, const char *> CoverageFlags[] = {
1139 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1140 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1141 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1142 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1143 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1144 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1145 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1146 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1147 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1148 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1149 std::make_pair(CoverageTracePCGuard,
1150 "-fsanitize-coverage-trace-pc-guard"),
1151 std::make_pair(CoverageInline8bitCounters,
1152 "-fsanitize-coverage-inline-8bit-counters"),
1153 std::make_pair(CoverageInlineBoolFlag,
1154 "-fsanitize-coverage-inline-bool-flag"),
1155 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1156 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1157 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1158 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1159 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1160 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1161 for (auto F : CoverageFlags) {
1162 if (CoverageFeatures & F.first)
1163 CmdArgs.push_back(F.second);
1165 addSpecialCaseListOpt(
1166 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1167 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1168 CoverageIgnorelistFiles);
1170 if (!GPUSanitize) {
1171 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1172 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1173 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1174 std::make_pair(BinaryMetadataCovered, "covered"),
1175 std::make_pair(BinaryMetadataAtomics, "atomics"),
1176 std::make_pair(BinaryMetadataUAR, "uar")};
1177 for (const auto &F : BinaryMetadataFlags) {
1178 if (BinaryMetadataFeatures & F.first)
1179 CmdArgs.push_back(
1180 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1182 addSpecialCaseListOpt(Args, CmdArgs,
1183 "-fexperimental-sanitize-metadata-ignorelist=",
1184 BinaryMetadataIgnorelistFiles);
1187 if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
1188 // Instruct the code generator to embed linker directives in the object file
1189 // that cause the required runtime libraries to be linked.
1190 CmdArgs.push_back(
1191 Args.MakeArgString("--dependent-lib=" +
1192 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1193 if (types::isCXX(InputType))
1194 CmdArgs.push_back(Args.MakeArgString(
1195 "--dependent-lib=" +
1196 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1198 if (TC.getTriple().isOSWindows() && needsStatsRt()) {
1199 CmdArgs.push_back(Args.MakeArgString(
1200 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1202 // The main executable must export the stats runtime.
1203 // FIXME: Only exporting from the main executable (e.g. based on whether the
1204 // translation unit defines main()) would save a little space, but having
1205 // multiple copies of the runtime shouldn't hurt.
1206 CmdArgs.push_back(Args.MakeArgString(
1207 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1208 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1211 if (Sanitizers.empty())
1212 return;
1213 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1215 if (!RecoverableSanitizers.empty())
1216 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1217 toString(RecoverableSanitizers)));
1219 if (!TrapSanitizers.empty())
1220 CmdArgs.push_back(
1221 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1223 addSpecialCaseListOpt(Args, CmdArgs,
1224 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1225 addSpecialCaseListOpt(Args, CmdArgs,
1226 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1228 if (MsanTrackOrigins)
1229 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1230 Twine(MsanTrackOrigins)));
1232 if (MsanUseAfterDtor)
1233 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1235 if (!MsanParamRetval)
1236 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1238 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1239 if (!TsanMemoryAccess) {
1240 CmdArgs.push_back("-mllvm");
1241 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1242 CmdArgs.push_back("-mllvm");
1243 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1245 if (!TsanFuncEntryExit) {
1246 CmdArgs.push_back("-mllvm");
1247 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1249 if (!TsanAtomics) {
1250 CmdArgs.push_back("-mllvm");
1251 CmdArgs.push_back("-tsan-instrument-atomics=0");
1254 if (HwasanUseAliases) {
1255 CmdArgs.push_back("-mllvm");
1256 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1259 if (CfiCrossDso)
1260 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1262 if (CfiICallGeneralizePointers)
1263 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1265 if (CfiICallNormalizeIntegers)
1266 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1268 if (CfiCanonicalJumpTables)
1269 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1271 if (Stats)
1272 CmdArgs.push_back("-fsanitize-stats");
1274 if (MinimalRuntime)
1275 CmdArgs.push_back("-fsanitize-minimal-runtime");
1277 if (AsanFieldPadding)
1278 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1279 Twine(AsanFieldPadding)));
1281 if (AsanUseAfterScope)
1282 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1284 if (AsanPoisonCustomArrayCookie)
1285 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1287 if (AsanGlobalsDeadStripping)
1288 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1290 if (!AsanUseOdrIndicator)
1291 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1293 if (AsanInvalidPointerCmp) {
1294 CmdArgs.push_back("-mllvm");
1295 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1298 if (AsanInvalidPointerSub) {
1299 CmdArgs.push_back("-mllvm");
1300 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1303 if (AsanOutlineInstrumentation) {
1304 CmdArgs.push_back("-mllvm");
1305 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1308 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1309 // inlining shadow memory poisoning. While this is a big performance burden
1310 // for now it allows full abstraction from implementation details.
1311 if (StableABI) {
1312 CmdArgs.push_back("-mllvm");
1313 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1314 CmdArgs.push_back("-mllvm");
1315 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1316 CmdArgs.push_back("-mllvm");
1317 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1320 // Only pass the option to the frontend if the user requested,
1321 // otherwise the frontend will just use the codegen default.
1322 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1323 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1324 AsanDtorKindToString(AsanDtorKind)));
1327 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1328 CmdArgs.push_back(Args.MakeArgString(
1329 "-fsanitize-address-use-after-return=" +
1330 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1333 if (!HwasanAbi.empty()) {
1334 CmdArgs.push_back("-default-function-attr");
1335 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1338 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1339 CmdArgs.push_back("-target-feature");
1340 CmdArgs.push_back("+tagged-globals");
1343 // MSan: Workaround for PR16386.
1344 // ASan: This is mainly to help LSan with cases such as
1345 // https://github.com/google/sanitizers/issues/373
1346 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1347 // affect compilation.
1348 if (Sanitizers.has(SanitizerKind::Memory) ||
1349 Sanitizers.has(SanitizerKind::Address))
1350 CmdArgs.push_back("-fno-assume-sane-operator-new");
1352 // libFuzzer wants to intercept calls to certain library functions, so the
1353 // following -fno-builtin-* flags force the compiler to emit interposable
1354 // libcalls to these functions. Other sanitizers effectively do the same thing
1355 // by marking all library call sites with NoBuiltin attribute in their LLVM
1356 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1357 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1358 CmdArgs.push_back("-fno-builtin-bcmp");
1359 CmdArgs.push_back("-fno-builtin-memcmp");
1360 CmdArgs.push_back("-fno-builtin-strncmp");
1361 CmdArgs.push_back("-fno-builtin-strcmp");
1362 CmdArgs.push_back("-fno-builtin-strncasecmp");
1363 CmdArgs.push_back("-fno-builtin-strcasecmp");
1364 CmdArgs.push_back("-fno-builtin-strstr");
1365 CmdArgs.push_back("-fno-builtin-strcasestr");
1366 CmdArgs.push_back("-fno-builtin-memmem");
1369 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1370 // enabled.
1371 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1372 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1373 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1374 << lastArgumentForMask(TC.getDriver(), Args,
1375 Sanitizers.Mask & CFIClasses)
1376 << "-fvisibility=";
1379 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1380 !hasTargetFeatureMTE(CmdArgs))
1381 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1384 SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1385 bool DiagnoseErrors) {
1386 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1387 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1388 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1389 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1390 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1391 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1392 "Invalid argument in parseArgValues!");
1393 SanitizerMask Kinds;
1394 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1395 const char *Value = A->getValue(i);
1396 SanitizerMask Kind;
1397 // Special case: don't accept -fsanitize=all.
1398 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1399 0 == strcmp("all", Value))
1400 Kind = SanitizerMask();
1401 else
1402 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1404 if (Kind)
1405 Kinds |= Kind;
1406 else if (DiagnoseErrors)
1407 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1408 << A->getSpelling() << Value;
1410 return Kinds;
1413 int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1414 bool DiagnoseErrors) {
1415 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1416 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1417 int Features = 0;
1418 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1419 const char *Value = A->getValue(i);
1420 int F = llvm::StringSwitch<int>(Value)
1421 .Case("func", CoverageFunc)
1422 .Case("bb", CoverageBB)
1423 .Case("edge", CoverageEdge)
1424 .Case("indirect-calls", CoverageIndirCall)
1425 .Case("trace-bb", CoverageTraceBB)
1426 .Case("trace-cmp", CoverageTraceCmp)
1427 .Case("trace-div", CoverageTraceDiv)
1428 .Case("trace-gep", CoverageTraceGep)
1429 .Case("8bit-counters", Coverage8bitCounters)
1430 .Case("trace-pc", CoverageTracePC)
1431 .Case("trace-pc-guard", CoverageTracePCGuard)
1432 .Case("no-prune", CoverageNoPrune)
1433 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1434 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1435 .Case("pc-table", CoveragePCTable)
1436 .Case("stack-depth", CoverageStackDepth)
1437 .Case("trace-loads", CoverageTraceLoads)
1438 .Case("trace-stores", CoverageTraceStores)
1439 .Case("control-flow", CoverageControlFlow)
1440 .Default(0);
1441 if (F == 0 && DiagnoseErrors)
1442 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1443 << A->getSpelling() << Value;
1444 Features |= F;
1446 return Features;
1449 int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1450 bool DiagnoseErrors) {
1451 assert(
1452 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1453 A->getOption().matches(
1454 options::OPT_fno_experimental_sanitize_metadata_EQ));
1455 int Features = 0;
1456 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1457 const char *Value = A->getValue(i);
1458 int F = llvm::StringSwitch<int>(Value)
1459 .Case("covered", BinaryMetadataCovered)
1460 .Case("atomics", BinaryMetadataAtomics)
1461 .Case("uar", BinaryMetadataUAR)
1462 .Case("all", ~0)
1463 .Default(0);
1464 if (F == 0 && DiagnoseErrors)
1465 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1466 << A->getSpelling() << Value;
1467 Features |= F;
1469 return Features;
1472 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1473 SanitizerMask Mask) {
1474 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1475 E = Args.rend();
1476 I != E; ++I) {
1477 const auto *Arg = *I;
1478 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1479 SanitizerMask AddKinds =
1480 expandSanitizerGroups(parseArgValues(D, Arg, false));
1481 if (AddKinds & Mask)
1482 return describeSanitizeArg(Arg, Mask);
1483 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1484 SanitizerMask RemoveKinds =
1485 expandSanitizerGroups(parseArgValues(D, Arg, false));
1486 Mask &= ~RemoveKinds;
1489 llvm_unreachable("arg list didn't provide expected value");
1492 std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1493 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1494 "Invalid argument in describeSanitizerArg!");
1496 std::string Sanitizers;
1497 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1498 if (expandSanitizerGroups(
1499 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1500 Mask) {
1501 if (!Sanitizers.empty())
1502 Sanitizers += ",";
1503 Sanitizers += A->getValue(i);
1507 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1508 return "-fsanitize=" + Sanitizers;