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"
27 using namespace clang;
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 |
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;
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
64 SanitizerKind::Unreachable | SanitizerKind::Return;
66 SanitizerKind::KernelHWAddress |
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 bool DiagnoseErrors);
132 const llvm::opt::ArgList &Args,
149 const llvm::opt::ArgList &Args) {
152 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
153 options::OPT_mno_execute_only,
false);
157 std::vector<std::string> &SCLFiles,
158 unsigned MalformedSCLErrorDiagID,
159 bool DiagnoseErrors) {
160 if (SCLFiles.empty())
164 std::unique_ptr<llvm::SpecialCaseList> SCL(
166 if (!SCL.get() && DiagnoseErrors)
167 D.Diag(MalformedSCLErrorDiagID) << BLError;
171 std::vector<std::string> &IgnorelistFiles,
172 bool DiagnoseErrors) {
176 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
177 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
178 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
179 {
"msan_ignorelist.txt", SanitizerKind::Memory},
180 {
"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
181 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
182 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
183 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
184 {
"ubsan_ignorelist.txt",
187 SanitizerKind::FloatDivideByZero}};
189 for (
auto BL : Ignorelists) {
190 if (!(Kinds & BL.Mask))
194 llvm::sys::path::append(
Path,
"share", BL.File);
195 if (
D.getVFS().exists(
Path))
196 IgnorelistFiles.push_back(std::string(
Path));
197 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
200 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) <<
Path;
203 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
210 const llvm::opt::ArgList &Args,
211 std::vector<std::string> &SCLFiles,
212 llvm::opt::OptSpecifier SCLOptionID,
213 llvm::opt::OptSpecifier NoSCLOptionID,
214 unsigned MalformedSCLErrorDiagID,
215 bool DiagnoseErrors) {
216 for (
const auto *Arg : Args) {
218 if (Arg->getOption().matches(SCLOptionID)) {
220 std::string SCLPath = Arg->getValue();
221 if (
D.getVFS().exists(SCLPath)) {
222 SCLFiles.push_back(SCLPath);
223 }
else if (DiagnoseErrors) {
224 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
227 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
239 #define SANITIZER(NAME, ID)
240 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
241 if (Kinds & SanitizerKind::ID) \
242 Kinds |= SanitizerKind::ID##Group;
243 #include "clang/Basic/Sanitizers.def"
248 const llvm::opt::ArgList &Args,
249 bool DiagnoseErrors) {
256 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
257 if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
261 SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;
262 if (InvalidValues && DiagnoseErrors) {
264 S.Mask = InvalidValues;
265 D.Diag(diag::err_drv_unsupported_option_argument)
266 << Arg->getSpelling() <<
toString(S);
269 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
279 return TrappingKinds;
283 return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();
288 if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
289 needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
290 (needsScudoRt() && !requiresMinimalRuntime()))
293 return (Sanitizers.Mask &
NeedsUbsanRt & ~TrapSanitizers.Mask) ||
298 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
299 CfiCrossDso && !ImplicitCfiRuntime;
303 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
304 CfiCrossDso && !ImplicitCfiRuntime;
314 return static_cast<bool>(Sanitizers.Mask &
NeedsLTO);
318 const llvm::opt::ArgList &Args,
319 bool DiagnoseErrors) {
333 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
334 options::OPT_fno_sanitize_cfi_cross_dso,
false);
343 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
344 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
347 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
348 bool RemoveObjectSizeAtO0 =
349 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
351 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
352 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
356 if (RemoveObjectSizeAtO0) {
357 AllRemove |= SanitizerKind::ObjectSize;
361 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
362 D.Diag(diag::warn_drv_object_size_disabled_O0)
363 << Arg->getAsString(Args);
374 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
375 if (DiagnoseErrors) {
377 D.Diag(diag::err_drv_argument_not_allowed_with)
378 << Desc <<
"-fsanitize-trap=undefined";
380 DiagnosedKinds |= KindsToDiagnose;
382 Add &= ~InvalidTrappingKinds;
384 if (MinimalRuntime) {
387 if (DiagnoseErrors) {
389 D.Diag(diag::err_drv_argument_not_allowed_with)
390 << Desc <<
"-fsanitize-minimal-runtime";
392 DiagnosedKinds |= KindsToDiagnose;
397 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
398 StringRef CM = A->getValue();
400 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
402 D.Diag(diag::err_drv_argument_only_allowed_with)
403 <<
"-fsanitize=function"
406 DiagnosedKinds |= SanitizerKind::Function;
412 const llvm::Triple &Triple = TC.
getTriple();
416 if (DiagnoseErrors) {
418 D.Diag(diag::err_drv_argument_not_allowed_with)
419 << Desc << Triple.str();
421 DiagnosedKinds |= KindsToDiagnose;
436 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
438 D.Diag(diag::err_drv_argument_not_allowed_with)
439 <<
"-fsanitize=cfi-mfcall"
440 <<
"-fsanitize-cfi-cross-dso";
442 DiagnosedKinds |= SanitizerKind::CFIMFCall;
445 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
446 if (DiagnoseErrors) {
448 D.Diag(diag::err_drv_unsupported_opt_for_target)
451 DiagnosedKinds |= KindsToDiagnose;
459 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
460 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
461 "RTTI disabled without -fno-rtti option?");
465 D.Diag(diag::err_drv_argument_not_allowed_with)
466 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
471 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
475 AllRemove |= SanitizerKind::Vptr;
483 Add &= ~InvalidTrappingKinds;
484 if (MinimalRuntime) {
495 if (Add & SanitizerKind::UndefinedGroup) {
496 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
497 options::OPT_fstrict_overflow,
false);
498 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
503 if (Add & SanitizerKind::Fuzzer)
504 Add |= SanitizerKind::FuzzerNoLink;
507 if (Add & SanitizerKind::FuzzerNoLink) {
516 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
523 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
524 std::make_pair(SanitizerKind::Address,
525 SanitizerKind::Thread | SanitizerKind::Memory),
526 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
527 std::make_pair(SanitizerKind::Leak,
528 SanitizerKind::Thread | SanitizerKind::Memory),
529 std::make_pair(SanitizerKind::KernelAddress,
530 SanitizerKind::Address | SanitizerKind::Leak |
531 SanitizerKind::Thread | SanitizerKind::Memory),
532 std::make_pair(SanitizerKind::HWAddress,
533 SanitizerKind::Address | SanitizerKind::Thread |
534 SanitizerKind::Memory | SanitizerKind::KernelAddress),
535 std::make_pair(SanitizerKind::Scudo,
536 SanitizerKind::Address | SanitizerKind::HWAddress |
537 SanitizerKind::Leak | SanitizerKind::Thread |
538 SanitizerKind::Memory | SanitizerKind::KernelAddress),
539 std::make_pair(SanitizerKind::SafeStack,
541 : SanitizerKind::Leak) |
542 SanitizerKind::Address | SanitizerKind::HWAddress |
543 SanitizerKind::Thread | SanitizerKind::Memory |
544 SanitizerKind::KernelAddress),
545 std::make_pair(SanitizerKind::KernelHWAddress,
546 SanitizerKind::Address | SanitizerKind::HWAddress |
547 SanitizerKind::Leak | SanitizerKind::Thread |
548 SanitizerKind::Memory | SanitizerKind::KernelAddress |
549 SanitizerKind::SafeStack),
550 std::make_pair(SanitizerKind::KernelMemory,
551 SanitizerKind::Address | SanitizerKind::HWAddress |
552 SanitizerKind::Leak | SanitizerKind::Thread |
553 SanitizerKind::Memory | SanitizerKind::KernelAddress |
554 SanitizerKind::Scudo | SanitizerKind::SafeStack),
555 std::make_pair(SanitizerKind::MemTag,
556 SanitizerKind::Address | SanitizerKind::KernelAddress |
557 SanitizerKind::HWAddress |
558 SanitizerKind::KernelHWAddress),
559 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};
565 for (
auto G : IncompatibleGroups) {
580 if ((Kinds &
NeedsLTO) && !
D.isUsingLTO() && DiagnoseErrors) {
581 D.Diag(diag::err_drv_argument_only_allowed_with)
585 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
586 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
587 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
588 D.Diag(diag::err_drv_argument_only_allowed_with)
597 if (~Supported & SanitizerKind::Vptr) {
603 if (KindsToDiagnose) {
605 S.Mask = KindsToDiagnose;
607 D.Diag(diag::err_drv_unsupported_opt_for_target)
609 Kinds &= ~KindsToDiagnose;
614 for (
auto G : IncompatibleGroups) {
619 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
622 Kinds &= ~Incompatible;
635 for (
const auto *Arg : Args) {
636 if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
643 SetToDiagnose.
Mask |= KindsToDiagnose;
645 D.Diag(diag::err_drv_unsupported_option_argument)
646 << Arg->getSpelling() <<
toString(SetToDiagnose);
647 DiagnosedUnrecoverableKinds |= KindsToDiagnose;
651 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
658 SetToDiagnose.
Mask |= KindsToDiagnose;
660 D.Diag(diag::err_drv_unsupported_option_argument)
661 << Arg->getSpelling() <<
toString(SetToDiagnose);
662 DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
668 RecoverableKinds &= Kinds;
671 TrappingKinds &= Kinds;
672 RecoverableKinds &= ~TrappingKinds;
677 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
683 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
684 options::OPT_fno_sanitize_ignorelist,
685 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
688 if (AllAddedKinds & SanitizerKind::Memory) {
690 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
691 options::OPT_fno_sanitize_memory_track_origins)) {
692 if (!A->getOption().matches(
693 options::OPT_fno_sanitize_memory_track_origins)) {
694 StringRef S = A->getValue();
695 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
696 MsanTrackOrigins > 2) {
698 D.Diag(clang::diag::err_drv_invalid_value)
699 << A->getAsString(Args) << S;
703 MsanUseAfterDtor = Args.hasFlag(
704 options::OPT_fsanitize_memory_use_after_dtor,
705 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
706 MsanParamRetval = Args.hasFlag(
707 options::OPT_fsanitize_memory_param_retval,
708 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
709 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
710 MsanUseAfterDtor =
false;
711 MsanParamRetval = Args.hasFlag(
712 options::OPT_fsanitize_memory_param_retval,
713 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
715 MsanUseAfterDtor =
false;
716 MsanParamRetval =
false;
719 if (AllAddedKinds & SanitizerKind::MemTag) {
721 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
722 if (S ==
"async" || S ==
"sync") {
723 MemtagMode = S.str();
725 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
726 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
731 if (AllAddedKinds & SanitizerKind::Thread) {
732 TsanMemoryAccess = Args.hasFlag(
733 options::OPT_fsanitize_thread_memory_access,
734 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
735 TsanFuncEntryExit = Args.hasFlag(
736 options::OPT_fsanitize_thread_func_entry_exit,
737 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
739 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
740 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
743 if (AllAddedKinds & SanitizerKind::CFI) {
746 NeedPIE |= CfiCrossDso;
747 CfiICallGeneralizePointers =
748 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
750 CfiICallNormalizeIntegers =
751 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
753 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
754 D.Diag(diag::err_drv_argument_not_allowed_with)
755 <<
"-fsanitize-cfi-cross-dso"
756 <<
"-fsanitize-cfi-icall-generalize-pointers";
758 CfiCanonicalJumpTables =
759 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
760 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
763 if (AllAddedKinds & SanitizerKind::KCFI) {
764 CfiICallNormalizeIntegers =
765 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
767 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
768 D.Diag(diag::err_drv_argument_not_allowed_with)
773 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
774 options::OPT_fno_sanitize_stats,
false);
776 if (MinimalRuntime) {
779 if (IncompatibleMask && DiagnoseErrors)
780 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
781 <<
"-fsanitize-minimal-runtime"
784 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
785 if (NonTrappingCfi && DiagnoseErrors)
786 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
787 <<
"fsanitize-minimal-runtime"
788 <<
"fsanitize-trap=cfi";
793 for (
const auto *Arg : Args) {
794 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
795 int LegacySanitizeCoverage;
796 if (Arg->getNumValues() == 1 &&
797 !StringRef(Arg->getValue(0))
798 .getAsInteger(0, LegacySanitizeCoverage)) {
799 CoverageFeatures = 0;
801 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
802 D.Diag(diag::warn_drv_deprecated_arg)
803 << Arg->getAsString(Args) <<
true
804 <<
"-fsanitize-coverage=trace-pc-guard";
815 CoverageFeatures = 0;
817 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
823 if (DiagnoseErrors) {
825 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
826 <<
"-fsanitize-coverage=func"
827 <<
"-fsanitize-coverage=bb";
829 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
830 <<
"-fsanitize-coverage=func"
831 <<
"-fsanitize-coverage=edge";
833 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
834 <<
"-fsanitize-coverage=bb"
835 <<
"-fsanitize-coverage=edge";
839 D.Diag(clang::diag::warn_drv_deprecated_arg)
840 <<
"-fsanitize-coverage=trace-bb" <<
true
841 <<
"-fsanitize-coverage=trace-pc-guard";
843 D.Diag(clang::diag::warn_drv_deprecated_arg)
844 <<
"-fsanitize-coverage=8bit-counters" <<
true
845 <<
"-fsanitize-coverage=trace-pc-guard";
853 if ((CoverageFeatures & InsertionPointTypes) &&
854 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
855 D.Diag(clang::diag::warn_drv_deprecated_arg)
856 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
857 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
862 if (!(CoverageFeatures & InsertionPointTypes)) {
863 if (CoverageFeatures &
876 if (CoverageFeatures) {
878 D, Args, CoverageAllowlistFiles,
879 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
880 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
883 D, Args, CoverageIgnorelistFiles,
884 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
885 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
890 for (
const auto *Arg :
891 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
892 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
893 if (Arg->getOption().matches(
894 options::OPT_fexperimental_sanitize_metadata_EQ)) {
896 BinaryMetadataFeatures |=
900 BinaryMetadataFeatures &=
906 if (BinaryMetadataFeatures) {
908 D, Args, BinaryMetadataIgnorelistFiles,
909 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
911 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
916 Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
920 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
922 if (AllAddedKinds & SanitizerKind::Address) {
925 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
926 StringRef S = A->getValue();
928 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
929 AsanFieldPadding > 2) &&
931 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
935 if (Arg *WindowsDebugRTArg =
936 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
937 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
938 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
939 switch (WindowsDebugRTArg->getOption().getID()) {
940 case options::OPT__SLASH_MTd:
941 case options::OPT__SLASH_MDd:
942 case options::OPT__SLASH_LDd:
943 if (DiagnoseErrors) {
944 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
945 << WindowsDebugRTArg->getAsString(Args)
947 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
952 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
953 options::OPT_fno_sanitize_stable_abi,
false);
955 AsanUseAfterScope = Args.hasFlag(
956 options::OPT_fsanitize_address_use_after_scope,
957 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
959 AsanPoisonCustomArrayCookie = Args.hasFlag(
960 options::OPT_fsanitize_address_poison_custom_array_cookie,
961 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
962 AsanPoisonCustomArrayCookie);
964 AsanOutlineInstrumentation =
965 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
966 options::OPT_fno_sanitize_address_outline_instrumentation,
967 AsanOutlineInstrumentation);
969 AsanGlobalsDeadStripping = Args.hasFlag(
970 options::OPT_fsanitize_address_globals_dead_stripping,
971 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
977 AsanUseOdrIndicator =
978 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
979 options::OPT_fno_sanitize_address_use_odr_indicator,
982 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
983 AsanInvalidPointerCmp =
true;
986 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
987 AsanInvalidPointerSub =
true;
991 (Args.hasArg(options::OPT_mkernel) ||
992 Args.hasArg(options::OPT_fapple_kext))) {
996 if (
const auto *Arg =
997 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
999 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1000 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1001 << Arg->getSpelling() << Arg->getValue();
1003 AsanDtorKind = parsedAsanDtorKind;
1006 if (
const auto *Arg = Args.getLastArg(
1007 options::OPT_sanitize_address_use_after_return_EQ)) {
1008 auto parsedAsanUseAfterReturn =
1010 if (parsedAsanUseAfterReturn ==
1011 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1013 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1014 << Arg->getSpelling() << Arg->getValue();
1016 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1020 AsanUseAfterScope =
false;
1023 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1024 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1026 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1028 SanitizerKind::PointerCompare |
1029 SanitizerKind::PointerSubtract)
1030 <<
"-fsanitize=address";
1034 if (AllAddedKinds & SanitizerKind::HWAddress) {
1035 if (Arg *HwasanAbiArg =
1036 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1037 HwasanAbi = HwasanAbiArg->getValue();
1038 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1040 D.Diag(clang::diag::err_drv_invalid_value)
1041 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1043 HwasanAbi =
"interceptor";
1045 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1046 HwasanUseAliases = Args.hasFlag(
1047 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1048 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1052 if (AllAddedKinds & SanitizerKind::SafeStack) {
1059 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1060 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1063 LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,
1064 options::OPT_fno_sanitize_link_cxx_runtime,
1068 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1069 options::OPT_fmemory_profile_EQ,
1070 options::OPT_fno_memory_profile,
false);
1073 Sanitizers.Mask |= Kinds;
1074 RecoverableSanitizers.Mask |= RecoverableKinds;
1075 TrapSanitizers.Mask |= TrappingKinds;
1076 assert(!(RecoverableKinds & TrappingKinds) &&
1077 "Overlap between recoverable and trapping sanitizers");
1082 #define SANITIZER(NAME, ID) \
1083 if (Sanitizers.has(SanitizerKind::ID)) { \
1088 #include "clang/Basic/Sanitizers.def"
1093 llvm::opt::ArgStringList &CmdArgs,
1094 const char *SCLOptFlag,
1095 const std::vector<std::string> &SCLFiles) {
1096 for (
const auto &SCLPath : SCLFiles) {
1099 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1104 const llvm::opt::ArgList &Args,
1105 llvm::opt::ArgStringList &CmdArgs,
1106 StringRef SymbolName) {
1108 LinkerOptionFlag =
"--linker-option=/include:";
1109 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1111 LinkerOptionFlag +=
'_';
1113 LinkerOptionFlag += SymbolName;
1114 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1118 for (
auto Start = CmdArgs.begin(),
End = CmdArgs.end(); Start !=
End;
1120 auto It = std::find(Start,
End, StringRef(
"+mte"));
1123 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1131 llvm::opt::ArgStringList &CmdArgs,
1139 bool GPUSanitize =
false;
1141 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1149 if (Sanitizers.has(SanitizerKind::Address)) {
1150 CmdArgs.push_back(
"-fsanitize=address");
1151 CmdArgs.push_back(
"-fsanitize-address-use-after-return=never");
1152 CmdArgs.push_back(
"-fno-sanitize-address-use-after-scope");
1155 CmdArgs.push_back(
"-mllvm");
1156 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1159 CmdArgs.push_back(
"-mllvm");
1160 CmdArgs.push_back(
"-asan-constructor-kind=none");
1162 CmdArgs.push_back(
"-mllvm");
1163 CmdArgs.push_back(
"-asan-stack=0");
1164 CmdArgs.push_back(
"-mllvm");
1165 CmdArgs.push_back(
"-asan-globals=0");
1166 CmdArgs.push_back(
"-mllvm");
1167 CmdArgs.push_back(
"-asan-stack-dynamic-alloca=0");
1168 CmdArgs.push_back(
"-mllvm");
1169 CmdArgs.push_back(
"-asan-use-after-return=never");
1171 if (!RecoverableSanitizers.empty())
1172 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1175 CmdArgs.push_back(
"-mllvm");
1176 CmdArgs.push_back(
"-asan-mapping-scale=4");
1184 std::pair<int, const char *> CoverageFlags[] = {
1185 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1186 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1187 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1196 "-fsanitize-coverage-trace-pc-guard"),
1198 "-fsanitize-coverage-inline-8bit-counters"),
1200 "-fsanitize-coverage-inline-bool-flag"),
1207 for (
auto F : CoverageFlags) {
1208 if (CoverageFeatures & F.first)
1209 CmdArgs.push_back(F.second);
1212 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1214 CoverageIgnorelistFiles);
1219 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1223 for (
const auto &F : BinaryMetadataFlags) {
1224 if (BinaryMetadataFeatures & F.first)
1226 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1229 "-fexperimental-sanitize-metadata-ignorelist=",
1230 BinaryMetadataIgnorelistFiles);
1233 if (TC.
getTriple().isOSWindows() && needsUbsanRt() &&
1234 Args.hasFlag(options::OPT_frtlib_defaultlib,
1235 options::OPT_fno_rtlib_defaultlib,
true)) {
1239 Args.MakeArgString(
"--dependent-lib=" +
1242 CmdArgs.push_back(Args.MakeArgString(
1243 "--dependent-lib=" +
1246 if (TC.
getTriple().isOSWindows() && needsStatsRt() &&
1247 Args.hasFlag(options::OPT_frtlib_defaultlib,
1248 options::OPT_fno_rtlib_defaultlib,
true)) {
1249 CmdArgs.push_back(Args.MakeArgString(
1256 CmdArgs.push_back(Args.MakeArgString(
1261 if (Sanitizers.empty())
1263 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1265 if (!RecoverableSanitizers.empty())
1266 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1269 if (!TrapSanitizers.empty())
1271 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1274 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1276 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1278 if (MsanTrackOrigins)
1279 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1280 Twine(MsanTrackOrigins)));
1282 if (MsanUseAfterDtor)
1283 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1285 if (!MsanParamRetval)
1286 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1289 if (!TsanMemoryAccess) {
1290 CmdArgs.push_back(
"-mllvm");
1291 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1292 CmdArgs.push_back(
"-mllvm");
1293 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1295 if (!TsanFuncEntryExit) {
1296 CmdArgs.push_back(
"-mllvm");
1297 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1300 CmdArgs.push_back(
"-mllvm");
1301 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1304 if (HwasanUseAliases) {
1305 CmdArgs.push_back(
"-mllvm");
1306 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1310 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1312 if (CfiICallGeneralizePointers)
1313 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1315 if (CfiICallNormalizeIntegers)
1316 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1318 if (CfiCanonicalJumpTables)
1319 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1322 CmdArgs.push_back(
"-fsanitize-stats");
1325 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1327 if (AsanFieldPadding)
1328 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1329 Twine(AsanFieldPadding)));
1331 if (AsanUseAfterScope)
1332 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1334 if (AsanPoisonCustomArrayCookie)
1335 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1337 if (AsanGlobalsDeadStripping)
1338 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1340 if (!AsanUseOdrIndicator)
1341 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1343 if (AsanInvalidPointerCmp) {
1344 CmdArgs.push_back(
"-mllvm");
1345 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1348 if (AsanInvalidPointerSub) {
1349 CmdArgs.push_back(
"-mllvm");
1350 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1353 if (AsanOutlineInstrumentation) {
1354 CmdArgs.push_back(
"-mllvm");
1355 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1362 CmdArgs.push_back(
"-mllvm");
1363 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1364 CmdArgs.push_back(
"-mllvm");
1365 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1366 CmdArgs.push_back(
"-mllvm");
1367 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1372 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1373 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1377 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1378 CmdArgs.push_back(Args.MakeArgString(
1379 "-fsanitize-address-use-after-return=" +
1383 if (!HwasanAbi.empty()) {
1384 CmdArgs.push_back(
"-default-function-attr");
1385 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1388 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1389 CmdArgs.push_back(
"-target-feature");
1390 CmdArgs.push_back(
"+tagged-globals");
1398 if (Sanitizers.has(SanitizerKind::Memory) ||
1399 Sanitizers.has(SanitizerKind::Address))
1400 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1407 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {
1408 CmdArgs.push_back(
"-fno-builtin-bcmp");
1409 CmdArgs.push_back(
"-fno-builtin-memcmp");
1410 CmdArgs.push_back(
"-fno-builtin-strncmp");
1411 CmdArgs.push_back(
"-fno-builtin-strcmp");
1412 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1413 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1414 CmdArgs.push_back(
"-fno-builtin-strstr");
1415 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1416 CmdArgs.push_back(
"-fno-builtin-memmem");
1422 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1423 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1429 if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1431 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1435 bool DiagnoseErrors) {
1436 assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
1437 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1438 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1439 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1440 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1441 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
1442 "Invalid argument in parseArgValues!");
1444 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1445 const char *
Value = A->getValue(i);
1448 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1449 0 == strcmp(
"all",
Value))
1456 else if (DiagnoseErrors)
1457 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1458 << A->getSpelling() <<
Value;
1464 bool DiagnoseErrors) {
1465 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1466 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1468 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1469 const char *
Value = A->getValue(i);
1470 int F = llvm::StringSwitch<int>(
Value)
1491 if (F == 0 && DiagnoseErrors)
1492 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1493 << A->getSpelling() <<
Value;
1500 bool DiagnoseErrors) {
1502 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1503 A->getOption().matches(
1504 options::OPT_fno_experimental_sanitize_metadata_EQ));
1506 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1507 const char *
Value = A->getValue(i);
1508 int F = llvm::StringSwitch<int>(
Value)
1514 if (F == 0 && DiagnoseErrors)
1515 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1516 << A->getSpelling() <<
Value;
1524 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1527 const auto *Arg = *I;
1528 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1531 if (AddKinds & Mask)
1533 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1536 Mask &= ~RemoveKinds;
1539 llvm_unreachable(
"arg list didn't provide expected value");
1543 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1544 "Invalid argument in describeSanitizerArg!");
1546 std::string Sanitizers;
1547 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1551 if (!Sanitizers.empty())
1553 Sanitizers += A->getValue(i);
1557 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1558 return "-fsanitize=" + Sanitizers;
enum clang::sema::@1659::IndirectLocalPathEntry::EntryKind Kind
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 const SanitizerMask NotAllowedWithExecuteOnly
@ CoverageInline8bitCounters
Defines the clang::SanitizerKind enum.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
bool needsFuzzerInterceptors() 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 needsUnwindTables() const
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const
constexpr XRayInstrMask None
bool isCXX(ID Id)
isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
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)
SanitizerMask Mask
Bitmask of enabled sanitizers.