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