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