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 (AllAddedKinds & 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 // Finally, initialize the set of available and recoverable sanitizers.
1349 Sanitizers.Mask |= Kinds;
1350 RecoverableSanitizers.Mask |= RecoverableKinds;
1351 TrapSanitizers.Mask |= TrappingKinds;
1352 assert(!(RecoverableKinds & TrappingKinds) &&
1353 "Overlap between recoverable and trapping sanitizers");
1354
1355 MergeHandlers.Mask |= MergeKinds;
1356
1357 AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;
1358 SuppressUBSanFeature.Mask |= IgnoreForUbsanFeature;
1359
1360 // Zero out SkipHotCutoffs for unused sanitizers
1361 SkipHotCutoffs.clear(~Sanitizers.Mask);
1362}
1363
1364static std::string toString(const clang::SanitizerSet &Sanitizers) {
1365 std::string Res;
1366#define SANITIZER(NAME, ID) \
1367 if (Sanitizers.has(SanitizerKind::ID)) { \
1368 if (!Res.empty()) \
1369 Res += ","; \
1370 Res += NAME; \
1371 }
1372#include "clang/Basic/Sanitizers.def"
1373 return Res;
1374}
1375
1376static std::string toString(const clang::SanitizerMaskCutoffs &Cutoffs) {
1378 serializeSanitizerMaskCutoffs(Cutoffs, Res);
1379 return llvm::join(Res, ",");
1380}
1381
1382static std::string toStringWithGroups(const clang::SanitizerSet &Sanitizers) {
1383 std::string Res;
1384#define SANITIZER(NAME, ID) \
1385 if (Sanitizers.has(SanitizerKind::ID)) { \
1386 if (!Res.empty()) \
1387 Res += ","; \
1388 Res += NAME; \
1389 }
1390#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID##Group)
1391#include "clang/Basic/Sanitizers.def"
1392 return Res;
1393}
1394
1395static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
1396 llvm::opt::ArgStringList &CmdArgs,
1397 const char *SCLOptFlag,
1398 const std::vector<std::string> &SCLFiles) {
1399 for (const auto &SCLPath : SCLFiles) {
1400 SmallString<64> SCLOpt(SCLOptFlag);
1401 SCLOpt += SCLPath;
1402 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1403 }
1404}
1405
1406static void addIncludeLinkerOption(const ToolChain &TC,
1407 const llvm::opt::ArgList &Args,
1408 llvm::opt::ArgStringList &CmdArgs,
1409 StringRef SymbolName) {
1410 SmallString<64> LinkerOptionFlag;
1411 LinkerOptionFlag = "--linker-option=/include:";
1412 if (TC.getTriple().getArch() == llvm::Triple::x86) {
1413 // Win32 mangles C function names with a '_' prefix.
1414 LinkerOptionFlag += '_';
1415 }
1416 LinkerOptionFlag += SymbolName;
1417 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1418}
1419
1420static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
1421 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1422 ++Start) {
1423 auto It = std::find(Start, End, StringRef("+mte"));
1424 if (It == End)
1425 break;
1426 if (It > Start && *std::prev(It) == StringRef("-target-feature"))
1427 return true;
1428 Start = It;
1429 }
1430 return false;
1431}
1432
1433void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
1434 llvm::opt::ArgStringList &CmdArgs,
1435 types::ID InputType) const {
1436 // NVPTX doesn't currently support sanitizers. Bailing out here means
1437 // that e.g. -fsanitize=address applies only to host code, which is what we
1438 // want for now.
1439 if (TC.getTriple().isNVPTX())
1440 return;
1441 // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
1442 bool GPUSanitize = false;
1443 if (TC.getTriple().isAMDGPU()) {
1444 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1445 true))
1446 return;
1447 GPUSanitize = true;
1448 }
1449
1450 // Translate available CoverageFeatures to corresponding clang-cc1 flags.
1451 // Do it even if Sanitizers.empty() since some forms of coverage don't require
1452 // sanitizers.
1453 std::pair<int, const char *> CoverageFlags[] = {
1454 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
1455 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
1456 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
1457 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
1458 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
1459 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
1460 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
1461 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
1462 std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
1463 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
1464 std::make_pair(CoverageTracePCEntryExit,
1465 "-fsanitize-coverage-trace-pc-entry-exit"),
1466 std::make_pair(CoverageTracePCGuard,
1467 "-fsanitize-coverage-trace-pc-guard"),
1468 std::make_pair(CoverageInline8bitCounters,
1469 "-fsanitize-coverage-inline-8bit-counters"),
1470 std::make_pair(CoverageInlineBoolFlag,
1471 "-fsanitize-coverage-inline-bool-flag"),
1472 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
1473 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
1474 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),
1475 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),
1476 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),
1477 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};
1478 for (auto F : CoverageFlags) {
1479 if (CoverageFeatures & F.first)
1480 CmdArgs.push_back(F.second);
1481 }
1483 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1484 addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
1485 CoverageIgnorelistFiles);
1486
1487 if (CoverageStackDepthCallbackMin)
1488 CmdArgs.push_back(
1489 Args.MakeArgString("-fsanitize-coverage-stack-depth-callback-min=" +
1490 Twine(CoverageStackDepthCallbackMin)));
1491
1492 if (!GPUSanitize) {
1493 // Translate available BinaryMetadataFeatures to corresponding clang-cc1
1494 // flags. Does not depend on any other sanitizers. Unsupported on GPUs.
1495 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1496 std::make_pair(BinaryMetadataCovered, "covered"),
1497 std::make_pair(BinaryMetadataAtomics, "atomics"),
1498 std::make_pair(BinaryMetadataUAR, "uar")};
1499 for (const auto &F : BinaryMetadataFlags) {
1500 if (BinaryMetadataFeatures & F.first)
1501 CmdArgs.push_back(
1502 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));
1503 }
1504 addSpecialCaseListOpt(Args, CmdArgs,
1505 "-fexperimental-sanitize-metadata-ignorelist=",
1506 BinaryMetadataIgnorelistFiles);
1507 }
1508
1509 if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
1510 Args.hasFlag(options::OPT_frtlib_defaultlib,
1511 options::OPT_fno_rtlib_defaultlib, true)) {
1512 // Instruct the code generator to embed linker directives in the object file
1513 // that cause the required runtime libraries to be linked.
1514 CmdArgs.push_back(
1515 Args.MakeArgString("--dependent-lib=" +
1516 TC.getCompilerRTBasename(Args, "ubsan_standalone")));
1517 if (types::isCXX(InputType))
1518 CmdArgs.push_back(Args.MakeArgString(
1519 "--dependent-lib=" +
1520 TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
1521 }
1522 if (TC.getTriple().isOSWindows() && needsStatsRt() &&
1523 Args.hasFlag(options::OPT_frtlib_defaultlib,
1524 options::OPT_fno_rtlib_defaultlib, true)) {
1525 CmdArgs.push_back(Args.MakeArgString(
1526 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
1527
1528 // The main executable must export the stats runtime.
1529 // FIXME: Only exporting from the main executable (e.g. based on whether the
1530 // translation unit defines main()) would save a little space, but having
1531 // multiple copies of the runtime shouldn't hurt.
1532 CmdArgs.push_back(Args.MakeArgString(
1533 "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
1534 addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
1535 }
1536
1537 if (Sanitizers.empty())
1538 return;
1539 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
1540
1541 if (!SuppressUBSanFeature.empty())
1542 CmdArgs.push_back(
1543 Args.MakeArgString("-fsanitize-ignore-for-ubsan-feature=" +
1544 toString(SuppressUBSanFeature)));
1545
1546 if (!RecoverableSanitizers.empty())
1547 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
1548 toString(RecoverableSanitizers)));
1549
1550 if (!TrapSanitizers.empty())
1551 CmdArgs.push_back(
1552 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
1553
1554 if (!MergeHandlers.empty())
1555 CmdArgs.push_back(
1556 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));
1557
1558 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);
1559 if (!SkipHotCutoffsStr.empty())
1560 CmdArgs.push_back(
1561 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1562
1563 if (!AnnotateDebugInfo.empty())
1564 CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +
1565 toString(AnnotateDebugInfo)));
1566
1567 Args.AddLastArg(CmdArgs, options::OPT_fsanitize_debug_trap_reasons_EQ);
1568
1569 addSpecialCaseListOpt(Args, CmdArgs,
1570 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1571 addSpecialCaseListOpt(Args, CmdArgs,
1572 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1573
1574 if (OverflowPatternExclusions)
1575 Args.AddAllArgs(
1576 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1577
1578 if (MsanTrackOrigins)
1579 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
1580 Twine(MsanTrackOrigins)));
1581
1582 if (MsanUseAfterDtor)
1583 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");
1584
1585 if (!MsanParamRetval)
1586 CmdArgs.push_back("-fno-sanitize-memory-param-retval");
1587
1588 // FIXME: Pass these parameters as function attributes, not as -llvm flags.
1589 if (!TsanMemoryAccess) {
1590 CmdArgs.push_back("-mllvm");
1591 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
1592 CmdArgs.push_back("-mllvm");
1593 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
1594 }
1595 if (!TsanFuncEntryExit) {
1596 CmdArgs.push_back("-mllvm");
1597 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
1598 }
1599 if (!TsanAtomics) {
1600 CmdArgs.push_back("-mllvm");
1601 CmdArgs.push_back("-tsan-instrument-atomics=0");
1602 }
1603
1604 if (HwasanUseAliases) {
1605 CmdArgs.push_back("-mllvm");
1606 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
1607 }
1608
1609 if (CfiCrossDso)
1610 CmdArgs.push_back("-fsanitize-cfi-cross-dso");
1611
1612 if (CfiICallGeneralizePointers)
1613 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
1614
1615 if (CfiICallNormalizeIntegers)
1616 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1617
1618 if (KcfiArity) {
1619 if (!TC.getTriple().isOSLinux() || !TC.getTriple().isArch64Bit()) {
1620 TC.getDriver().Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)
1621 << TC.getTriple().str();
1622 }
1623 CmdArgs.push_back("-fsanitize-kcfi-arity");
1624 }
1625
1626 if (KcfiHash)
1627 CmdArgs.push_back(Args.MakeArgString("-fsanitize-kcfi-hash=" + *KcfiHash));
1628
1629 if (CfiCanonicalJumpTables)
1630 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
1631
1632 if (Stats)
1633 CmdArgs.push_back("-fsanitize-stats");
1634
1635 if (MinimalRuntime)
1636 CmdArgs.push_back("-fsanitize-minimal-runtime");
1637
1638 if (TrapLoop)
1639 CmdArgs.push_back("-fsanitize-trap-loop");
1640
1641 if (HandlerPreserveAllRegs)
1642 CmdArgs.push_back("-fsanitize-handler-preserve-all-regs");
1643
1644 if (AsanFieldPadding)
1645 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
1646 Twine(AsanFieldPadding)));
1647
1648 if (AsanUseAfterScope)
1649 CmdArgs.push_back("-fsanitize-address-use-after-scope");
1650
1651 if (AsanPoisonCustomArrayCookie)
1652 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
1653
1654 if (AsanGlobalsDeadStripping)
1655 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
1656
1657 if (!AsanUseOdrIndicator)
1658 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");
1659
1660 if (AsanInvalidPointerCmp) {
1661 CmdArgs.push_back("-mllvm");
1662 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");
1663 }
1664
1665 if (AsanInvalidPointerSub) {
1666 CmdArgs.push_back("-mllvm");
1667 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
1668 }
1669
1670 if (AsanOutlineInstrumentation) {
1671 CmdArgs.push_back("-mllvm");
1672 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1673 }
1674
1675 if (!TysanOutlineInstrumentation) {
1676 CmdArgs.push_back("-mllvm");
1677 CmdArgs.push_back("-tysan-outline-instrumentation=false");
1678 }
1679
1680 // When emitting Stable ABI instrumentation, force outlining calls and avoid
1681 // inlining shadow memory poisoning. While this is a big performance burden
1682 // for now it allows full abstraction from implementation details.
1683 if (StableABI) {
1684 CmdArgs.push_back("-mllvm");
1685 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
1686 CmdArgs.push_back("-mllvm");
1687 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");
1688 CmdArgs.push_back("-mllvm");
1689 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");
1690 }
1691
1692 // Only pass the option to the frontend if the user requested,
1693 // otherwise the frontend will just use the codegen default.
1694 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1695 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
1696 AsanDtorKindToString(AsanDtorKind)));
1697 }
1698
1699 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1700 CmdArgs.push_back(Args.MakeArgString(
1701 "-fsanitize-address-use-after-return=" +
1702 AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
1703 }
1704
1705 if (!HwasanAbi.empty()) {
1706 CmdArgs.push_back("-default-function-attr");
1707 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
1708 }
1709
1710 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1711 CmdArgs.push_back("-target-feature");
1712 CmdArgs.push_back("+tagged-globals");
1713 }
1714
1715 // MSan: Workaround for PR16386.
1716 // ASan: This is mainly to help LSan with cases such as
1717 // https://github.com/google/sanitizers/issues/373
1718 // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
1719 // affect compilation.
1720 if (Sanitizers.has(SanitizerKind::Memory) ||
1721 Sanitizers.has(SanitizerKind::Address))
1722 CmdArgs.push_back("-fno-assume-sane-operator-new");
1723
1724 // Flags for -fsanitize=alloc-token.
1725 if (AllocTokenFastABI)
1726 CmdArgs.push_back("-fsanitize-alloc-token-fast-abi");
1727 if (AllocTokenExtended)
1728 CmdArgs.push_back("-fsanitize-alloc-token-extended");
1729
1730 // libFuzzer wants to intercept calls to certain library functions, so the
1731 // following -fno-builtin-* flags force the compiler to emit interposable
1732 // libcalls to these functions. Other sanitizers effectively do the same thing
1733 // by marking all library call sites with NoBuiltin attribute in their LLVM
1734 // pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)
1735 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1736 CmdArgs.push_back("-fno-builtin-bcmp");
1737 CmdArgs.push_back("-fno-builtin-memcmp");
1738 CmdArgs.push_back("-fno-builtin-strncmp");
1739 CmdArgs.push_back("-fno-builtin-strcmp");
1740 CmdArgs.push_back("-fno-builtin-strncasecmp");
1741 CmdArgs.push_back("-fno-builtin-strcasecmp");
1742 CmdArgs.push_back("-fno-builtin-strstr");
1743 CmdArgs.push_back("-fno-builtin-strcasestr");
1744 CmdArgs.push_back("-fno-builtin-memmem");
1745 }
1746
1747 // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
1748 // enabled.
1749 if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&
1750 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1751 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)
1752 << lastArgumentForMask(TC.getDriver(), Args,
1753 Sanitizers.Mask & CFIClasses)
1754 << "-fvisibility=";
1755 }
1756
1757 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1758 !hasTargetFeatureMTE(CmdArgs))
1759 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
1760}
1761
1762SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
1763 bool DiagnoseErrors) {
1764 assert(
1765 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1766 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1767 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1768 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1769 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1770 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1771 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1772 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
1773 A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
1774 A->getOption().matches(
1775 options::OPT_fno_sanitize_annotate_debug_info_EQ) ||
1776 A->getOption().matches(
1777 options::OPT_fsanitize_ignore_for_ubsan_feature_EQ)) &&
1778 "Invalid argument in parseArgValues!");
1779 SanitizerMask Kinds;
1780 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1781 const char *Value = A->getValue(i);
1782 SanitizerMask Kind;
1783 // Special case: don't accept -fsanitize=all.
1784 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1785 0 == strcmp("all", Value))
1786 Kind = SanitizerMask();
1787 else
1788 Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
1789
1790 if (Kind)
1791 Kinds |= Kind;
1792 else if (DiagnoseErrors)
1793 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1794 << A->getSpelling() << Value;
1795 }
1796 return Kinds;
1797}
1798
1799void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A,
1800 bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs) {
1801 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1802 "Invalid argument in parseArgCutoffs!");
1803 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1804 const char *Value = A->getValue(i);
1805
1806 // We don't check the value of Cutoffs[i]: it's legal to specify
1807 // a cutoff of 0.
1808 if (!parseSanitizerWeightedValue(Value, /*AllowGroups=*/true, Cutoffs) &&
1809 DiagnoseErrors)
1810 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1811 << A->getSpelling() << Value;
1812 }
1813}
1814
1816 const llvm::opt::Arg *A,
1817 bool DiagnoseErrors) {
1818 int Exclusions = 0;
1819 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1820 const char *Value = A->getValue(i);
1821 int E =
1822 llvm::StringSwitch<int>(Value)
1823 .Case("none", LangOptionsBase::None)
1824 .Case("all", LangOptionsBase::All)
1825 .Case("add-unsigned-overflow-test",
1827 .Case("add-signed-overflow-test",
1829 .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)
1830 .Case("unsigned-post-decr-while", LangOptionsBase::PostDecrInWhile)
1831 .Default(0);
1832 if (E == 0)
1833 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1834 << A->getSpelling() << Value;
1835 Exclusions |= E;
1836 }
1837 return Exclusions;
1838}
1839
1840int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,
1841 bool DiagnoseErrors) {
1842 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1843 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1844 int Features = 0;
1845 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1846 const char *Value = A->getValue(i);
1847 int F = llvm::StringSwitch<int>(Value)
1848 .Case("func", CoverageFunc)
1849 .Case("bb", CoverageBB)
1850 .Case("edge", CoverageEdge)
1851 .Case("indirect-calls", CoverageIndirCall)
1852 .Case("trace-bb", CoverageTraceBB)
1853 .Case("trace-cmp", CoverageTraceCmp)
1854 .Case("trace-div", CoverageTraceDiv)
1855 .Case("trace-gep", CoverageTraceGep)
1856 .Case("8bit-counters", Coverage8bitCounters)
1857 .Case("trace-pc", CoverageTracePC)
1858 .Case("trace-pc-entry-exit", CoverageTracePCEntryExit)
1859 .Case("trace-pc-guard", CoverageTracePCGuard)
1860 .Case("no-prune", CoverageNoPrune)
1861 .Case("inline-8bit-counters", CoverageInline8bitCounters)
1862 .Case("inline-bool-flag", CoverageInlineBoolFlag)
1863 .Case("pc-table", CoveragePCTable)
1864 .Case("stack-depth", CoverageStackDepth)
1865 .Case("trace-loads", CoverageTraceLoads)
1866 .Case("trace-stores", CoverageTraceStores)
1867 .Case("control-flow", CoverageControlFlow)
1868 .Default(0);
1869 if (F == 0 && DiagnoseErrors)
1870 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1871 << A->getSpelling() << Value;
1872 Features |= F;
1873 }
1874 return Features;
1875}
1876
1877int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
1878 bool DiagnoseErrors) {
1879 assert(
1880 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1881 A->getOption().matches(
1882 options::OPT_fno_experimental_sanitize_metadata_EQ));
1883 int Features = 0;
1884 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1885 const char *Value = A->getValue(i);
1886 int F = llvm::StringSwitch<int>(Value)
1887 .Case("covered", BinaryMetadataCovered)
1888 .Case("atomics", BinaryMetadataAtomics)
1889 .Case("uar", BinaryMetadataUAR)
1890 .Case("all", ~0)
1891 .Default(0);
1892 if (F == 0 && DiagnoseErrors)
1893 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1894 << A->getSpelling() << Value;
1895 Features |= F;
1896 }
1897 return Features;
1898}
1899
1900std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
1901 SanitizerMask Mask) {
1902 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1903 E = Args.rend();
1904 I != E; ++I) {
1905 const auto *Arg = *I;
1906 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1907 SanitizerMask AddKinds =
1908 expandSanitizerGroups(parseArgValues(D, Arg, false));
1909 if (AddKinds & Mask)
1910 return describeSanitizeArg(Arg, Mask);
1911 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1912 SanitizerMask RemoveKinds =
1913 expandSanitizerGroups(parseArgValues(D, Arg, false));
1914 Mask &= ~RemoveKinds;
1915 }
1916 }
1917 llvm_unreachable("arg list didn't provide expected value");
1918}
1919
1920std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
1921 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1922 "Invalid argument in describeSanitizerArg!");
1923
1924 std::string Sanitizers;
1925 for (int i = 0, n = A->getNumValues(); i != n; ++i) {
1927 parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &
1928 Mask) {
1929 if (!Sanitizers.empty())
1930 Sanitizers += ",";
1931 Sanitizers += A->getValue(i);
1932 }
1933 }
1934
1935 assert(!Sanitizers.empty() && "arg didn't provide expected value");
1936 return "-fsanitize=" + Sanitizers;
1937}
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: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:890
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
Definition Types.cpp:262
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:782
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