15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/StringSwitch.h"
18#include "llvm/Support/Path.h"
19#include "llvm/Support/SpecialCaseList.h"
20#include "llvm/Support/VirtualFileSystem.h"
21#include "llvm/TargetParser/AArch64TargetParser.h"
22#include "llvm/TargetParser/RISCVTargetParser.h"
23#include "llvm/TargetParser/TargetParser.h"
24#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
32 SanitizerKind::Undefined | SanitizerKind::Integer |
33 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
34 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
35 SanitizerKind::ObjCCast;
37 SanitizerKind::Vptr | SanitizerKind::CFI;
41 SanitizerKind::Function | SanitizerKind::KCFI;
43 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
44 SanitizerKind::Memory | SanitizerKind::DataFlow |
45 SanitizerKind::NumericalStability;
47 SanitizerKind::Address | SanitizerKind::HWAddress |
48 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
49 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
50 SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
51 SanitizerKind::KernelMemory | SanitizerKind::Leak |
52 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
53 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
54 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
55 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
56 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
57 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
58 SanitizerKind::NumericalStability;
60 SanitizerKind::Undefined | SanitizerKind::Integer |
61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
64 SanitizerKind::Unreachable | SanitizerKind::Return;
66 SanitizerKind::KernelHWAddress |
70 (SanitizerKind::Undefined &
~SanitizerKind::Vptr) | SanitizerKind::Integer |
71 SanitizerKind::Nullability | SanitizerKind::LocalBounds |
72 SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
73 SanitizerKind::ObjCCast;
76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
78 SanitizerKind::CFIUnrelatedCast;
81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
115 bool DiagnoseErrors);
120 bool DiagnoseErrors);
125 const llvm::opt::Arg *A,
126 bool DiagnoseErrors);
131 bool DiagnoseErrors);
138 const llvm::opt::ArgList &Args,
155 const llvm::opt::ArgList &Args) {
158 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
159 options::OPT_mno_execute_only,
false);
163 std::vector<std::string> &SCLFiles,
164 unsigned MalformedSCLErrorDiagID,
165 bool DiagnoseErrors) {
166 if (SCLFiles.empty())
170 std::unique_ptr<llvm::SpecialCaseList> SCL(
171 llvm::SpecialCaseList::create(SCLFiles,
D.getVFS(), BLError));
172 if (!SCL.get() && DiagnoseErrors)
173 D.Diag(MalformedSCLErrorDiagID) << BLError;
177 std::vector<std::string> &IgnorelistFiles,
178 bool DiagnoseErrors) {
182 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
183 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
184 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
185 {
"msan_ignorelist.txt", SanitizerKind::Memory},
186 {
"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
187 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
188 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
189 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
190 {
"ubsan_ignorelist.txt",
191 SanitizerKind::Undefined | SanitizerKind::Integer |
192 SanitizerKind::Nullability |
193 SanitizerKind::FloatDivideByZero}};
195 for (
auto BL : Ignorelists) {
196 if (!(Kinds & BL.Mask))
200 llvm::sys::path::append(
Path,
"share", BL.File);
201 if (
D.getVFS().exists(
Path))
202 IgnorelistFiles.push_back(std::string(
Path));
203 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
206 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) <<
Path;
209 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
216 const llvm::opt::ArgList &Args,
217 std::vector<std::string> &SCLFiles,
218 llvm::opt::OptSpecifier SCLOptionID,
219 llvm::opt::OptSpecifier NoSCLOptionID,
220 unsigned MalformedSCLErrorDiagID,
221 bool DiagnoseErrors) {
222 for (
const auto *Arg : Args) {
224 if (Arg->getOption().matches(SCLOptionID)) {
226 std::string SCLPath = Arg->getValue();
227 if (
D.getVFS().exists(SCLPath)) {
228 SCLFiles.push_back(SCLPath);
229 }
else if (DiagnoseErrors) {
230 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
233 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
245#define SANITIZER(NAME, ID)
246#define SANITIZER_GROUP(NAME, ID, ALIAS) \
247 if (Kinds & SanitizerKind::ID) \
248 Kinds |= SanitizerKind::ID##Group;
249#include "clang/Basic/Sanitizers.def"
254 const llvm::opt::ArgList &Args,
255 bool DiagnoseErrors) {
262 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
263 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
267 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
268 if (InvalidValues && DiagnoseErrors) {
270 S.Mask = InvalidValues;
271 D.Diag(diag::err_drv_unsupported_option_argument)
272 << Arg->getSpelling() <<
toString(S);
275 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
285 return TrappingKinds;
304 return !(Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
305 CfiCrossDso && !ImplicitCfiRuntime;
309 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
310 CfiCrossDso && !ImplicitCfiRuntime;
324 const llvm::opt::ArgList &Args,
325 bool DiagnoseErrors) {
339 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
340 options::OPT_fno_sanitize_cfi_cross_dso,
false);
349 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
350 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
353 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
354 bool RemoveObjectSizeAtO0 =
355 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
357 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
358 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
362 if (RemoveObjectSizeAtO0) {
363 AllRemove |= SanitizerKind::ObjectSize;
367 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
368 D.Diag(diag::warn_drv_object_size_disabled_O0)
369 << Arg->getAsString(Args);
380 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
381 if (DiagnoseErrors) {
383 D.Diag(diag::err_drv_argument_not_allowed_with)
384 << Desc <<
"-fsanitize-trap=undefined";
386 DiagnosedKinds |= KindsToDiagnose;
388 Add &= ~InvalidTrappingKinds;
390 if (MinimalRuntime) {
393 if (DiagnoseErrors) {
395 D.Diag(diag::err_drv_argument_not_allowed_with)
396 << Desc <<
"-fsanitize-minimal-runtime";
398 DiagnosedKinds |= KindsToDiagnose;
400 Add &= ~NotAllowedWithMinimalRuntime;
403 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
404 StringRef CM = A->getValue();
406 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
408 D.Diag(diag::err_drv_argument_only_allowed_with)
409 <<
"-fsanitize=function"
412 DiagnosedKinds |= SanitizerKind::Function;
418 const llvm::Triple &Triple = TC.
getTriple();
422 if (DiagnoseErrors) {
424 D.Diag(diag::err_drv_argument_not_allowed_with)
425 << Desc << Triple.str();
427 DiagnosedKinds |= KindsToDiagnose;
429 Add &= ~NotAllowedWithExecuteOnly;
442 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
444 D.Diag(diag::err_drv_argument_not_allowed_with)
445 <<
"-fsanitize=cfi-mfcall"
446 <<
"-fsanitize-cfi-cross-dso";
448 DiagnosedKinds |= SanitizerKind::CFIMFCall;
451 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
452 if (DiagnoseErrors) {
454 D.Diag(diag::err_drv_unsupported_opt_for_target)
457 DiagnosedKinds |= KindsToDiagnose;
465 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
466 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
467 "RTTI disabled without -fno-rtti option?");
471 D.Diag(diag::err_drv_argument_not_allowed_with)
472 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
477 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
481 AllRemove |= SanitizerKind::Vptr;
489 Add &= ~InvalidTrappingKinds;
490 if (MinimalRuntime) {
491 Add &= ~NotAllowedWithMinimalRuntime;
496 Add &= ~NotAllowedWithExecuteOnly;
501 if (Add & SanitizerKind::UndefinedGroup) {
502 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
503 options::OPT_fstrict_overflow,
false);
504 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
509 if (Add & SanitizerKind::Fuzzer)
510 Add |= SanitizerKind::FuzzerNoLink;
513 if (Add & SanitizerKind::FuzzerNoLink) {
522 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
529 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
530 std::make_pair(SanitizerKind::Address,
531 SanitizerKind::Thread | SanitizerKind::Memory),
532 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
533 std::make_pair(SanitizerKind::Leak,
534 SanitizerKind::Thread | SanitizerKind::Memory),
535 std::make_pair(SanitizerKind::KernelAddress,
536 SanitizerKind::Address | SanitizerKind::Leak |
537 SanitizerKind::Thread | SanitizerKind::Memory),
538 std::make_pair(SanitizerKind::HWAddress,
539 SanitizerKind::Address | SanitizerKind::Thread |
540 SanitizerKind::Memory | SanitizerKind::KernelAddress),
541 std::make_pair(SanitizerKind::Scudo,
542 SanitizerKind::Address | SanitizerKind::HWAddress |
543 SanitizerKind::Leak | SanitizerKind::Thread |
544 SanitizerKind::Memory | SanitizerKind::KernelAddress),
545 std::make_pair(SanitizerKind::SafeStack,
547 : SanitizerKind::Leak) |
548 SanitizerKind::Address | SanitizerKind::HWAddress |
549 SanitizerKind::Thread | SanitizerKind::Memory |
550 SanitizerKind::KernelAddress),
551 std::make_pair(SanitizerKind::KernelHWAddress,
552 SanitizerKind::Address | SanitizerKind::HWAddress |
553 SanitizerKind::Leak | SanitizerKind::Thread |
554 SanitizerKind::Memory | SanitizerKind::KernelAddress |
555 SanitizerKind::SafeStack),
556 std::make_pair(SanitizerKind::KernelMemory,
557 SanitizerKind::Address | SanitizerKind::HWAddress |
558 SanitizerKind::Leak | SanitizerKind::Thread |
559 SanitizerKind::Memory | SanitizerKind::KernelAddress |
560 SanitizerKind::Scudo | SanitizerKind::SafeStack),
561 std::make_pair(SanitizerKind::MemTag,
562 SanitizerKind::Address | SanitizerKind::KernelAddress |
563 SanitizerKind::HWAddress |
564 SanitizerKind::KernelHWAddress),
565 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
571 for (
auto G : IncompatibleGroups) {
573 if ((
Default & Group) && (Kinds & G.second))
586 if ((Kinds &
NeedsLTO) && !
D.isUsingLTO() && DiagnoseErrors) {
587 D.Diag(diag::err_drv_argument_only_allowed_with)
591 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
592 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
593 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
594 D.Diag(diag::err_drv_argument_only_allowed_with)
603 if (~Supported & SanitizerKind::Vptr) {
609 if (KindsToDiagnose) {
611 S.Mask = KindsToDiagnose;
613 D.Diag(diag::err_drv_unsupported_opt_for_target)
615 Kinds &= ~KindsToDiagnose;
620 for (
auto G : IncompatibleGroups) {
625 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
628 Kinds &= ~Incompatible;
641 for (
const auto *Arg : Args) {
642 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
649 SetToDiagnose.
Mask |= KindsToDiagnose;
651 D.Diag(diag::err_drv_unsupported_option_argument)
652 << Arg->getSpelling() <<
toString(SetToDiagnose);
653 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
657 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
664 SetToDiagnose.
Mask |= KindsToDiagnose;
666 D.Diag(diag::err_drv_unsupported_option_argument)
667 << Arg->getSpelling() <<
toString(SetToDiagnose);
668 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
670 RecoverableKinds &= ~expandSanitizerGroups(Remove);
674 RecoverableKinds &= Kinds;
675 RecoverableKinds &= ~Unrecoverable;
677 TrappingKinds &= Kinds;
678 RecoverableKinds &= ~TrappingKinds;
683 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
689 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
690 options::OPT_fno_sanitize_ignorelist,
691 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
694 if (AllAddedKinds & SanitizerKind::Memory) {
696 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
697 options::OPT_fno_sanitize_memory_track_origins)) {
698 if (!A->getOption().matches(
699 options::OPT_fno_sanitize_memory_track_origins)) {
700 StringRef S = A->getValue();
701 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
702 MsanTrackOrigins > 2) {
704 D.Diag(clang::diag::err_drv_invalid_value)
705 << A->getAsString(Args) << S;
709 MsanUseAfterDtor = Args.hasFlag(
710 options::OPT_fsanitize_memory_use_after_dtor,
711 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
712 MsanParamRetval = Args.hasFlag(
713 options::OPT_fsanitize_memory_param_retval,
714 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
715 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
716 MsanUseAfterDtor =
false;
717 MsanParamRetval = Args.hasFlag(
718 options::OPT_fsanitize_memory_param_retval,
719 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
721 MsanUseAfterDtor =
false;
722 MsanParamRetval =
false;
725 if (AllAddedKinds & SanitizerKind::MemTag) {
727 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
728 if (S ==
"async" || S ==
"sync") {
729 MemtagMode = S.str();
731 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
732 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
737 if (AllAddedKinds & SanitizerKind::Thread) {
738 TsanMemoryAccess = Args.hasFlag(
739 options::OPT_fsanitize_thread_memory_access,
740 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
741 TsanFuncEntryExit = Args.hasFlag(
742 options::OPT_fsanitize_thread_func_entry_exit,
743 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
745 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
746 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
749 if (AllAddedKinds & SanitizerKind::CFI) {
752 NeedPIE |= CfiCrossDso;
753 CfiICallGeneralizePointers =
754 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
756 CfiICallNormalizeIntegers =
757 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
759 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
760 D.Diag(diag::err_drv_argument_not_allowed_with)
761 <<
"-fsanitize-cfi-cross-dso"
762 <<
"-fsanitize-cfi-icall-generalize-pointers";
764 CfiCanonicalJumpTables =
765 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
766 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
769 if (AllAddedKinds & SanitizerKind::KCFI) {
770 CfiICallNormalizeIntegers =
771 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
773 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
774 D.Diag(diag::err_drv_argument_not_allowed_with)
779 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
780 options::OPT_fno_sanitize_stats,
false);
782 if (MinimalRuntime) {
785 if (IncompatibleMask && DiagnoseErrors)
786 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
787 <<
"-fsanitize-minimal-runtime"
790 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
791 if (NonTrappingCfi && DiagnoseErrors)
792 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
793 <<
"fsanitize-minimal-runtime"
794 <<
"fsanitize-trap=cfi";
797 for (
const auto *Arg : Args.filtered(
798 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
800 OverflowPatternExclusions |=
806 for (
const auto *Arg : Args) {
807 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
808 int LegacySanitizeCoverage;
809 if (Arg->getNumValues() == 1 &&
810 !StringRef(Arg->getValue(0))
811 .getAsInteger(0, LegacySanitizeCoverage)) {
812 CoverageFeatures = 0;
814 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
815 D.Diag(diag::warn_drv_deprecated_arg)
816 << Arg->getAsString(Args) <<
true
817 <<
"-fsanitize-coverage=trace-pc-guard";
828 CoverageFeatures = 0;
830 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
832 CoverageFeatures &= ~parseCoverageFeatures(
D, Arg, DiagnoseErrors);
836 if (DiagnoseErrors) {
838 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
839 <<
"-fsanitize-coverage=func"
840 <<
"-fsanitize-coverage=bb";
842 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
843 <<
"-fsanitize-coverage=func"
844 <<
"-fsanitize-coverage=edge";
846 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
847 <<
"-fsanitize-coverage=bb"
848 <<
"-fsanitize-coverage=edge";
852 D.Diag(clang::diag::warn_drv_deprecated_arg)
853 <<
"-fsanitize-coverage=trace-bb" <<
true
854 <<
"-fsanitize-coverage=trace-pc-guard";
856 D.Diag(clang::diag::warn_drv_deprecated_arg)
857 <<
"-fsanitize-coverage=8bit-counters" <<
true
858 <<
"-fsanitize-coverage=trace-pc-guard";
866 if ((CoverageFeatures & InsertionPointTypes) &&
867 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
868 D.Diag(clang::diag::warn_drv_deprecated_arg)
869 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
870 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
875 if (!(CoverageFeatures & InsertionPointTypes)) {
876 if (CoverageFeatures &
889 if (CoverageFeatures) {
891 D, Args, CoverageAllowlistFiles,
892 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
893 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
896 D, Args, CoverageIgnorelistFiles,
897 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
898 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
903 for (
const auto *Arg :
904 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
905 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
906 if (Arg->getOption().matches(
907 options::OPT_fexperimental_sanitize_metadata_EQ)) {
909 BinaryMetadataFeatures |=
913 BinaryMetadataFeatures &=
914 ~parseBinaryMetadataFeatures(
D, Arg, DiagnoseErrors);
919 if (BinaryMetadataFeatures) {
921 D, Args, BinaryMetadataIgnorelistFiles,
922 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
924 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
929 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
933 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
935 if (AllAddedKinds & SanitizerKind::Address) {
938 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
939 StringRef S = A->getValue();
941 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
942 AsanFieldPadding > 2) &&
944 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
948 if (Arg *WindowsDebugRTArg =
949 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
950 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
951 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
952 switch (WindowsDebugRTArg->getOption().getID()) {
953 case options::OPT__SLASH_MTd:
954 case options::OPT__SLASH_MDd:
955 case options::OPT__SLASH_LDd:
956 if (DiagnoseErrors) {
957 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
958 << WindowsDebugRTArg->getAsString(Args)
960 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
965 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
966 options::OPT_fno_sanitize_stable_abi,
false);
968 AsanUseAfterScope = Args.hasFlag(
969 options::OPT_fsanitize_address_use_after_scope,
970 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
972 AsanPoisonCustomArrayCookie = Args.hasFlag(
973 options::OPT_fsanitize_address_poison_custom_array_cookie,
974 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
975 AsanPoisonCustomArrayCookie);
977 AsanOutlineInstrumentation =
978 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
979 options::OPT_fno_sanitize_address_outline_instrumentation,
980 AsanOutlineInstrumentation);
982 AsanGlobalsDeadStripping = Args.hasFlag(
983 options::OPT_fsanitize_address_globals_dead_stripping,
984 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
990 AsanUseOdrIndicator =
991 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
992 options::OPT_fno_sanitize_address_use_odr_indicator,
995 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
996 AsanInvalidPointerCmp =
true;
999 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1000 AsanInvalidPointerSub =
true;
1004 (Args.hasArg(options::OPT_mkernel) ||
1005 Args.hasArg(options::OPT_fapple_kext))) {
1006 AsanDtorKind = llvm::AsanDtorKind::None;
1009 if (
const auto *Arg =
1010 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1012 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1013 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1014 << Arg->getSpelling() << Arg->getValue();
1016 AsanDtorKind = parsedAsanDtorKind;
1019 if (
const auto *Arg = Args.getLastArg(
1020 options::OPT_sanitize_address_use_after_return_EQ)) {
1021 auto parsedAsanUseAfterReturn =
1023 if (parsedAsanUseAfterReturn ==
1024 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1026 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1027 << Arg->getSpelling() << Arg->getValue();
1029 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1033 AsanUseAfterScope =
false;
1036 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1037 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1039 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1041 SanitizerKind::PointerCompare |
1042 SanitizerKind::PointerSubtract)
1043 <<
"-fsanitize=address";
1047 if (AllAddedKinds & SanitizerKind::HWAddress) {
1048 if (Arg *HwasanAbiArg =
1049 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1050 HwasanAbi = HwasanAbiArg->getValue();
1051 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1053 D.Diag(clang::diag::err_drv_invalid_value)
1054 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1056 HwasanAbi =
"interceptor";
1058 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1059 HwasanUseAliases = Args.hasFlag(
1060 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1061 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1065 if (AllAddedKinds & SanitizerKind::SafeStack) {
1072 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1073 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1076 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1077 options::OPT_fno_sanitize_link_cxx_runtime,
1081 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1082 options::OPT_fmemory_profile_EQ,
1083 options::OPT_fno_memory_profile,
false);
1086 Sanitizers.
Mask |= Kinds;
1087 RecoverableSanitizers.
Mask |= RecoverableKinds;
1088 TrapSanitizers.
Mask |= TrappingKinds;
1089 assert(!(RecoverableKinds & TrappingKinds) &&
1090 "Overlap between recoverable and trapping sanitizers");
1095#define SANITIZER(NAME, ID) \
1096 if (Sanitizers.has(SanitizerKind::ID)) { \
1101#include "clang/Basic/Sanitizers.def"
1106 llvm::opt::ArgStringList &CmdArgs,
1107 const char *SCLOptFlag,
1108 const std::vector<std::string> &SCLFiles) {
1109 for (
const auto &SCLPath : SCLFiles) {
1112 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1117 const llvm::opt::ArgList &Args,
1118 llvm::opt::ArgStringList &CmdArgs,
1119 StringRef SymbolName) {
1121 LinkerOptionFlag =
"--linker-option=/include:";
1122 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1124 LinkerOptionFlag +=
'_';
1126 LinkerOptionFlag += SymbolName;
1127 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1131 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1133 auto It = std::find(Start, End, StringRef(
"+mte"));
1136 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1144 llvm::opt::ArgStringList &CmdArgs,
1152 bool GPUSanitize =
false;
1154 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1163 std::pair<int, const char *> CoverageFlags[] = {
1164 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1165 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1166 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1175 "-fsanitize-coverage-trace-pc-guard"),
1177 "-fsanitize-coverage-inline-8bit-counters"),
1179 "-fsanitize-coverage-inline-bool-flag"),
1186 for (
auto F : CoverageFlags) {
1187 if (CoverageFeatures & F.first)
1188 CmdArgs.push_back(F.second);
1191 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1193 CoverageIgnorelistFiles);
1198 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1202 for (
const auto &F : BinaryMetadataFlags) {
1203 if (BinaryMetadataFeatures & F.first)
1205 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1208 "-fexperimental-sanitize-metadata-ignorelist=",
1209 BinaryMetadataIgnorelistFiles);
1213 Args.hasFlag(options::OPT_frtlib_defaultlib,
1214 options::OPT_fno_rtlib_defaultlib,
true)) {
1218 Args.MakeArgString(
"--dependent-lib=" +
1221 CmdArgs.push_back(Args.MakeArgString(
1222 "--dependent-lib=" +
1226 Args.hasFlag(options::OPT_frtlib_defaultlib,
1227 options::OPT_fno_rtlib_defaultlib,
true)) {
1228 CmdArgs.push_back(Args.MakeArgString(
1235 CmdArgs.push_back(Args.MakeArgString(
1240 if (Sanitizers.
empty())
1242 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1244 if (!RecoverableSanitizers.
empty())
1245 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1248 if (!TrapSanitizers.
empty())
1250 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1253 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1255 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1257 if (OverflowPatternExclusions)
1259 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1261 if (MsanTrackOrigins)
1262 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1263 Twine(MsanTrackOrigins)));
1265 if (MsanUseAfterDtor)
1266 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1268 if (!MsanParamRetval)
1269 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1272 if (!TsanMemoryAccess) {
1273 CmdArgs.push_back(
"-mllvm");
1274 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1275 CmdArgs.push_back(
"-mllvm");
1276 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1278 if (!TsanFuncEntryExit) {
1279 CmdArgs.push_back(
"-mllvm");
1280 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1283 CmdArgs.push_back(
"-mllvm");
1284 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1287 if (HwasanUseAliases) {
1288 CmdArgs.push_back(
"-mllvm");
1289 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1293 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1295 if (CfiICallGeneralizePointers)
1296 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1298 if (CfiICallNormalizeIntegers)
1299 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1301 if (CfiCanonicalJumpTables)
1302 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1305 CmdArgs.push_back(
"-fsanitize-stats");
1308 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1310 if (AsanFieldPadding)
1311 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1312 Twine(AsanFieldPadding)));
1314 if (AsanUseAfterScope)
1315 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1317 if (AsanPoisonCustomArrayCookie)
1318 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1320 if (AsanGlobalsDeadStripping)
1321 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1323 if (!AsanUseOdrIndicator)
1324 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1326 if (AsanInvalidPointerCmp) {
1327 CmdArgs.push_back(
"-mllvm");
1328 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1331 if (AsanInvalidPointerSub) {
1332 CmdArgs.push_back(
"-mllvm");
1333 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1336 if (AsanOutlineInstrumentation) {
1337 CmdArgs.push_back(
"-mllvm");
1338 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1345 CmdArgs.push_back(
"-mllvm");
1346 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1347 CmdArgs.push_back(
"-mllvm");
1348 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1349 CmdArgs.push_back(
"-mllvm");
1350 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1355 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1356 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1360 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1361 CmdArgs.push_back(Args.MakeArgString(
1362 "-fsanitize-address-use-after-return=" +
1366 if (!HwasanAbi.empty()) {
1367 CmdArgs.push_back(
"-default-function-attr");
1368 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1371 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1372 CmdArgs.push_back(
"-target-feature");
1373 CmdArgs.push_back(
"+tagged-globals");
1381 if (Sanitizers.
has(SanitizerKind::Memory) ||
1382 Sanitizers.
has(SanitizerKind::Address))
1383 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1390 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1391 CmdArgs.push_back(
"-fno-builtin-bcmp");
1392 CmdArgs.push_back(
"-fno-builtin-memcmp");
1393 CmdArgs.push_back(
"-fno-builtin-strncmp");
1394 CmdArgs.push_back(
"-fno-builtin-strcmp");
1395 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1396 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1397 CmdArgs.push_back(
"-fno-builtin-strstr");
1398 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1399 CmdArgs.push_back(
"-fno-builtin-memmem");
1405 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1406 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1412 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1414 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1418 bool DiagnoseErrors) {
1419 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1420 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1421 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1422 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1423 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1424 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1425 "Invalid argument in parseArgValues!");
1427 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1428 const char *
Value = A->getValue(i);
1431 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1432 0 == strcmp(
"all",
Value))
1439 else if (DiagnoseErrors)
1440 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1441 << A->getSpelling() <<
Value;
1447 const llvm::opt::Arg *A,
1448 bool DiagnoseErrors) {
1450 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1451 const char *
Value = A->getValue(i);
1453 llvm::StringSwitch<int>(
Value)
1461 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1462 << A->getSpelling() <<
Value;
1469 bool DiagnoseErrors) {
1470 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1471 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1473 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1474 const char *
Value = A->getValue(i);
1475 int F = llvm::StringSwitch<int>(
Value)
1496 if (F == 0 && DiagnoseErrors)
1497 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1498 << A->getSpelling() <<
Value;
1505 bool DiagnoseErrors) {
1507 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1508 A->getOption().matches(
1509 options::OPT_fno_experimental_sanitize_metadata_EQ));
1511 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1512 const char *
Value = A->getValue(i);
1513 int F = llvm::StringSwitch<int>(
Value)
1519 if (F == 0 && DiagnoseErrors)
1520 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1521 << A->getSpelling() <<
Value;
1529 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1532 const auto *Arg = *I;
1533 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1536 if (AddKinds & Mask)
1538 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1541 Mask &= ~RemoveKinds;
1544 llvm_unreachable(
"arg list didn't provide expected value");
1548 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1549 "Invalid argument in describeSanitizerArg!");
1551 std::string Sanitizers;
1552 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1556 if (!Sanitizers.empty())
1558 Sanitizers += A->getValue(i);
1562 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1563 return "-fsanitize=" + Sanitizers;
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 void addIncludeLinkerOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, StringRef SymbolName)
static bool isExecuteOnlyTarget(const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Return true if an execute-only target disallows data access to code sections.
static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs)
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 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 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 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
@ CoverageInline8bitCounters
Defines the clang::SanitizerKind enum.
@ None
Don't exclude any overflow patterns from sanitizers.
@ AddOverflowTest
if (a + b < a)
@ All
Exclude all overflow patterns (below)
@ PostDecrInWhile
while (count–)
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
bool needsFuzzerInterceptors() const
bool needsStatsRt() const
bool needsCfiDiagRt() const
bool needsUbsanRt() const
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, bool DiagnoseErrors=true)
Parses the sanitizer arguments from an argument list.
bool needsHwasanRt() const
bool requiresMinimalRuntime() const
bool needsUnwindTables() const
bool needsDfsanRt() const
bool needsScudoRt() const
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
The JSON file list parser is used to communicate input to InstallAPI.
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
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)
bool empty() const
Returns true if no sanitizers are enabled.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
SanitizerMask Mask
Bitmask of enabled sanitizers.
bool hasOneOf(SanitizerMask K) const
Check if one or more sanitizers are enabled.