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