clang 23.0.0git
SanitizerArgs.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
10#include "clang/Driver/Driver.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/Path.h"
17#include "llvm/Support/SpecialCaseList.h"
18#include "llvm/Support/VirtualFileSystem.h"
19#include "llvm/TargetParser/AArch64TargetParser.h"
20#include "llvm/TargetParser/RISCVTargetParser.h"
21#include "llvm/TargetParser/TargetParser.h"
22#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
23#include <memory>
24
25using namespace clang;
26using namespace clang::driver;
27using namespace llvm::opt;
28
30 SanitizerKind::Undefined | SanitizerKind::Integer |
31 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |
32 SanitizerKind::Nullability | SanitizerKind::CFI |
33 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |
34 SanitizerKind::Vptr;
36 SanitizerKind::Vptr | SanitizerKind::CFI;
37static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
38static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;
40 SanitizerKind::Function | SanitizerKind::KCFI;
42 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
43 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
44 SanitizerKind::NumericalStability;
46 SanitizerKind::Address | SanitizerKind::HWAddress |
47 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
48 SanitizerKind::Type | SanitizerKind::MemtagStack |
49 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
50 SanitizerKind::Memory | 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 SanitizerKind::NumericalStability | SanitizerKind::Vptr |
58 SanitizerKind::CFI | SanitizerKind::AllocToken;
60 SanitizerKind::Undefined | SanitizerKind::Integer |
61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |
63 SanitizerKind::Vptr;
64static const SanitizerMask Unrecoverable = SanitizerKind::Unreachable |
65 SanitizerKind::Return |
66 SanitizerKind::AllocToken;
67static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |
68 SanitizerKind::KernelHWAddress |
69 SanitizerKind::KCFI;
70static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
72 SanitizerKind::Undefined | SanitizerKind::Integer |
73 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
74 SanitizerKind::LocalBounds | SanitizerKind::CFI |
75 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
77 SanitizerKind::Undefined | SanitizerKind::Vptr;
79 SanitizerKind::CFI | SanitizerKind::LocalBounds;
82 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
83 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
84 SanitizerKind::CFIUnrelatedCast;
86 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
87 SanitizerKind::SafeStack | SanitizerKind::MemtagStack |
88 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
89 SanitizerKind::KCFI | SanitizerKind::AllocToken;
90
113
119
120/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
121/// invalid components. Returns a SanitizerMask.
122static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
123 bool DiagnoseErrors);
124
125/// Parse a -fsanitize=<sanitizer1>=<value1>... or -fno-sanitize= argument's
126/// values, diagnosing any invalid components.
127/// Cutoffs are stored in the passed parameter.
128static void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,
129 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs);
130
131/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid
132/// components. Returns OR of members of \c CoverageFeature enumeration.
133static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
134 bool DiagnoseErrors);
135
136/// Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing
137/// any invalid values. Returns a mask of excluded overflow patterns.
139 const llvm::opt::Arg *A,
140 bool DiagnoseErrors);
141
142/// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid
143/// components. Returns OR of members of \c BinaryMetadataFeature enumeration.
144static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
145 bool DiagnoseErrors);
146
147/// Produce an argument string from ArgList \p Args, which shows how it
148/// provides some sanitizer kind from \p Mask. For example, the argument list
149/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
150/// would produce "-fsanitize=vptr".
151static std::string lastArgumentForMask(const Driver &D,
152 const llvm::opt::ArgList &Args,
153 SanitizerMask Mask);
154
155/// Produce an argument string from argument \p A, which shows how it provides
156/// a value in \p Mask. For instance, the argument
157/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
158/// "-fsanitize=alignment".
159static std::string describeSanitizeArg(const llvm::opt::Arg *A,
160 SanitizerMask Mask);
161
162/// Produce a string containing comma-separated names of sanitizers in \p
163/// Sanitizers set.
164static std::string toString(const clang::SanitizerSet &Sanitizers);
165
166/// Produce a string containing comma-separated names of sanitizers and
167/// sanitizer groups in \p Sanitizers set.
168static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers);
169
170/// Return true if an execute-only target disallows data access to code
171/// sections.
172static bool isExecuteOnlyTarget(const llvm::Triple &Triple,
173 const llvm::opt::ArgList &Args) {
174 if (Triple.isPS5())
175 return true;
176 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
177 options::OPT_mno_execute_only, false);
178}
179
181 std::vector<std::string> &SCLFiles,
182 unsigned MalformedSCLErrorDiagID,
183 bool DiagnoseErrors) {
184 if (SCLFiles.empty())
185 return;
186
187 std::string BLError;
188 std::unique_ptr<llvm::SpecialCaseList> SCL(
189 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
190 if (!SCL && DiagnoseErrors)
191 D.Diag(MalformedSCLErrorDiagID) << BLError;
192}
193
194static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
195 std::vector<std::string> &IgnorelistFiles,
196 bool DiagnoseErrors) {
197 struct Ignorelist {
198 const char *File;
199 SanitizerMask Mask;
200 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
201 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
202 {"memtag_ignorelist.txt", SanitizerKind::MemTag},
203 {"msan_ignorelist.txt", SanitizerKind::Memory},
204 {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
205 {"tsan_ignorelist.txt", SanitizerKind::Thread},
206 {"tysan_blacklist.txt", SanitizerKind::Type},
207 {"dfsan_abilist.txt", SanitizerKind::DataFlow},
208 {"cfi_ignorelist.txt", SanitizerKind::CFI},
209 {"alloc_token_ignorelist.txt", SanitizerKind::AllocToken},
210 {"ubsan_ignorelist.txt",
211 SanitizerKind::Undefined | SanitizerKind::Vptr |
212 SanitizerKind::Integer | SanitizerKind::Nullability |
213 SanitizerKind::FloatDivideByZero}};
214
215 for (auto BL : Ignorelists) {
216 if (!(Kinds & BL.Mask))
217 continue;
218
220 llvm::sys::path::append(Path, "share", BL.File);
221 if (D.getVFS().exists(Path))
222 IgnorelistFiles.push_back(std::string(Path));
223 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
224 // If cfi_ignorelist.txt cannot be found in the resource dir, driver
225 // should fail.
226 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
227 }
229 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
230 DiagnoseErrors);
231}
232
233/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
234/// diagnosing any invalid file paths and validating special case list format.
235static void parseSpecialCaseListArg(const Driver &D,
236 const llvm::opt::ArgList &Args,
237 std::vector<std::string> &SCLFiles,
238 llvm::opt::OptSpecifier SCLOptionID,
239 llvm::opt::OptSpecifier NoSCLOptionID,
240 unsigned MalformedSCLErrorDiagID,
241 bool DiagnoseErrors) {
242 for (const auto *Arg : Args) {
243 // Match -fsanitize-(coverage-)?(allow|ignore)list.
244 if (Arg->getOption().matches(SCLOptionID)) {
245 Arg->claim();
246 std::string SCLPath = Arg->getValue();
247 if (D.getVFS().exists(SCLPath)) {
248 SCLFiles.push_back(SCLPath);
249 } else if (DiagnoseErrors) {
250 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
251 }
252 // Match -fno-sanitize-ignorelist.
253 } else if (Arg->getOption().matches(NoSCLOptionID)) {
254 Arg->claim();
255 SCLFiles.clear();
256 }
257 }
258 validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,
259 DiagnoseErrors);
260}
261
262/// Sets group bits for every group that has at least one representative already
263/// enabled in \p Kinds.
265#define SANITIZER(NAME, ID)
266#define SANITIZER_GROUP(NAME, ID, ALIAS) \
267 if (Kinds & SanitizerKind::ID) \
268 Kinds |= SanitizerKind::ID##Group;
269#include "clang/Basic/Sanitizers.def"
270 return Kinds;
271}
272
273// Computes the sanitizer mask as:
274// Default + Arguments (in or out) + AlwaysIn - AlwaysOut
275// with arguments parsed from left to right.
276static SanitizerMask
277parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
278 bool DiagnoseErrors, SanitizerMask Default,
280 int OptOutID) {
281 assert(!(AlwaysIn & AlwaysOut) &&
282 "parseSanitizeArgs called with contradictory in/out requirements");
283
284 SanitizerMask Output = Default;
285 // Keep track of which violations we have already reported, to avoid
286 // duplicate error messages.
287 SanitizerMask DiagnosedAlwaysInViolations;
288 SanitizerMask DiagnosedAlwaysOutViolations;
289 for (const auto *Arg : Args) {
290 if (Arg->getOption().matches(OptInID)) {
291 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
292 // Report error if user explicitly tries to opt-in to an always-out
293 // sanitizer.
294 if (SanitizerMask KindsToDiagnose =
295 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
296 if (DiagnoseErrors) {
297 SanitizerSet SetToDiagnose;
298 SetToDiagnose.Mask |= KindsToDiagnose;
299 D.Diag(diag::err_drv_unsupported_option_argument)
300 << Arg->getSpelling() << toStringWithGroups(SetToDiagnose);
301 DiagnosedAlwaysOutViolations |= KindsToDiagnose;
302 }
303 }
304 Output |= expandSanitizerGroups(Add);
305 Arg->claim();
306 } else if (Arg->getOption().matches(OptOutID)) {
307 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
308 // Report error if user explicitly tries to opt-out of an always-in
309 // sanitizer.
310 if (SanitizerMask KindsToDiagnose =
311 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
312 if (DiagnoseErrors) {
313 SanitizerSet SetToDiagnose;
314 SetToDiagnose.Mask |= KindsToDiagnose;
315 D.Diag(diag::err_drv_unsupported_option_argument)
316 << Arg->getSpelling() << toStringWithGroups(SetToDiagnose);
317 DiagnosedAlwaysInViolations |= KindsToDiagnose;
318 }
319 }
320 Output &= ~expandSanitizerGroups(Remove);
321 Arg->claim();
322 }
323 }
324
325 Output |= AlwaysIn;
326 Output &= ~AlwaysOut;
327
328 return Output;
329}
330
332 const llvm::opt::ArgList &Args,
333 bool DiagnoseErrors) {
334 SanitizerMask AlwaysTrap; // Empty
336
337 return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
338 NeverTrap, options::OPT_fsanitize_trap_EQ,
339 options::OPT_fno_sanitize_trap_EQ);
340}
341
343parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args,
344 bool DiagnoseErrors) {
345 SanitizerMaskCutoffs Cutoffs;
346 for (const auto *Arg : Args)
347 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {
348 Arg->claim();
349 parseArgCutoffs(D, Arg, DiagnoseErrors, Cutoffs);
350 }
351
352 return Cutoffs;
353}
354
358
360 // All of these include ubsan.
361 if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
364 return false;
365
366 return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
367 CoverageFeatures;
368}
369
371 // Link UBSAN C++ runtime very selectively, as it's needed in only very
372 // specific cases, but forces the program to depend on C++ ABI. UBSAN C++
373 // runtime is not included with other sanitizers.
374 return static_cast<bool>(Sanitizers.Mask & NeedsUbsanCxxRt &
375 ~TrapSanitizers.Mask);
376}
377
379 // Diag runtime includes cross dso runtime.
380 return !needsCfiCrossDsoDiagRt() && CfiCrossDso && !ImplicitCfiRuntime;
381}
382
384 // UBSsan handles CFI diagnostics without cross-DSO suppport.
385 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
386 CfiCrossDso && !ImplicitCfiRuntime;
387}
388
389bool SanitizerArgs::requiresPIE() const { return NeedPIE; }
390
392 return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
393}
394
396 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
397}
398
400 const llvm::opt::ArgList &Args,
401 bool DiagnoseErrors, bool DiagnoseBoundArchErrors,
402 StringRef BoundArch,
403 Action::OffloadKind DeviceOffloadKind) {
404 SanitizerMask AllRemove; // During the loop below, the accumulated set of
405 // sanitizers disabled by the current sanitizer
406 // argument or any argument after it.
407 SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
408 // -fsanitize= flags (directly or via group
409 // expansion), some of which may be disabled
410 // later. Used to carefully prune
411 // unused-argument diagnostics.
412 SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
413 // Used to deduplicate diagnostics.
414 SanitizerMask IgnoreForUbsanFeature; // Accumulated set of values passed to
415 // `-fsanitize-ignore-for-ubsan-feature`.
416 SanitizerMask Kinds;
417
418 // Figure out the base toolchain's sanitizer support so we can diagnose the
419 // diff for a specific BoundArch.
420 const SanitizerMask ToolChainSupported =
421 setGroupBits(TC.getSupportedSanitizers("", DeviceOffloadKind));
422
423 const SanitizerMask BoundArchSupported =
424 BoundArch.empty() ? ToolChainSupported
426 BoundArch, DeviceOffloadKind));
427
428 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
429 options::OPT_fno_sanitize_cfi_cross_dso, false);
430
431 ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
432
433 const Driver &D = TC.getDriver();
434 SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);
435 SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
436 const llvm::Triple &Triple = TC.getTriple();
437
438 MinimalRuntime =
439 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
440 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
441 HandlerPreserveAllRegs =
442 Args.hasFlag(options::OPT_fsanitize_handler_preserve_all_regs,
443 options::OPT_fno_sanitize_handler_preserve_all_regs,
444 HandlerPreserveAllRegs) &&
445 MinimalRuntime && (Triple.isAArch64() || Triple.isX86_64());
446 TrapLoop = Args.hasFlag(options::OPT_fsanitize_trap_loop,
447 options::OPT_fno_sanitize_trap_loop, false);
448
449 // The object size sanitizer should not be enabled at -O0.
450 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
451 bool RemoveObjectSizeAtO0 =
452 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
453
454 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
455 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
456 Arg->claim();
457 SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
458
459 if (RemoveObjectSizeAtO0) {
460 AllRemove |= SanitizerKind::ObjectSize;
461
462 // The user explicitly enabled the object size sanitizer. Warn
463 // that this does nothing at -O0.
464 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
465 D.Diag(diag::warn_drv_object_size_disabled_O0)
466 << Arg->getAsString(Args);
467 }
468
469 AllAddedKinds |= expandSanitizerGroups(Add);
470
471 // Avoid diagnosing any sanitizer which is disabled later.
472 Add &= ~AllRemove;
473 // At this point we have not expanded groups, so any unsupported
474 // sanitizers in Add are those which have been explicitly enabled.
475 // Diagnose them.
476 if (SanitizerMask KindsToDiagnose =
477 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
478 if (DiagnoseErrors) {
479 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
480 D.Diag(diag::err_drv_argument_not_allowed_with)
481 << Desc << "-fsanitize-trap=undefined";
482 }
483 DiagnosedKinds |= KindsToDiagnose;
484 }
485 Add &= ~InvalidTrappingKinds;
486
487 if (MinimalRuntime) {
488 if (SanitizerMask KindsToDiagnose =
489 Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {
490 if (DiagnoseErrors) {
491 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
492 D.Diag(diag::err_drv_argument_not_allowed_with)
493 << Desc << "-fsanitize-minimal-runtime";
494 }
495 DiagnosedKinds |= KindsToDiagnose;
496 }
498 }
499
500 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
501 StringRef CM = A->getValue();
502 if (CM != "small" &&
503 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
504 if (DiagnoseErrors)
505 D.Diag(diag::err_drv_argument_only_allowed_with)
506 << "-fsanitize=function"
507 << "-mcmodel=small";
509 DiagnosedKinds |= SanitizerKind::Function;
510 }
511 }
512 // -fsanitize=function and -fsanitize=kcfi instrument indirect function
513 // calls to load a type hash before the function label. Therefore, an
514 // execute-only target doesn't support the function and kcfi sanitizers.
515 if (isExecuteOnlyTarget(Triple, Args)) {
516 if (SanitizerMask KindsToDiagnose =
517 Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {
518 if (DiagnoseErrors) {
519 std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);
520 llvm::opt::Arg *A = Args.getLastArgNoClaim(
521 options::OPT_mexecute_only, options::OPT_mno_execute_only);
522 if (A && A->getOption().matches(options::OPT_mexecute_only))
523 D.Diag(diag::err_drv_argument_not_allowed_with)
524 << Desc << A->getAsString(Args);
525 else
526 D.Diag(diag::err_drv_unsupported_opt_for_target)
527 << Desc << Triple.str();
528 }
529 DiagnosedKinds |= KindsToDiagnose;
530 }
532 }
533
534 // FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
535 // There are currently two problems:
536 // - Virtual function call checks need to pass a pointer to the function
537 // address to llvm.type.test and a pointer to the address point to the
538 // diagnostic function. Currently we pass the same pointer to both
539 // places.
540 // - Non-virtual function call checks may need to check multiple type
541 // identifiers.
542 // Fixing both of those may require changes to the cross-DSO CFI
543 // interface.
544 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
545 if (DiagnoseErrors)
546 D.Diag(diag::err_drv_argument_not_allowed_with)
547 << "-fsanitize=cfi-mfcall"
548 << "-fsanitize-cfi-cross-dso";
549 Add &= ~SanitizerKind::CFIMFCall;
550 DiagnosedKinds |= SanitizerKind::CFIMFCall;
551 }
552
553 // Check for sanitizers that are supported by the toolchain but not for
554 // this specific arch (e.g., AMDGPU requires specific subtarget features
555 // for address sanitizer.)
556 if (SanitizerMask ArchSpecificUnsupported =
557 Add & ToolChainSupported & ~BoundArchSupported & ~DiagnosedKinds;
558 ArchSpecificUnsupported && DiagnoseBoundArchErrors) {
559 // Upgrade the warning to an error if the unsupported sanitizer was
560 // explicitly specified for the bound arch.
561
562 // FIXME: There are additional options which explicitly bind to this
563 // device.
564 bool IsExplicitDevice =
565 Arg->getBaseArg().getOption().matches(options::OPT_Xarch_device);
566
567 // Check if the toolchain provides a feature requirement hint for
568 // any of the unsupported sanitizers
569 StringRef Requirement =
570 TC.getSanitizerRequirement(ArchSpecificUnsupported, BoundArch);
571 if (!Requirement.empty()) {
572 // Emit diagnostic with feature requirement
573 //
574 // TODO: Use variant of unsupported_option_part_for_target that
575 // includes offload_arch_req_feature
576 D.Diag(
577 IsExplicitDevice
578 ? diag::
579 err_drv_unsupported_option_for_offload_arch_req_feature
580 : diag::
581 warn_drv_unsupported_option_for_offload_arch_req_feature)
582 << Arg->getAsString(Args) << BoundArch << Requirement;
583 } else {
584 // Fall back to generic diagnostic if no requirement was provided
585 SanitizerSet UnsupportedSet;
586 UnsupportedSet.Mask = ArchSpecificUnsupported;
587 D.Diag(diag::warn_drv_unsupported_option_part_for_target)
588 << toString(UnsupportedSet) << Arg->getAsString(Args)
589 << Triple.str();
590 }
591
592 DiagnosedKinds |= ArchSpecificUnsupported;
593 }
594
595 // Check for sanitizers that are not supported at all by the toolchain
596 if (SanitizerMask KindsToDiagnose =
597 Add & ~ToolChainSupported & ~DiagnosedKinds;
598 DiagnoseErrors && KindsToDiagnose) {
599 bool IsExplicitDevice =
600 Arg->getBaseArg().getOption().matches(options::OPT_Xarch_device);
601 // For device offload compilation, emit a warning since the sanitizer
602 // may still work on the host. For non-offload compilation or explicit
603 // device specification, emit an error.
604 if (DeviceOffloadKind != Action::OFK_None &&
605 DeviceOffloadKind != Action::OFK_Host) {
606 // For warnings, extract just the sanitizer names (e.g., "fuzzer")
607 // instead of the full argument (e.g., "-fsanitize=fuzzer")
608 SanitizerSet KindSet;
609 KindSet.Mask = KindsToDiagnose;
610 D.Diag(IsExplicitDevice
611 ? diag::err_drv_unsupported_option_part_for_target
612 : diag::warn_drv_unsupported_option_part_for_target)
613 << toString(KindSet) << Arg->getAsString(Args)
614 << TC.getTriple().str();
615 } else {
616 // For non-offload targets, use the shorter diagnostic format
617 D.Diag(diag::err_drv_unsupported_opt_for_target)
618 << describeSanitizeArg(Arg, KindsToDiagnose)
619 << TC.getTriple().str();
620 }
621
622 DiagnosedKinds |= KindsToDiagnose;
623 }
624
625 Add &= BoundArchSupported;
626
627 // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
628 // so we don't error out if -fno-rtti and -fsanitize=undefined were
629 // passed.
630 if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
631 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
632 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
633 "RTTI disabled without -fno-rtti option?");
634 // The user explicitly passed -fno-rtti with -fsanitize=vptr, but
635 // the vptr sanitizer requires RTTI, so this is a user error.
636 if (DiagnoseErrors)
637 D.Diag(diag::err_drv_argument_not_allowed_with)
638 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
639 } else {
640 // The vptr sanitizer requires RTTI, but RTTI is disabled (by
641 // default). Warn that the vptr sanitizer is being disabled.
642 if (DiagnoseErrors)
643 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
644 }
645
646 // Take out the Vptr sanitizer from the enabled sanitizers
647 AllRemove |= SanitizerKind::Vptr;
648 }
649
650 Add = expandSanitizerGroups(Add);
651 // Group expansion may have enabled a sanitizer which is disabled later.
652 Add &= ~AllRemove;
653 // Silently discard any unsupported sanitizers implicitly enabled through
654 // group expansion.
655 Add &= ~InvalidTrappingKinds;
656 if (MinimalRuntime) {
658 }
659 // NotAllowedWithExecuteOnly is silently discarded on an execute-only
660 // target if implicitly enabled through group expansion.
661 if (isExecuteOnlyTarget(Triple, Args))
663 if (CfiCrossDso)
664 Add &= ~SanitizerKind::CFIMFCall;
665 // -fsanitize=undefined does not expand to signed-integer-overflow in
666 // -fwrapv (implied by -fno-strict-overflow) mode.
667 if (Add & SanitizerKind::UndefinedGroup) {
668 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
669 options::OPT_fstrict_overflow, false);
670 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
671 Add &= ~SanitizerKind::SignedIntegerOverflow;
672 if (Args.hasFlagNoClaim(options::OPT_fwrapv_pointer,
673 options::OPT_fno_wrapv_pointer, S))
674 Add &= ~SanitizerKind::PointerOverflow;
675 }
676 Add &= BoundArchSupported;
677
678 if (Add & SanitizerKind::Fuzzer)
679 Add |= SanitizerKind::FuzzerNoLink;
680
681 // Enable coverage if the fuzzing flag is set.
682 if (Add & SanitizerKind::FuzzerNoLink) {
683 CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
685 // Due to TLS differences, stack depth tracking is only enabled on Linux
686 if (TC.getTriple().isOSLinux())
687 CoverageFeatures |= CoverageStackDepth;
688 }
689
690 Kinds |= Add;
691 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
692 Arg->claim();
693 SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
694 AllRemove |= expandSanitizerGroups(Remove);
695 } else if (Arg->getOption().matches(
696 options::OPT_fsanitize_ignore_for_ubsan_feature_EQ)) {
697 Arg->claim();
698 IgnoreForUbsanFeature |=
699 expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
700 }
701 }
702
703 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
704 std::make_pair(SanitizerKind::Address,
705 SanitizerKind::Thread | SanitizerKind::Memory),
706 std::make_pair(SanitizerKind::Type,
707 SanitizerKind::Address | SanitizerKind::KernelAddress |
708 SanitizerKind::Memory | SanitizerKind::Leak |
709 SanitizerKind::Thread | SanitizerKind::KernelAddress),
710 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
711 std::make_pair(SanitizerKind::Leak,
712 SanitizerKind::Thread | SanitizerKind::Memory),
713 std::make_pair(SanitizerKind::KernelAddress,
714 SanitizerKind::Address | SanitizerKind::Leak |
715 SanitizerKind::Thread | SanitizerKind::Memory),
716 std::make_pair(SanitizerKind::HWAddress,
717 SanitizerKind::Address | SanitizerKind::Thread |
718 SanitizerKind::Memory | SanitizerKind::KernelAddress),
719 std::make_pair(SanitizerKind::Scudo,
720 SanitizerKind::Address | SanitizerKind::HWAddress |
721 SanitizerKind::Leak | SanitizerKind::Thread |
722 SanitizerKind::Memory | SanitizerKind::KernelAddress),
723 std::make_pair(SanitizerKind::SafeStack,
724 (TC.getTriple().isOSFuchsia() ? SanitizerMask()
725 : SanitizerKind::Leak) |
726 SanitizerKind::Address | SanitizerKind::HWAddress |
727 SanitizerKind::Thread | SanitizerKind::Memory |
728 SanitizerKind::KernelAddress),
729 std::make_pair(SanitizerKind::KernelHWAddress,
730 SanitizerKind::Address | SanitizerKind::HWAddress |
731 SanitizerKind::Leak | SanitizerKind::Thread |
732 SanitizerKind::Memory | SanitizerKind::KernelAddress |
733 SanitizerKind::SafeStack),
734 std::make_pair(SanitizerKind::KernelMemory,
735 SanitizerKind::Address | SanitizerKind::HWAddress |
736 SanitizerKind::Leak | SanitizerKind::Thread |
737 SanitizerKind::Memory | SanitizerKind::KernelAddress |
738 SanitizerKind::Scudo | SanitizerKind::SafeStack),
739 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
740 SanitizerKind::KernelAddress |
741 SanitizerKind::HWAddress |
742 SanitizerKind::KernelHWAddress),
743 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
744 std::make_pair(SanitizerKind::Realtime,
745 SanitizerKind::Address | SanitizerKind::Thread |
746 SanitizerKind::Undefined | SanitizerKind::Memory |
747 SanitizerKind::Type),
748 std::make_pair(SanitizerKind::AllocToken,
749 SanitizerKind::Address | SanitizerKind::HWAddress |
750 SanitizerKind::KernelAddress |
751 SanitizerKind::KernelHWAddress |
752 SanitizerKind::Memory)};
753
754 // Enable toolchain specific default sanitizers if not explicitly disabled.
755 SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
756
757 // Disable default sanitizers that are incompatible with explicitly requested
758 // ones.
759 for (auto G : IncompatibleGroups) {
760 SanitizerMask Group = G.first;
761 if ((Default & Group) && (Kinds & G.second))
762 Default &= ~Group;
763 }
764
765 Kinds |= Default;
766
767 // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
768 // is disabled.
769 if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
770 Kinds &= ~SanitizerKind::Vptr;
771 }
772
773 // Check that LTO is enabled if we need it.
774 if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {
775 D.Diag(diag::err_drv_argument_only_allowed_with)
776 << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
777 }
778
779 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
780 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
781 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
782 D.Diag(diag::err_drv_argument_only_allowed_with)
783 << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
784 << "-ffixed-x18";
785 }
786
787 // Report error if there are non-trapping sanitizers that require
788 // c++abi-specific parts of UBSan runtime, and they are not provided by the
789 // toolchain. We don't have a good way to check the latter, so we just
790 // check if the toolchan supports vptr.
791 if (~BoundArchSupported & SanitizerKind::Vptr) {
792 SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
793 // The runtime library supports the Microsoft C++ ABI, but only well enough
794 // for CFI. FIXME: Remove this once we support vptr on Windows.
795 if (TC.getTriple().isOSWindows())
796 KindsToDiagnose &= ~SanitizerKind::CFI;
797 if (KindsToDiagnose) {
798 SanitizerSet S;
799 S.Mask = KindsToDiagnose;
800 if (DiagnoseErrors)
801 D.Diag(diag::err_drv_unsupported_opt_for_target)
802 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();
803 Kinds &= ~KindsToDiagnose;
804 }
805 }
806
807 // Warn about incompatible groups of sanitizers.
808 for (auto G : IncompatibleGroups) {
809 SanitizerMask Group = G.first;
810 if (Kinds & Group) {
811 if (SanitizerMask Incompatible = Kinds & G.second) {
812 if (DiagnoseErrors)
813 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
814 << lastArgumentForMask(D, Args, Group)
816 Kinds &= ~Incompatible;
817 }
818 }
819 }
820 // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
821 // -fsanitize=address. Perhaps it should print an error, or perhaps
822 // -f(-no)sanitize=leak should change whether leak detection is enabled by
823 // default in ASan?
824
825 // Parse -f(no-)?sanitize-recover flags.
826 SanitizerMask RecoverableKinds = parseSanitizeArgs(
827 D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
828 Unrecoverable, options::OPT_fsanitize_recover_EQ,
829 options::OPT_fno_sanitize_recover_EQ);
830 RecoverableKinds &= Kinds;
831
832 TrappingKinds &= Kinds;
833 RecoverableKinds &= ~TrappingKinds;
834
835 // Parse -f(no-)?sanitize-nonmerged-handlers flags
836 SanitizerMask MergeKinds =
837 parseSanitizeArgs(D, Args, DiagnoseErrors, MergeDefault, {}, {},
838 options::OPT_fsanitize_merge_handlers_EQ,
839 options::OPT_fno_sanitize_merge_handlers_EQ);
840 MergeKinds &= Kinds;
841
842 // Parse -fno-fsanitize-skip-hot-cutoff flags
843 SkipHotCutoffs = parseSanitizeSkipHotCutoffArgs(D, Args, DiagnoseErrors);
844
845 // Parse -f(no-)?sanitize-annotate-debug-info flags
846 SanitizerMask AnnotateDebugInfoKinds =
847 parseSanitizeArgs(D, Args, DiagnoseErrors, AnnotateDebugInfoDefault, {},
848 {}, options::OPT_fsanitize_annotate_debug_info_EQ,
849 options::OPT_fno_sanitize_annotate_debug_info_EQ);
850 AnnotateDebugInfoKinds &= Kinds;
851
852 // Setup ignorelist files.
853 // Add default ignorelist from resource directory for activated sanitizers,
854 // and validate special case lists format.
855 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
856 addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);
857
858 // Parse -f(no-)?sanitize-ignorelist options.
859 // This also validates special case lists format.
861 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
862 options::OPT_fno_sanitize_ignorelist,
863 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
864
865 // Verify that -fsanitize-coverage-stack-depth-callback-min is >= 0.
866 if (Arg *A = Args.getLastArg(
867 options::OPT_fsanitize_coverage_stack_depth_callback_min_EQ)) {
868 StringRef S = A->getValue();
869 if (S.getAsInteger(0, CoverageStackDepthCallbackMin) ||
870 CoverageStackDepthCallbackMin < 0) {
871 if (DiagnoseErrors)
872 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
873 }
874 }
875
876 // Parse -f[no-]sanitize-memory-track-origins[=level] options.
877 if (AllAddedKinds & SanitizerKind::Memory) {
878 if (Arg *A =
879 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
880 options::OPT_fno_sanitize_memory_track_origins)) {
881 if (!A->getOption().matches(
882 options::OPT_fno_sanitize_memory_track_origins)) {
883 StringRef S = A->getValue();
884 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
885 MsanTrackOrigins > 2) {
886 if (DiagnoseErrors)
887 D.Diag(clang::diag::err_drv_invalid_value)
888 << A->getAsString(Args) << S;
889 }
890 }
891 }
892 MsanUseAfterDtor = Args.hasFlag(
893 options::OPT_fsanitize_memory_use_after_dtor,
894 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
895 MsanParamRetval = Args.hasFlag(
896 options::OPT_fsanitize_memory_param_retval,
897 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
898 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
899 MsanUseAfterDtor = false;
900 MsanParamRetval = Args.hasFlag(
901 options::OPT_fsanitize_memory_param_retval,
902 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
903 } else {
904 MsanUseAfterDtor = false;
905 MsanParamRetval = false;
906 }
907
908 if (AllAddedKinds & SanitizerKind::MemTag) {
909 StringRef S =
910 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
911 if (S == "async" || S == "sync") {
912 MemtagMode = S.str();
913 } else {
914 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
915 << "-fsanitize-memtag-mode=" << S << "{async, sync}";
916 MemtagMode = "sync";
917 }
918 }
919
920 if (AllAddedKinds & SanitizerKind::Thread) {
921 TsanMemoryAccess = Args.hasFlag(
922 options::OPT_fsanitize_thread_memory_access,
923 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
924 TsanFuncEntryExit = Args.hasFlag(
925 options::OPT_fsanitize_thread_func_entry_exit,
926 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
927 TsanAtomics =
928 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
929 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
930 }
931
932 if (AllAddedKinds & SanitizerKind::CFI) {
933 // Without PIE, external function address may resolve to a PLT record, which
934 // can not be verified by the target module.
935 NeedPIE |= CfiCrossDso;
936 CfiICallGeneralizePointers =
937 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
938
939 CfiICallNormalizeIntegers =
940 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
941
942 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
943 D.Diag(diag::err_drv_argument_not_allowed_with)
944 << "-fsanitize-cfi-cross-dso"
945 << "-fsanitize-cfi-icall-generalize-pointers";
946
947 CfiCanonicalJumpTables =
948 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
949 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);
950 }
951
952 if (AllAddedKinds & SanitizerKind::KCFI) {
953 CfiICallGeneralizePointers =
954 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
955 CfiICallNormalizeIntegers =
956 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
957
958 KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);
959
960 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
961 D.Diag(diag::err_drv_argument_not_allowed_with)
962 << "-fsanitize=kcfi"
963 << lastArgumentForMask(D, Args, SanitizerKind::CFI);
964 }
965
966 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
967 options::OPT_fno_sanitize_stats, false);
968
969 if (MinimalRuntime) {
970 SanitizerMask IncompatibleMask =
972 if (IncompatibleMask && DiagnoseErrors)
973 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
974 << "-fsanitize-minimal-runtime"
975 << lastArgumentForMask(D, Args, IncompatibleMask);
976 }
977
978 for (const auto *Arg : Args.filtered(
979 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
980 Arg->claim();
981 OverflowPatternExclusions |=
982 parseOverflowPatternExclusionValues(D, Arg, DiagnoseErrors);
983 }
984
985 // Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
986 // enabled sanitizers.
987 for (const auto *Arg : Args) {
988 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
989 int LegacySanitizeCoverage;
990 if (Arg->getNumValues() == 1 &&
991 !StringRef(Arg->getValue(0))
992 .getAsInteger(0, LegacySanitizeCoverage)) {
993 CoverageFeatures = 0;
994 Arg->claim();
995 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
996 D.Diag(diag::warn_drv_deprecated_arg)
997 << Arg->getAsString(Args) << /*hasReplacement=*/true
998 << "-fsanitize-coverage=trace-pc-guard";
999 }
1000 continue;
1001 }
1002 CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);
1003
1004 // Disable coverage and not claim the flags if there is at least one
1005 // non-supporting sanitizer.
1006 if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {
1007 Arg->claim();
1008 } else {
1009 CoverageFeatures = 0;
1010 }
1011 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
1012 Arg->claim();
1013 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);
1014 }
1015 }
1016 // Choose at most one coverage type: function, bb, or edge.
1017 if (DiagnoseErrors) {
1018 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))
1019 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1020 << "-fsanitize-coverage=func"
1021 << "-fsanitize-coverage=bb";
1022 if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))
1023 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1024 << "-fsanitize-coverage=func"
1025 << "-fsanitize-coverage=edge";
1026 if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))
1027 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1028 << "-fsanitize-coverage=bb"
1029 << "-fsanitize-coverage=edge";
1030 // Basic block tracing and 8-bit counters require some type of coverage
1031 // enabled.
1032 if (CoverageFeatures & CoverageTraceBB)
1033 D.Diag(clang::diag::warn_drv_deprecated_arg)
1034 << "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true
1035 << "-fsanitize-coverage=trace-pc-guard";
1036 if (CoverageFeatures & Coverage8bitCounters)
1037 D.Diag(clang::diag::warn_drv_deprecated_arg)
1038 << "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true
1039 << "-fsanitize-coverage=trace-pc-guard";
1040 }
1041
1042 int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
1043 int InstrumentationTypes = CoverageTracePC | CoverageTracePCEntryExit |
1047 if ((CoverageFeatures & InsertionPointTypes) &&
1048 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
1049 D.Diag(clang::diag::warn_drv_deprecated_arg)
1050 << "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true
1051 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
1052 "control-flow]";
1053 }
1054
1055 // trace-pc w/o func/bb/edge implies edge.
1056 if (!(CoverageFeatures & InsertionPointTypes)) {
1057 if (CoverageFeatures & (CoverageTracePC | CoverageTracePCEntryExit |
1060 CoverageFeatures |= CoverageEdge;
1061
1062 if (CoverageFeatures & CoverageStackDepth)
1063 CoverageFeatures |= CoverageFunc;
1064 }
1065
1066 // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
1067 // This also validates special case lists format.
1068 // Here, OptSpecifier() acts as a never-matching command-line argument.
1069 // So, there is no way to clear coverage lists but you can append to them.
1070 if (CoverageFeatures) {
1072 D, Args, CoverageAllowlistFiles,
1073 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
1074 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
1075 DiagnoseErrors);
1077 D, Args, CoverageIgnorelistFiles,
1078 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
1079 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
1080 DiagnoseErrors);
1081 }
1082
1083 // Parse -f(no-)?sanitize-metadata.
1084 for (const auto *Arg :
1085 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
1086 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
1087 if (Arg->getOption().matches(
1088 options::OPT_fexperimental_sanitize_metadata_EQ)) {
1089 Arg->claim();
1090 BinaryMetadataFeatures |=
1091 parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
1092 } else {
1093 Arg->claim();
1094 BinaryMetadataFeatures &=
1095 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);
1096 }
1097 }
1098
1099 // Parse -fsanitize-metadata-ignorelist option if enabled.
1100 if (BinaryMetadataFeatures) {
1102 D, Args, BinaryMetadataIgnorelistFiles,
1103 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
1104 OptSpecifier(), // Cannot clear ignore list, only append.
1105 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
1106 DiagnoseErrors);
1107 }
1108
1109 SharedRuntime = Args.hasFlag(
1110 options::OPT_shared_libsan, options::OPT_static_libsan,
1111 TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
1112 TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
1113 if (!SharedRuntime && TC.getTriple().isOSWindows()) {
1114 Arg *A =
1115 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
1116 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
1117 << A->getSpelling() << TC.getTriple().str();
1118 }
1119
1120 ImplicitCfiRuntime = TC.getTriple().isAndroid();
1121
1122 if (AllAddedKinds & SanitizerKind::Address) {
1123 NeedPIE |= TC.getTriple().isOSFuchsia();
1124 if (Arg *A =
1125 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
1126 StringRef S = A->getValue();
1127 // Legal values are 0 and 1, 2, but in future we may add more levels.
1128 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
1129 AsanFieldPadding > 2) &&
1130 DiagnoseErrors) {
1131 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1132 }
1133 }
1134
1135 if (Arg *WindowsDebugRTArg =
1136 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
1137 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
1138 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
1139 switch (WindowsDebugRTArg->getOption().getID()) {
1140 case options::OPT__SLASH_MTd:
1141 case options::OPT__SLASH_MDd:
1142 case options::OPT__SLASH_LDd:
1143 if (DiagnoseErrors) {
1144 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1145 << WindowsDebugRTArg->getAsString(Args)
1146 << lastArgumentForMask(D, Args, SanitizerKind::Address);
1147 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1148 }
1149 }
1150 }
1151
1152 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1153 options::OPT_fno_sanitize_stable_abi, false);
1154
1155 AsanPoisonCustomArrayCookie = Args.hasFlag(
1156 options::OPT_fsanitize_address_poison_custom_array_cookie,
1157 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1158 AsanPoisonCustomArrayCookie);
1159
1160 AsanOutlineInstrumentation =
1161 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1162 options::OPT_fno_sanitize_address_outline_instrumentation,
1163 AsanOutlineInstrumentation);
1164
1165 AsanGlobalsDeadStripping = Args.hasFlag(
1166 options::OPT_fsanitize_address_globals_dead_stripping,
1167 options::OPT_fno_sanitize_address_globals_dead_stripping, true);
1168
1169 // Enable ODR indicators which allow better handling of mixed instrumented
1170 // and uninstrumented globals. Disable them for Windows where weak odr
1171 // indicators (.weak.__odr_asan_gen*) may cause multiple definition linker
1172 // errors in the absence of -lldmingw.
1173 AsanUseOdrIndicator =
1174 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1175 options::OPT_fno_sanitize_address_use_odr_indicator,
1176 !TC.getTriple().isOSWindows());
1177
1178 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1179 AsanInvalidPointerCmp = true;
1180 }
1181
1182 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1183 AsanInvalidPointerSub = true;
1184 }
1185
1186 if (TC.getTriple().isOSDarwin() &&
1187 (Args.hasArg(options::OPT_mkernel) ||
1188 Args.hasArg(options::OPT_fapple_kext))) {
1189 AsanDtorKind = llvm::AsanDtorKind::None;
1190 }
1191
1192 if (const auto *Arg =
1193 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1194 auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
1195 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1196 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1197 << Arg->getSpelling() << Arg->getValue();
1198 }
1199 AsanDtorKind = parsedAsanDtorKind;
1200 }
1201
1202 if (const auto *Arg = Args.getLastArg(
1203 options::OPT_sanitize_address_use_after_return_EQ)) {
1204 auto parsedAsanUseAfterReturn =
1206 if (parsedAsanUseAfterReturn ==
1207 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1208 DiagnoseErrors) {
1209 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
1210 << Arg->getSpelling() << Arg->getValue();
1211 }
1212 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1213 }
1214
1215 } else {
1216 // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
1217 SanitizerMask DetectInvalidPointerPairs =
1218 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1219 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1220 DiagnoseErrors) {
1221 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1222 << lastArgumentForMask(D, Args,
1223 SanitizerKind::PointerCompare |
1224 SanitizerKind::PointerSubtract)
1225 << "-fsanitize=address";
1226 }
1227 }
1228
1229 if (AllAddedKinds & (SanitizerKind::Address | SanitizerKind::KernelAddress)) {
1230 AsanUseAfterScope = Args.hasFlag(
1231 options::OPT_fsanitize_address_use_after_scope,
1232 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1233 } else {
1234 AsanUseAfterScope = false;
1235 }
1236
1237 if (AllAddedKinds & SanitizerKind::HWAddress) {
1238 if (Arg *HwasanAbiArg =
1239 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1240 HwasanAbi = HwasanAbiArg->getValue();
1241 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&
1242 DiagnoseErrors)
1243 D.Diag(clang::diag::err_drv_invalid_value)
1244 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1245 } else {
1246 HwasanAbi = "interceptor";
1247 }
1248 if (TC.getTriple().getArch() == llvm::Triple::x86_64)
1249 HwasanUseAliases = Args.hasFlag(
1250 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1251 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1252 HwasanUseAliases);
1253 }
1254
1255 if (AllAddedKinds & SanitizerKind::SafeStack) {
1256 // SafeStack runtime is built into the system on Android and Fuchsia.
1257 SafeStackRuntime =
1258 !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
1259 }
1260
1261 if (AllAddedKinds & SanitizerKind::AllocToken) {
1262 AllocTokenFastABI = Args.hasFlag(
1263 options::OPT_fsanitize_alloc_token_fast_abi,
1264 options::OPT_fno_sanitize_alloc_token_fast_abi, AllocTokenFastABI);
1265 AllocTokenExtended = Args.hasFlag(
1266 options::OPT_fsanitize_alloc_token_extended,
1267 options::OPT_fno_sanitize_alloc_token_extended, AllocTokenExtended);
1268 }
1269
1270 if (AllAddedKinds & SanitizerKind::Type) {
1271 TysanOutlineInstrumentation =
1272 Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,
1273 options::OPT_fno_sanitize_type_outline_instrumentation,
1274 TysanOutlineInstrumentation);
1275 }
1276
1277 LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
1278 options::OPT_fno_sanitize_link_runtime,
1279 !Args.hasArg(options::OPT_r));
1280
1281 // Parse -link-cxx-sanitizer flag.
1282 LinkCXXRuntimes = D.CCCIsCXX();
1283 LinkCXXRuntimes =
1284 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1285 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1286
1287 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1288 options::OPT_fmemory_profile_EQ,
1289 options::OPT_fno_memory_profile, false);
1290
1291 // Finally, initialize the set of available and recoverable sanitizers.
1292 Sanitizers.Mask |= Kinds;
1293 RecoverableSanitizers.Mask |= RecoverableKinds;
1294 TrapSanitizers.Mask |= TrappingKinds;
1295 assert(!(RecoverableKinds & TrappingKinds) &&
1296 "Overlap between recoverable and trapping sanitizers");
1297
1298 MergeHandlers.Mask |= MergeKinds;
1299
1300 AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;
1301 SuppressUBSanFeature.Mask |= IgnoreForUbsanFeature;
1302
1303 // Zero out SkipHotCutoffs for unused sanitizers
1304 SkipHotCutoffs.clear(~Sanitizers.Mask);
1305}
1306
1307static std::string toString(const clang::SanitizerSet &Sanitizers) {
1308 std::string Res;
1309#define SANITIZER(NAME, ID) \
1310 if (Sanitizers.has(SanitizerKind::ID)) { \
1311 if (!Res.empty()) \
1312 Res += ","; \
1313 Res += NAME; \
1314 }
1315#include "clang/Basic/Sanitizers.def"
1316 return Res;
1317}
1318
1319static std::string toString(const clang::SanitizerMaskCutoffs &Cutoffs) {
1321 serializeSanitizerMaskCutoffs(Cutoffs, Res);
1322 return llvm::join(Res, ",");
1323}
1324
1325static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers) {
1326 std::string Res;
1327#define SANITIZER(NAME, ID) \
1328 if (Sanitizers.has(SanitizerKind::ID)) { \
1329 if (!Res.empty()) \
1330 Res += ","; \
1331 Res += NAME; \
1332 }
1333#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID##Group)
1334#include "clang/Basic/Sanitizers.def"
1335 return Res;
1336}
1337
1338static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1339 llvm::opt::ArgStringList &CmdArgs,
1340 const char *SCLOptFlag,
1341 const std::vector<std::string> &SCLFiles) {
1342 for (const auto &SCLPath : SCLFiles) {
1343 SmallString<64> SCLOpt(SCLOptFlag);
1344 SCLOpt += SCLPath;
1345 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1346 }
1347}
1348
1349static void addIncludeLinkerOption(const ToolChain &TC,
1350 const llvm::opt::ArgList &Args,
1351 llvm::opt::ArgStringList &CmdArgs,
1352 StringRef SymbolName) {
1353 SmallString<64> LinkerOptionFlag;
1354 LinkerOptionFlag = "--linker-option=/include:";
1355 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1356 // Win32 mangles C function names with a '_' prefix.
1357 LinkerOptionFlag += '_';
1358 }
1359 LinkerOptionFlag += SymbolName;
1360 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1361}
1362
1363static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1364 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1365 ++Start) {
1366 auto It = std::find(Start, End, StringRef("+mte"));
1367 if (It == End)
1368 break;
1369 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1370 return true;
1371 Start = It;
1372 }
1373 return false;
1374}
1375
1376void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1377 llvm::opt::ArgStringList &CmdArgs,
1378 types::ID InputType) const {
1379 // NVPTX doesn't currently support sanitizers. Bailing out here means
1380 // that e.g. -fsanitize=address applies only to host code, which is what we
1381 // want for now.
1382 if (TC.getTriple().isNVPTX())
1383 return;
1384 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1385 bool GPUSanitize = false;
1386 if (TC.getTriple().isAMDGPU()) {
1387 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1388 true))
1389 return;
1390 GPUSanitize = true;
1391 }
1392
1393 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1394 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1395 // sanitizers.
1396 std::pair<int, const char *> CoverageFlags[] = {
1397 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1398 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1399 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1400 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1401 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1402 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1403 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1404 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1405 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1406 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1407 std::make_pair(CoverageTracePCEntryExit,
1408 "-fsanitize-coverage-trace-pc-entry-exit"),
1409 std::make_pair(CoverageTracePCGuard,
1410 "-fsanitize-coverage-trace-pc-guard"),
1411 std::make_pair(CoverageInline8bitCounters,
1412 "-fsanitize-coverage-inline-8bit-counters"),
1413 std::make_pair(CoverageInlineBoolFlag,
1414 "-fsanitize-coverage-inline-bool-flag"),
1415 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1416 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1417 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1418 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1419 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1420 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1421 for (auto F : CoverageFlags) {
1422 if (CoverageFeatures & F.first)
1423 CmdArgs.push_back(F.second);
1424 }
1426 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1427 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1428 CoverageIgnorelistFiles);
1429
1430 if (CoverageStackDepthCallbackMin)
1431 CmdArgs.push_back(
1432 Args.MakeArgString("-fsanitize-coverage-stack-depth-callback-min=" +
1433 Twine(CoverageStackDepthCallbackMin)));
1434
1435 if (!GPUSanitize) {
1436 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1437 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1438 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1439 std::make_pair(BinaryMetadataCovered, "covered"),
1440 std::make_pair(BinaryMetadataAtomics, "atomics"),
1441 std::make_pair(BinaryMetadataUAR, "uar")};
1442 for (const auto &F : BinaryMetadataFlags) {
1443 if (BinaryMetadataFeatures & F.first)
1444 CmdArgs.push_back(
1445 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1446 }
1447 addSpecialCaseListOpt(Args, CmdArgs,
1448 "-fexperimental-sanitize-metadata-ignorelist=",
1449 BinaryMetadataIgnorelistFiles);
1450 }
1451
1452 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
1453 Args.hasFlag(options::OPT_frtlib_defaultlib,
1454 options::OPT_fno_rtlib_defaultlib, true)) {
1455 // Instruct the code generator to embed linker directives in the object file
1456 // that cause the required runtime libraries to be linked.
1457 CmdArgs.push_back(
1458 Args.MakeArgString("--dependent-lib=" +
1459 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1460 if (types::isCXX(InputType))
1461 CmdArgs.push_back(Args.MakeArgString(
1462 "--dependent-lib=" +
1463 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1464 }
1465 if (TC.getTriple().isOSWindows() && needsStatsRt() &&
1466 Args.hasFlag(options::OPT_frtlib_defaultlib,
1467 options::OPT_fno_rtlib_defaultlib, true)) {
1468 CmdArgs.push_back(Args.MakeArgString(
1469 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1470
1471 // The main executable must export the stats runtime.
1472 // FIXME: Only exporting from the main executable (e.g. based on whether the
1473 // translation unit defines main()) would save a little space, but having
1474 // multiple copies of the runtime shouldn't hurt.
1475 CmdArgs.push_back(Args.MakeArgString(
1476 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1477 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1478 }
1479
1480 if (Sanitizers.empty())
1481 return;
1482 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1483
1484 if (!SuppressUBSanFeature.empty())
1485 CmdArgs.push_back(
1486 Args.MakeArgString("-fsanitize-ignore-for-ubsan-feature=" +
1487 toString(SuppressUBSanFeature)));
1488
1489 if (!RecoverableSanitizers.empty())
1490 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1491 toString(RecoverableSanitizers)));
1492
1493 if (!TrapSanitizers.empty())
1494 CmdArgs.push_back(
1495 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1496
1497 if (!MergeHandlers.empty())
1498 CmdArgs.push_back(
1499 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
1500
1501 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);
1502 if (!SkipHotCutoffsStr.empty())
1503 CmdArgs.push_back(
1504 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1505
1506 if (!AnnotateDebugInfo.empty())
1507 CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +
1508 toString(AnnotateDebugInfo)));
1509
1510 Args.AddLastArg(CmdArgs, options::OPT_fsanitize_debug_trap_reasons_EQ);
1511
1512 addSpecialCaseListOpt(Args, CmdArgs,
1513 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1514 addSpecialCaseListOpt(Args, CmdArgs,
1515 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1516
1517 if (OverflowPatternExclusions)
1518 Args.AddAllArgs(
1519 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1520
1521 if (MsanTrackOrigins)
1522 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1523 Twine(MsanTrackOrigins)));
1524
1525 if (MsanUseAfterDtor)
1526 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1527
1528 if (!MsanParamRetval)
1529 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1530
1531 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1532 if (!TsanMemoryAccess) {
1533 CmdArgs.push_back("-mllvm");
1534 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1535 CmdArgs.push_back("-mllvm");
1536 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1537 }
1538 if (!TsanFuncEntryExit) {
1539 CmdArgs.push_back("-mllvm");
1540 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1541 }
1542 if (!TsanAtomics) {
1543 CmdArgs.push_back("-mllvm");
1544 CmdArgs.push_back("-tsan-instrument-atomics=0");
1545 }
1546
1547 if (HwasanUseAliases) {
1548 CmdArgs.push_back("-mllvm");
1549 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1550 }
1551
1552 if (CfiCrossDso)
1553 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1554
1555 if (CfiICallGeneralizePointers)
1556 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1557
1558 if (CfiICallNormalizeIntegers)
1559 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1560
1561 if (KcfiArity) {
1562 if (!TC.getTriple().isOSLinux() || !TC.getTriple().isArch64Bit()) {
1563 TC.getDriver().Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)
1564 << TC.getTriple().str();
1565 }
1566 CmdArgs.push_back("-fsanitize-kcfi-arity");
1567 }
1568
1569 if (CfiCanonicalJumpTables)
1570 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1571
1572 if (Stats)
1573 CmdArgs.push_back("-fsanitize-stats");
1574
1575 if (MinimalRuntime)
1576 CmdArgs.push_back("-fsanitize-minimal-runtime");
1577
1578 if (TrapLoop)
1579 CmdArgs.push_back("-fsanitize-trap-loop");
1580
1581 if (HandlerPreserveAllRegs)
1582 CmdArgs.push_back("-fsanitize-handler-preserve-all-regs");
1583
1584 if (AsanFieldPadding)
1585 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1586 Twine(AsanFieldPadding)));
1587
1588 if (AsanUseAfterScope)
1589 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1590
1591 if (AsanPoisonCustomArrayCookie)
1592 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1593
1594 if (AsanGlobalsDeadStripping)
1595 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1596
1597 if (!AsanUseOdrIndicator)
1598 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1599
1600 if (AsanInvalidPointerCmp) {
1601 CmdArgs.push_back("-mllvm");
1602 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1603 }
1604
1605 if (AsanInvalidPointerSub) {
1606 CmdArgs.push_back("-mllvm");
1607 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1608 }
1609
1610 if (AsanOutlineInstrumentation) {
1611 CmdArgs.push_back("-mllvm");
1612 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1613 }
1614
1615 if (!TysanOutlineInstrumentation) {
1616 CmdArgs.push_back("-mllvm");
1617 CmdArgs.push_back("-tysan-outline-instrumentation=false");
1618 }
1619
1620 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1621 // inlining shadow memory poisoning. While this is a big performance burden
1622 // for now it allows full abstraction from implementation details.
1623 if (StableABI) {
1624 CmdArgs.push_back("-mllvm");
1625 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1626 CmdArgs.push_back("-mllvm");
1627 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1628 CmdArgs.push_back("-mllvm");
1629 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1630 }
1631
1632 // Only pass the option to the frontend if the user requested,
1633 // otherwise the frontend will just use the codegen default.
1634 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1635 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1636 AsanDtorKindToString(AsanDtorKind)));
1637 }
1638
1639 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1640 CmdArgs.push_back(Args.MakeArgString(
1641 "-fsanitize-address-use-after-return=" +
1642 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1643 }
1644
1645 if (!HwasanAbi.empty()) {
1646 CmdArgs.push_back("-default-function-attr");
1647 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1648 }
1649
1650 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1651 CmdArgs.push_back("-target-feature");
1652 CmdArgs.push_back("+tagged-globals");
1653 }
1654
1655 // MSan: Workaround for PR16386.
1656 // ASan: This is mainly to help LSan with cases such as
1657 // https://github.com/google/sanitizers/issues/373
1658 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1659 // affect compilation.
1660 if (Sanitizers.has(SanitizerKind::Memory) ||
1661 Sanitizers.has(SanitizerKind::Address))
1662 CmdArgs.push_back("-fno-assume-sane-operator-new");
1663
1664 // Flags for -fsanitize=alloc-token.
1665 if (AllocTokenFastABI)
1666 CmdArgs.push_back("-fsanitize-alloc-token-fast-abi");
1667 if (AllocTokenExtended)
1668 CmdArgs.push_back("-fsanitize-alloc-token-extended");
1669
1670 // libFuzzer wants to intercept calls to certain library functions, so the
1671 // following -fno-builtin-* flags force the compiler to emit interposable
1672 // libcalls to these functions. Other sanitizers effectively do the same thing
1673 // by marking all library call sites with NoBuiltin attribute in their LLVM
1674 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1675 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1676 CmdArgs.push_back("-fno-builtin-bcmp");
1677 CmdArgs.push_back("-fno-builtin-memcmp");
1678 CmdArgs.push_back("-fno-builtin-strncmp");
1679 CmdArgs.push_back("-fno-builtin-strcmp");
1680 CmdArgs.push_back("-fno-builtin-strncasecmp");
1681 CmdArgs.push_back("-fno-builtin-strcasecmp");
1682 CmdArgs.push_back("-fno-builtin-strstr");
1683 CmdArgs.push_back("-fno-builtin-strcasestr");
1684 CmdArgs.push_back("-fno-builtin-memmem");
1685 }
1686
1687 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1688 // enabled.
1689 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1690 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1691 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1692 << lastArgumentForMask(TC.getDriver(), Args,
1693 Sanitizers.Mask & CFIClasses)
1694 << "-fvisibility=";
1695 }
1696
1697 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1698 !hasTargetFeatureMTE(CmdArgs))
1699 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1700}
1701
1702SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1703 bool DiagnoseErrors) {
1704 assert(
1705 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1706 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1707 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1708 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1709 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1710 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1711 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1712 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
1713 A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
1714 A->getOption().matches(
1715 options::OPT_fno_sanitize_annotate_debug_info_EQ) ||
1716 A->getOption().matches(
1717 options::OPT_fsanitize_ignore_for_ubsan_feature_EQ)) &&
1718 "Invalid argument in parseArgValues!");
1719 SanitizerMask Kinds;
1720 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1721 const char *Value = A->getValue(i);
1722 SanitizerMask Kind;
1723 // Special case: don't accept -fsanitize=all.
1724 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1725 0 == strcmp("all", Value))
1726 Kind = SanitizerMask();
1727 else
1728 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1729
1730 if (Kind)
1731 Kinds |= Kind;
1732 else if (DiagnoseErrors)
1733 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1734 << A->getSpelling() << Value;
1735 }
1736 return Kinds;
1737}
1738
1739void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,
1740 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs) {
1741 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1742 "Invalid argument in parseArgCutoffs!");
1743 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1744 const char *Value = A->getValue(i);
1745
1746 // We don't check the value of Cutoffs[i]: it's legal to specify
1747 // a cutoff of 0.
1748 if (!parseSanitizerWeightedValue(Value, /*AllowGroups=*/true, Cutoffs) &&
1749 DiagnoseErrors)
1750 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1751 << A->getSpelling() << Value;
1752 }
1753}
1754
1756 const llvm::opt::Arg *A,
1757 bool DiagnoseErrors) {
1758 int Exclusions = 0;
1759 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1760 const char *Value = A->getValue(i);
1761 int E =
1762 llvm::StringSwitch<int>(Value)
1763 .Case("none", LangOptionsBase::None)
1764 .Case("all", LangOptionsBase::All)
1765 .Case("add-unsigned-overflow-test",
1767 .Case("add-signed-overflow-test",
1769 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
1770 .Case("unsigned-post-decr-while", LangOptionsBase::PostDecrInWhile)
1771 .Default(0);
1772 if (E == 0)
1773 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1774 << A->getSpelling() << Value;
1775 Exclusions |= E;
1776 }
1777 return Exclusions;
1778}
1779
1780int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1781 bool DiagnoseErrors) {
1782 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1783 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1784 int Features = 0;
1785 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1786 const char *Value = A->getValue(i);
1787 int F = llvm::StringSwitch<int>(Value)
1788 .Case("func", CoverageFunc)
1789 .Case("bb", CoverageBB)
1790 .Case("edge", CoverageEdge)
1791 .Case("indirect-calls", CoverageIndirCall)
1792 .Case("trace-bb", CoverageTraceBB)
1793 .Case("trace-cmp", CoverageTraceCmp)
1794 .Case("trace-div", CoverageTraceDiv)
1795 .Case("trace-gep", CoverageTraceGep)
1796 .Case("8bit-counters", Coverage8bitCounters)
1797 .Case("trace-pc", CoverageTracePC)
1798 .Case("trace-pc-entry-exit", CoverageTracePCEntryExit)
1799 .Case("trace-pc-guard", CoverageTracePCGuard)
1800 .Case("no-prune", CoverageNoPrune)
1801 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1802 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1803 .Case("pc-table", CoveragePCTable)
1804 .Case("stack-depth", CoverageStackDepth)
1805 .Case("trace-loads", CoverageTraceLoads)
1806 .Case("trace-stores", CoverageTraceStores)
1807 .Case("control-flow", CoverageControlFlow)
1808 .Default(0);
1809 if (F == 0 && DiagnoseErrors)
1810 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1811 << A->getSpelling() << Value;
1812 Features |= F;
1813 }
1814 return Features;
1815}
1816
1817int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1818 bool DiagnoseErrors) {
1819 assert(
1820 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1821 A->getOption().matches(
1822 options::OPT_fno_experimental_sanitize_metadata_EQ));
1823 int Features = 0;
1824 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1825 const char *Value = A->getValue(i);
1826 int F = llvm::StringSwitch<int>(Value)
1827 .Case("covered", BinaryMetadataCovered)
1828 .Case("atomics", BinaryMetadataAtomics)
1829 .Case("uar", BinaryMetadataUAR)
1830 .Case("all", ~0)
1831 .Default(0);
1832 if (F == 0 && DiagnoseErrors)
1833 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1834 << A->getSpelling() << Value;
1835 Features |= F;
1836 }
1837 return Features;
1838}
1839
1840std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1841 SanitizerMask Mask) {
1842 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1843 E = Args.rend();
1844 I != E; ++I) {
1845 const auto *Arg = *I;
1846 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1847 SanitizerMask AddKinds =
1848 expandSanitizerGroups(parseArgValues(D, Arg, false));
1849 if (AddKinds & Mask)
1850 return describeSanitizeArg(Arg, Mask);
1851 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1852 SanitizerMask RemoveKinds =
1853 expandSanitizerGroups(parseArgValues(D, Arg, false));
1854 Mask &= ~RemoveKinds;
1855 }
1856 }
1857 llvm_unreachable("arg list didn't provide expected value");
1858}
1859
1860std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1861 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1862 "Invalid argument in describeSanitizerArg!");
1863
1864 std::string Sanitizers;
1865 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1867 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1868 Mask) {
1869 if (!Sanitizers.empty())
1870 Sanitizers += ",";
1871 Sanitizers += A->getValue(i);
1872 }
1873 }
1874
1875 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1876 return "-fsanitize=" + Sanitizers;
1877}
static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, std::vector< std::string > &IgnorelistFiles, bool DiagnoseErrors)
static std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask)
Produce an argument string from argument A, which shows how it provides a value in Mask.
static SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)
static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers and sanitizer groups in Sanitizers se...
static SanitizerMask parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors, SanitizerMask Default, SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID, int OptOutID)
static void addIncludeLinkerOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, StringRef SymbolName)
static bool isExecuteOnlyTarget(const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Return true if an execute-only target disallows data access to code sections.
static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs)
BinaryMetadataFeature
@ BinaryMetadataUAR
@ BinaryMetadataCovered
@ BinaryMetadataAtomics
static const SanitizerMask SupportsCoverage
static const SanitizerMask CFIClasses
static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid components.
static const SanitizerMask TrappingSupported
static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any invalid components.
static const SanitizerMask NeedsUnwindTables
static const SanitizerMask MergeDefault
static const SanitizerMask AnnotateDebugInfoDefault
static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *SCLOptFlag, const std::vector< std::string > &SCLFiles)
static const SanitizerMask NotAllowedWithMinimalRuntime
static const SanitizerMask AlwaysRecoverable
static std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, SanitizerMask Mask)
Produce an argument string from ArgList Args, which shows how it provides some sanitizer kind from Ma...
static SanitizerMaskCutoffs parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static const SanitizerMask NeedsUbsanCxxRt
static const SanitizerMask TrappingDefault
static const SanitizerMask CompatibleWithMinimalRuntime
static const SanitizerMask Unrecoverable
static const SanitizerMask RecoverableByDefault
static void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs)
Parse a -fsanitize=<sanitizer1>=<value1>... or -fno-sanitize= argument's values, diagnosing any inval...
static const SanitizerMask NeedsLTO
static SanitizerMask setGroupBits(SanitizerMask Kinds)
Sets group bits for every group that has at least one representative already enabled in Kinds.
static const SanitizerMask NeedsUbsanRt
static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.
static void validateSpecialCaseListFormat(const Driver &D, std::vector< std::string > &SCLFiles, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
static const SanitizerMask NotAllowedWithTrap
static void parseSpecialCaseListArg(const Driver &D, const llvm::opt::ArgList &Args, std::vector< std::string > &SCLFiles, llvm::opt::OptSpecifier SCLOptionID, llvm::opt::OptSpecifier NoSCLOptionID, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)
Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, diagnosing any invalid file ...
static int parseOverflowPatternExclusionValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)
Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing any invalid values.
static const SanitizerMask NotAllowedWithExecuteOnly
CoverageFeature
@ CoverageTracePCGuard
@ CoverageTraceLoads
@ CoverageTracePC
@ CoverageFunc
@ Coverage8bitCounters
@ CoverageTraceCmp
@ CoverageBB
@ CoverageTraceDiv
@ CoverageInlineBoolFlag
@ CoverageTraceStores
@ CoverageTraceGep
@ CoverageTracePCEntryExit
@ CoverageStackDepth
@ CoverageControlFlow
@ CoverageNoPrune
@ CoveragePCTable
@ CoverageIndirCall
@ CoverageInline8bitCounters
@ CoverageTraceBB
@ CoverageEdge
Defines the clang::SanitizerKind enum.
@ None
Don't exclude any overflow patterns from sanitizers.
@ AddUnsignedOverflowTest
if (a + b < a)
@ All
Exclude all overflow patterns (below)
@ AddSignedOverflowTest
if (a + b < a)
@ PostDecrInWhile
while (count–)
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition Driver.h:99
DiagnosticBuilder Diag(unsigned DiagID) const
Definition Driver.h:169
std::string ResourceDir
The path to the compiler resource directory.
Definition Driver.h:189
llvm::vfs::FileSystem & getVFS() const
Definition Driver.h:421
bool isUsingLTO() const
Returns true if we are performing any kind of LTO.
Definition Driver.h:744
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
Definition Driver.h:232
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, bool DiagnoseErrors=true, bool DiagnoseBoundArchErrors=true, StringRef BoundArch="", Action::OffloadKind DeviceOffloadKind=Action::OFK_None)
Parses the sanitizer arguments from an argument list.
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
ToolChain - Access to tools for a single platform.
Definition ToolChain.h:93
const Driver & getDriver() const
Definition ToolChain.h:283
RTTIMode getRTTIMode() const
Definition ToolChain.h:366
virtual SanitizerMask getSupportedSanitizers(StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const
Return sanitizers which are available in this toolchain.
virtual StringRef getSanitizerRequirement(SanitizerMask Kinds, StringRef BoundArch) const
Returns the feature requirement for a sanitizer on a specific arch for diagnostic purposes.
Definition ToolChain.h:355
const llvm::opt::Arg * getRTTIArg() const
Definition ToolChain.h:363
const llvm::Triple & getTriple() const
Definition ToolChain.h:285
std::string getCompilerRTBasename(const llvm::opt::ArgList &Args, StringRef Component, FileType Type=ToolChain::FT_Static) const
virtual SanitizerMask getDefaultSanitizers() const
Return sanitizers which are enabled by default.
Definition ToolChain.h:872
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
Definition Types.cpp:262
The JSON file list parser is used to communicate input to InstallAPI.
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)
bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups, SanitizerMaskCutoffs &Cutoffs)
Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or -fno-sanitize= value lis...
@ Incompatible
Incompatible - We reject this conversion outright, it is invalid to represent it in the AST.
Definition Sema.h:787
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl< std::string > &Values)
Serialize a SanitizerMaskCutoffs into command line arguments.
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind)
llvm::AsanDetectStackUseAfterReturnMode AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr)
StringRef AsanDetectStackUseAfterReturnModeToString(llvm::AsanDetectStackUseAfterReturnMode mode)
SanitizerMask Mask
Bitmask of enabled sanitizers.
Definition Sanitizers.h:201