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"
30 SanitizerKind::Undefined | SanitizerKind::Integer |
31 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |
32 SanitizerKind::Nullability | SanitizerKind::CFI |
33 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |
36 SanitizerKind::Vptr | SanitizerKind::CFI;
40 SanitizerKind::Function | SanitizerKind::KCFI;
42 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
43 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
44 SanitizerKind::NumericalStability;
46 SanitizerKind::Address | SanitizerKind::HWAddress |
47 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
48 SanitizerKind::Type | SanitizerKind::MemtagStack |
49 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
50 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
51 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
52 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
53 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
54 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
55 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
56 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
57 SanitizerKind::NumericalStability | SanitizerKind::Vptr |
60 SanitizerKind::Undefined | SanitizerKind::Integer |
61 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
62 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast |
65 SanitizerKind::Unreachable | SanitizerKind::Return;
67 SanitizerKind::KernelHWAddress |
71 SanitizerKind::Undefined | SanitizerKind::Integer |
72 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
73 SanitizerKind::LocalBounds | SanitizerKind::CFI |
74 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
76 SanitizerKind::Undefined | SanitizerKind::Vptr;
78 SanitizerKind::CFI | SanitizerKind::LocalBounds;
81 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
82 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
83 SanitizerKind::CFIUnrelatedCast;
86 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
87 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
120 bool DiagnoseErrors);
131 bool DiagnoseErrors);
136 const llvm::opt::Arg *A,
137 bool DiagnoseErrors);
142 bool DiagnoseErrors);
149 const llvm::opt::ArgList &Args,
170 const llvm::opt::ArgList &Args) {
173 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
174 options::OPT_mno_execute_only,
false);
178 std::vector<std::string> &SCLFiles,
179 unsigned MalformedSCLErrorDiagID,
180 bool DiagnoseErrors) {
181 if (SCLFiles.empty())
185 std::unique_ptr<llvm::SpecialCaseList> SCL(
186 llvm::SpecialCaseList::create(SCLFiles,
D.getVFS(), BLError));
187 if (!SCL && DiagnoseErrors)
188 D.Diag(MalformedSCLErrorDiagID) << BLError;
192 std::vector<std::string> &IgnorelistFiles,
193 bool DiagnoseErrors) {
197 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
198 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
199 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
200 {
"msan_ignorelist.txt", SanitizerKind::Memory},
201 {
"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
202 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
203 {
"tysan_blacklist.txt", SanitizerKind::Type},
204 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
205 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
206 {
"ubsan_ignorelist.txt",
207 SanitizerKind::Undefined | SanitizerKind::Vptr |
208 SanitizerKind::Integer | SanitizerKind::Nullability |
209 SanitizerKind::FloatDivideByZero}};
211 for (
auto BL : Ignorelists) {
212 if (!(Kinds & BL.Mask))
216 llvm::sys::path::append(
Path,
"share", BL.File);
217 if (
D.getVFS().exists(
Path))
218 IgnorelistFiles.push_back(std::string(
Path));
219 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
222 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) <<
Path;
225 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
232 const llvm::opt::ArgList &Args,
233 std::vector<std::string> &SCLFiles,
234 llvm::opt::OptSpecifier SCLOptionID,
235 llvm::opt::OptSpecifier NoSCLOptionID,
236 unsigned MalformedSCLErrorDiagID,
237 bool DiagnoseErrors) {
238 for (
const auto *Arg : Args) {
240 if (Arg->getOption().matches(SCLOptionID)) {
242 std::string SCLPath = Arg->getValue();
243 if (
D.getVFS().exists(SCLPath)) {
244 SCLFiles.push_back(SCLPath);
245 }
else if (DiagnoseErrors) {
246 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
249 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
261#define SANITIZER(NAME, ID)
262#define SANITIZER_GROUP(NAME, ID, ALIAS) \
263 if (Kinds & SanitizerKind::ID) \
264 Kinds |= SanitizerKind::ID##Group;
265#include "clang/Basic/Sanitizers.def"
278 "parseSanitizeArgs called with contradictory in/out requirements");
285 for (
const auto *Arg : Args) {
286 if (Arg->getOption().matches(OptInID)) {
291 Add &
AlwaysOut & ~DiagnosedAlwaysOutViolations) {
292 if (DiagnoseErrors) {
294 SetToDiagnose.
Mask |= KindsToDiagnose;
295 D.Diag(diag::err_drv_unsupported_option_argument)
297 DiagnosedAlwaysOutViolations |= KindsToDiagnose;
302 }
else if (Arg->getOption().matches(OptOutID)) {
307 Remove &
AlwaysIn & ~DiagnosedAlwaysInViolations) {
308 if (DiagnoseErrors) {
310 SetToDiagnose.
Mask |= KindsToDiagnose;
311 D.Diag(diag::err_drv_unsupported_option_argument)
313 DiagnosedAlwaysInViolations |= KindsToDiagnose;
316 Output &= ~expandSanitizerGroups(Remove);
322 Output &= ~AlwaysOut;
328 const llvm::opt::ArgList &Args,
329 bool DiagnoseErrors) {
334 NeverTrap, options::OPT_fsanitize_trap_EQ,
335 options::OPT_fno_sanitize_trap_EQ);
340 bool DiagnoseErrors) {
342 for (
const auto *Arg : Args)
343 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {
371 ~TrapSanitizers.Mask);
381 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
382 CfiCrossDso && !ImplicitCfiRuntime;
396 const llvm::opt::ArgList &Args,
397 bool DiagnoseErrors) {
411 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
412 options::OPT_fno_sanitize_cfi_cross_dso,
false);
421 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
422 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
425 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
426 bool RemoveObjectSizeAtO0 =
427 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
429 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
430 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
434 if (RemoveObjectSizeAtO0) {
435 AllRemove |= SanitizerKind::ObjectSize;
439 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
440 D.Diag(diag::warn_drv_object_size_disabled_O0)
441 << Arg->getAsString(Args);
452 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
453 if (DiagnoseErrors) {
455 D.Diag(diag::err_drv_argument_not_allowed_with)
456 << Desc <<
"-fsanitize-trap=undefined";
458 DiagnosedKinds |= KindsToDiagnose;
460 Add &= ~InvalidTrappingKinds;
462 if (MinimalRuntime) {
465 if (DiagnoseErrors) {
467 D.Diag(diag::err_drv_argument_not_allowed_with)
468 << Desc <<
"-fsanitize-minimal-runtime";
470 DiagnosedKinds |= KindsToDiagnose;
472 Add &= ~NotAllowedWithMinimalRuntime;
475 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
476 StringRef CM = A->getValue();
478 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
480 D.Diag(diag::err_drv_argument_only_allowed_with)
481 <<
"-fsanitize=function"
484 DiagnosedKinds |= SanitizerKind::Function;
490 const llvm::Triple &Triple = TC.
getTriple();
494 if (DiagnoseErrors) {
496 llvm::opt::Arg *A = Args.getLastArgNoClaim(
497 options::OPT_mexecute_only, options::OPT_mno_execute_only);
498 if (A && A->getOption().matches(options::OPT_mexecute_only))
499 D.Diag(diag::err_drv_argument_not_allowed_with)
500 << Desc << A->getAsString(Args);
502 D.Diag(diag::err_drv_unsupported_opt_for_target)
503 << Desc << Triple.str();
505 DiagnosedKinds |= KindsToDiagnose;
507 Add &= ~NotAllowedWithExecuteOnly;
520 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
522 D.Diag(diag::err_drv_argument_not_allowed_with)
523 <<
"-fsanitize=cfi-mfcall"
524 <<
"-fsanitize-cfi-cross-dso";
526 DiagnosedKinds |= SanitizerKind::CFIMFCall;
529 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
530 if (DiagnoseErrors) {
532 D.Diag(diag::err_drv_unsupported_opt_for_target)
535 DiagnosedKinds |= KindsToDiagnose;
543 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
544 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
545 "RTTI disabled without -fno-rtti option?");
549 D.Diag(diag::err_drv_argument_not_allowed_with)
550 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
555 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
559 AllRemove |= SanitizerKind::Vptr;
567 Add &= ~InvalidTrappingKinds;
568 if (MinimalRuntime) {
569 Add &= ~NotAllowedWithMinimalRuntime;
574 Add &= ~NotAllowedWithExecuteOnly;
579 if (Add & SanitizerKind::UndefinedGroup) {
580 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
581 options::OPT_fstrict_overflow,
false);
582 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
584 if (Args.hasFlagNoClaim(options::OPT_fwrapv_pointer,
585 options::OPT_fno_wrapv_pointer, S))
590 if (Add & SanitizerKind::Fuzzer)
591 Add |= SanitizerKind::FuzzerNoLink;
594 if (Add & SanitizerKind::FuzzerNoLink) {
603 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
610 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
611 std::make_pair(SanitizerKind::Address,
612 SanitizerKind::Thread | SanitizerKind::Memory),
613 std::make_pair(SanitizerKind::Type,
614 SanitizerKind::Address | SanitizerKind::KernelAddress |
615 SanitizerKind::Memory | SanitizerKind::Leak |
616 SanitizerKind::Thread | SanitizerKind::KernelAddress),
617 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
618 std::make_pair(SanitizerKind::Leak,
619 SanitizerKind::Thread | SanitizerKind::Memory),
620 std::make_pair(SanitizerKind::KernelAddress,
621 SanitizerKind::Address | SanitizerKind::Leak |
622 SanitizerKind::Thread | SanitizerKind::Memory),
623 std::make_pair(SanitizerKind::HWAddress,
624 SanitizerKind::Address | SanitizerKind::Thread |
625 SanitizerKind::Memory | SanitizerKind::KernelAddress),
626 std::make_pair(SanitizerKind::Scudo,
627 SanitizerKind::Address | SanitizerKind::HWAddress |
628 SanitizerKind::Leak | SanitizerKind::Thread |
629 SanitizerKind::Memory | SanitizerKind::KernelAddress),
630 std::make_pair(SanitizerKind::SafeStack,
632 : SanitizerKind::Leak) |
633 SanitizerKind::Address | SanitizerKind::HWAddress |
634 SanitizerKind::Thread | SanitizerKind::Memory |
635 SanitizerKind::KernelAddress),
636 std::make_pair(SanitizerKind::KernelHWAddress,
637 SanitizerKind::Address | SanitizerKind::HWAddress |
638 SanitizerKind::Leak | SanitizerKind::Thread |
639 SanitizerKind::Memory | SanitizerKind::KernelAddress |
640 SanitizerKind::SafeStack),
641 std::make_pair(SanitizerKind::KernelMemory,
642 SanitizerKind::Address | SanitizerKind::HWAddress |
643 SanitizerKind::Leak | SanitizerKind::Thread |
644 SanitizerKind::Memory | SanitizerKind::KernelAddress |
645 SanitizerKind::Scudo | SanitizerKind::SafeStack),
646 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
647 SanitizerKind::KernelAddress |
648 SanitizerKind::HWAddress |
649 SanitizerKind::KernelHWAddress),
650 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
651 std::make_pair(SanitizerKind::Realtime,
652 SanitizerKind::Address | SanitizerKind::Thread |
653 SanitizerKind::Undefined | SanitizerKind::Memory)};
660 for (
auto G : IncompatibleGroups) {
662 if ((
Default & Group) && (Kinds & G.second))
675 if ((Kinds &
NeedsLTO) && !
D.isUsingLTO() && DiagnoseErrors) {
676 D.Diag(diag::err_drv_argument_only_allowed_with)
680 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
681 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
682 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
683 D.Diag(diag::err_drv_argument_only_allowed_with)
692 if (~Supported & SanitizerKind::Vptr) {
698 if (KindsToDiagnose) {
700 S.Mask = KindsToDiagnose;
702 D.Diag(diag::err_drv_unsupported_opt_for_target)
704 Kinds &= ~KindsToDiagnose;
709 for (
auto G : IncompatibleGroups) {
714 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
717 Kinds &= ~Incompatible;
730 options::OPT_fno_sanitize_recover_EQ);
731 RecoverableKinds &= Kinds;
733 TrappingKinds &= Kinds;
734 RecoverableKinds &= ~TrappingKinds;
739 options::OPT_fsanitize_merge_handlers_EQ,
740 options::OPT_fno_sanitize_merge_handlers_EQ);
749 {}, options::OPT_fsanitize_annotate_debug_info_EQ,
750 options::OPT_fno_sanitize_annotate_debug_info_EQ);
751 AnnotateDebugInfoKinds &= Kinds;
756 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
762 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
763 options::OPT_fno_sanitize_ignorelist,
764 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
767 if (Arg *A = Args.getLastArg(
768 options::OPT_fsanitize_coverage_stack_depth_callback_min_EQ)) {
769 StringRef S = A->getValue();
770 if (S.getAsInteger(0, CoverageStackDepthCallbackMin) ||
771 CoverageStackDepthCallbackMin < 0) {
773 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
778 if (AllAddedKinds & SanitizerKind::Memory) {
780 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
781 options::OPT_fno_sanitize_memory_track_origins)) {
782 if (!A->getOption().matches(
783 options::OPT_fno_sanitize_memory_track_origins)) {
784 StringRef S = A->getValue();
785 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
786 MsanTrackOrigins > 2) {
788 D.Diag(clang::diag::err_drv_invalid_value)
789 << A->getAsString(Args) << S;
793 MsanUseAfterDtor = Args.hasFlag(
794 options::OPT_fsanitize_memory_use_after_dtor,
795 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
796 MsanParamRetval = Args.hasFlag(
797 options::OPT_fsanitize_memory_param_retval,
798 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
799 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
800 MsanUseAfterDtor =
false;
801 MsanParamRetval = Args.hasFlag(
802 options::OPT_fsanitize_memory_param_retval,
803 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
805 MsanUseAfterDtor =
false;
806 MsanParamRetval =
false;
809 if (AllAddedKinds & SanitizerKind::MemTag) {
811 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
812 if (S ==
"async" || S ==
"sync") {
813 MemtagMode = S.str();
815 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
816 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
821 if (AllAddedKinds & SanitizerKind::Thread) {
822 TsanMemoryAccess = Args.hasFlag(
823 options::OPT_fsanitize_thread_memory_access,
824 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
825 TsanFuncEntryExit = Args.hasFlag(
826 options::OPT_fsanitize_thread_func_entry_exit,
827 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
829 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
830 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
833 if (AllAddedKinds & SanitizerKind::CFI) {
836 NeedPIE |= CfiCrossDso;
837 CfiICallGeneralizePointers =
838 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
840 CfiICallNormalizeIntegers =
841 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
843 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
844 D.Diag(diag::err_drv_argument_not_allowed_with)
845 <<
"-fsanitize-cfi-cross-dso"
846 <<
"-fsanitize-cfi-icall-generalize-pointers";
848 CfiCanonicalJumpTables =
849 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
850 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
853 if (AllAddedKinds & SanitizerKind::KCFI) {
854 CfiICallGeneralizePointers =
855 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
856 CfiICallNormalizeIntegers =
857 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
859 KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);
861 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
862 D.Diag(diag::err_drv_argument_not_allowed_with)
867 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
868 options::OPT_fno_sanitize_stats,
false);
870 if (MinimalRuntime) {
873 if (IncompatibleMask && DiagnoseErrors)
874 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
875 <<
"-fsanitize-minimal-runtime"
879 for (
const auto *Arg : Args.filtered(
880 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
882 OverflowPatternExclusions |=
888 for (
const auto *Arg : Args) {
889 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
890 int LegacySanitizeCoverage;
891 if (Arg->getNumValues() == 1 &&
892 !StringRef(Arg->getValue(0))
893 .getAsInteger(0, LegacySanitizeCoverage)) {
894 CoverageFeatures = 0;
896 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
897 D.Diag(diag::warn_drv_deprecated_arg)
898 << Arg->getAsString(Args) <<
true
899 <<
"-fsanitize-coverage=trace-pc-guard";
910 CoverageFeatures = 0;
912 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
914 CoverageFeatures &= ~parseCoverageFeatures(
D, Arg, DiagnoseErrors);
918 if (DiagnoseErrors) {
920 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
921 <<
"-fsanitize-coverage=func"
922 <<
"-fsanitize-coverage=bb";
924 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
925 <<
"-fsanitize-coverage=func"
926 <<
"-fsanitize-coverage=edge";
928 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
929 <<
"-fsanitize-coverage=bb"
930 <<
"-fsanitize-coverage=edge";
934 D.Diag(clang::diag::warn_drv_deprecated_arg)
935 <<
"-fsanitize-coverage=trace-bb" <<
true
936 <<
"-fsanitize-coverage=trace-pc-guard";
938 D.Diag(clang::diag::warn_drv_deprecated_arg)
939 <<
"-fsanitize-coverage=8bit-counters" <<
true
940 <<
"-fsanitize-coverage=trace-pc-guard";
948 if ((CoverageFeatures & InsertionPointTypes) &&
949 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
950 D.Diag(clang::diag::warn_drv_deprecated_arg)
951 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
952 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
957 if (!(CoverageFeatures & InsertionPointTypes)) {
958 if (CoverageFeatures &
971 if (CoverageFeatures) {
973 D, Args, CoverageAllowlistFiles,
974 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
975 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
978 D, Args, CoverageIgnorelistFiles,
979 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
980 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
985 for (
const auto *Arg :
986 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
987 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
988 if (Arg->getOption().matches(
989 options::OPT_fexperimental_sanitize_metadata_EQ)) {
991 BinaryMetadataFeatures |=
995 BinaryMetadataFeatures &=
996 ~parseBinaryMetadataFeatures(
D, Arg, DiagnoseErrors);
1001 if (BinaryMetadataFeatures) {
1003 D, Args, BinaryMetadataIgnorelistFiles,
1004 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
1006 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
1010 SharedRuntime = Args.hasFlag(
1011 options::OPT_shared_libsan, options::OPT_static_libsan,
1014 if (!SharedRuntime && TC.
getTriple().isOSWindows()) {
1016 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
1017 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
1018 << A->getSpelling() << TC.
getTriple().str();
1021 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
1023 if (AllAddedKinds & SanitizerKind::Address) {
1024 NeedPIE |= TC.
getTriple().isOSFuchsia();
1026 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
1027 StringRef S = A->getValue();
1029 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
1030 AsanFieldPadding > 2) &&
1032 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1036 if (Arg *WindowsDebugRTArg =
1037 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
1038 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
1039 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
1040 switch (WindowsDebugRTArg->getOption().getID()) {
1041 case options::OPT__SLASH_MTd:
1042 case options::OPT__SLASH_MDd:
1043 case options::OPT__SLASH_LDd:
1044 if (DiagnoseErrors) {
1045 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1046 << WindowsDebugRTArg->getAsString(Args)
1048 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1053 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1054 options::OPT_fno_sanitize_stable_abi,
false);
1056 AsanPoisonCustomArrayCookie = Args.hasFlag(
1057 options::OPT_fsanitize_address_poison_custom_array_cookie,
1058 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1059 AsanPoisonCustomArrayCookie);
1061 AsanOutlineInstrumentation =
1062 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1063 options::OPT_fno_sanitize_address_outline_instrumentation,
1064 AsanOutlineInstrumentation);
1066 AsanGlobalsDeadStripping = Args.hasFlag(
1067 options::OPT_fsanitize_address_globals_dead_stripping,
1068 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
1074 AsanUseOdrIndicator =
1075 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1076 options::OPT_fno_sanitize_address_use_odr_indicator,
1079 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1080 AsanInvalidPointerCmp =
true;
1083 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1084 AsanInvalidPointerSub =
true;
1088 (Args.hasArg(options::OPT_mkernel) ||
1089 Args.hasArg(options::OPT_fapple_kext))) {
1090 AsanDtorKind = llvm::AsanDtorKind::None;
1093 if (
const auto *Arg =
1094 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1096 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1097 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1098 << Arg->getSpelling() << Arg->getValue();
1100 AsanDtorKind = parsedAsanDtorKind;
1103 if (
const auto *Arg = Args.getLastArg(
1104 options::OPT_sanitize_address_use_after_return_EQ)) {
1105 auto parsedAsanUseAfterReturn =
1107 if (parsedAsanUseAfterReturn ==
1108 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1110 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1111 << Arg->getSpelling() << Arg->getValue();
1113 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1119 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1120 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1122 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1124 SanitizerKind::PointerCompare |
1125 SanitizerKind::PointerSubtract)
1126 <<
"-fsanitize=address";
1130 if (AllAddedKinds & (SanitizerKind::Address | SanitizerKind::KernelAddress)) {
1131 AsanUseAfterScope = Args.hasFlag(
1132 options::OPT_fsanitize_address_use_after_scope,
1133 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1135 AsanUseAfterScope =
false;
1138 if (AllAddedKinds & SanitizerKind::HWAddress) {
1139 if (Arg *HwasanAbiArg =
1140 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1141 HwasanAbi = HwasanAbiArg->getValue();
1142 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1144 D.Diag(clang::diag::err_drv_invalid_value)
1145 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1147 HwasanAbi =
"interceptor";
1149 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1150 HwasanUseAliases = Args.hasFlag(
1151 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1152 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1156 if (AllAddedKinds & SanitizerKind::SafeStack) {
1162 LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
1163 options::OPT_fno_sanitize_link_runtime,
1164 !Args.hasArg(options::OPT_r));
1167 LinkCXXRuntimes =
D.CCCIsCXX();
1169 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1170 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1172 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1173 options::OPT_fmemory_profile_EQ,
1174 options::OPT_fno_memory_profile,
false);
1177 Sanitizers.
Mask |= Kinds;
1178 RecoverableSanitizers.
Mask |= RecoverableKinds;
1179 TrapSanitizers.
Mask |= TrappingKinds;
1180 assert(!(RecoverableKinds & TrappingKinds) &&
1181 "Overlap between recoverable and trapping sanitizers");
1183 MergeHandlers.
Mask |= MergeKinds;
1185 AnnotateDebugInfo.
Mask |= AnnotateDebugInfoKinds;
1193#define SANITIZER(NAME, ID) \
1194 if (Sanitizers.has(SanitizerKind::ID)) { \
1199#include "clang/Basic/Sanitizers.def"
1206 return llvm::join(Res,
",");
1211#define SANITIZER(NAME, ID) \
1212 if (Sanitizers.has(SanitizerKind::ID)) { \
1217#define SANITIZER_GROUP(NAME, ID, ALIAS) SANITIZER(NAME, ID##Group)
1218#include "clang/Basic/Sanitizers.def"
1223 llvm::opt::ArgStringList &CmdArgs,
1224 const char *SCLOptFlag,
1225 const std::vector<std::string> &SCLFiles) {
1226 for (
const auto &SCLPath : SCLFiles) {
1229 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1234 const llvm::opt::ArgList &Args,
1235 llvm::opt::ArgStringList &CmdArgs,
1236 StringRef SymbolName) {
1238 LinkerOptionFlag =
"--linker-option=/include:";
1239 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1241 LinkerOptionFlag +=
'_';
1243 LinkerOptionFlag += SymbolName;
1244 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1248 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1250 auto It = std::find(Start, End, StringRef(
"+mte"));
1253 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1261 llvm::opt::ArgStringList &CmdArgs,
1269 bool GPUSanitize =
false;
1271 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1280 std::pair<int, const char *> CoverageFlags[] = {
1281 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1282 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1283 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1292 "-fsanitize-coverage-trace-pc-guard"),
1294 "-fsanitize-coverage-inline-8bit-counters"),
1296 "-fsanitize-coverage-inline-bool-flag"),
1303 for (
auto F : CoverageFlags) {
1304 if (CoverageFeatures & F.first)
1305 CmdArgs.push_back(F.second);
1308 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1310 CoverageIgnorelistFiles);
1312 if (CoverageStackDepthCallbackMin)
1314 Args.MakeArgString(
"-fsanitize-coverage-stack-depth-callback-min=" +
1315 Twine(CoverageStackDepthCallbackMin)));
1320 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1324 for (
const auto &F : BinaryMetadataFlags) {
1325 if (BinaryMetadataFeatures & F.first)
1327 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1330 "-fexperimental-sanitize-metadata-ignorelist=",
1331 BinaryMetadataIgnorelistFiles);
1335 Args.hasFlag(options::OPT_frtlib_defaultlib,
1336 options::OPT_fno_rtlib_defaultlib,
true)) {
1340 Args.MakeArgString(
"--dependent-lib=" +
1343 CmdArgs.push_back(Args.MakeArgString(
1344 "--dependent-lib=" +
1348 Args.hasFlag(options::OPT_frtlib_defaultlib,
1349 options::OPT_fno_rtlib_defaultlib,
true)) {
1350 CmdArgs.push_back(Args.MakeArgString(
1357 CmdArgs.push_back(Args.MakeArgString(
1362 if (Sanitizers.
empty())
1364 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1366 if (!RecoverableSanitizers.
empty())
1367 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1370 if (!TrapSanitizers.
empty())
1372 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1374 if (!MergeHandlers.
empty())
1376 Args.MakeArgString(
"-fsanitize-merge=" +
toString(MergeHandlers)));
1378 std::string SkipHotCutoffsStr =
toString(SkipHotCutoffs);
1379 if (!SkipHotCutoffsStr.empty())
1381 Args.MakeArgString(
"-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1383 if (!AnnotateDebugInfo.
empty())
1384 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-annotate-debug-info=" +
1387 Args.AddLastArg(CmdArgs, options::OPT_fsanitize_debug_trap_reasons_EQ);
1390 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1392 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1394 if (OverflowPatternExclusions)
1396 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1398 if (MsanTrackOrigins)
1399 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1400 Twine(MsanTrackOrigins)));
1402 if (MsanUseAfterDtor)
1403 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1405 if (!MsanParamRetval)
1406 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1409 if (!TsanMemoryAccess) {
1410 CmdArgs.push_back(
"-mllvm");
1411 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1412 CmdArgs.push_back(
"-mllvm");
1413 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1415 if (!TsanFuncEntryExit) {
1416 CmdArgs.push_back(
"-mllvm");
1417 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1420 CmdArgs.push_back(
"-mllvm");
1421 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1424 if (HwasanUseAliases) {
1425 CmdArgs.push_back(
"-mllvm");
1426 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1430 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1432 if (CfiICallGeneralizePointers)
1433 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1435 if (CfiICallNormalizeIntegers)
1436 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1440 TC.
getDriver().
Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)
1443 CmdArgs.push_back(
"-fsanitize-kcfi-arity");
1446 if (CfiCanonicalJumpTables)
1447 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1450 CmdArgs.push_back(
"-fsanitize-stats");
1453 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1455 if (AsanFieldPadding)
1456 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1457 Twine(AsanFieldPadding)));
1459 if (AsanUseAfterScope)
1460 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1462 if (AsanPoisonCustomArrayCookie)
1463 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1465 if (AsanGlobalsDeadStripping)
1466 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1468 if (!AsanUseOdrIndicator)
1469 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1471 if (AsanInvalidPointerCmp) {
1472 CmdArgs.push_back(
"-mllvm");
1473 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1476 if (AsanInvalidPointerSub) {
1477 CmdArgs.push_back(
"-mllvm");
1478 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1481 if (AsanOutlineInstrumentation) {
1482 CmdArgs.push_back(
"-mllvm");
1483 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1490 CmdArgs.push_back(
"-mllvm");
1491 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1492 CmdArgs.push_back(
"-mllvm");
1493 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1494 CmdArgs.push_back(
"-mllvm");
1495 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1500 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1501 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1505 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1506 CmdArgs.push_back(Args.MakeArgString(
1507 "-fsanitize-address-use-after-return=" +
1511 if (!HwasanAbi.empty()) {
1512 CmdArgs.push_back(
"-default-function-attr");
1513 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1516 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1517 CmdArgs.push_back(
"-target-feature");
1518 CmdArgs.push_back(
"+tagged-globals");
1526 if (Sanitizers.
has(SanitizerKind::Memory) ||
1527 Sanitizers.
has(SanitizerKind::Address))
1528 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1535 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1536 CmdArgs.push_back(
"-fno-builtin-bcmp");
1537 CmdArgs.push_back(
"-fno-builtin-memcmp");
1538 CmdArgs.push_back(
"-fno-builtin-strncmp");
1539 CmdArgs.push_back(
"-fno-builtin-strcmp");
1540 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1541 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1542 CmdArgs.push_back(
"-fno-builtin-strstr");
1543 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1544 CmdArgs.push_back(
"-fno-builtin-memmem");
1550 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1551 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1557 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1559 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1563 bool DiagnoseErrors) {
1565 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1566 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1567 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1568 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1569 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1570 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1571 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1572 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
1573 A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
1574 A->getOption().matches(
1575 options::OPT_fno_sanitize_annotate_debug_info_EQ)) &&
1576 "Invalid argument in parseArgValues!");
1578 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1579 const char *
Value = A->getValue(i);
1582 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1583 0 == strcmp(
"all",
Value))
1590 else if (DiagnoseErrors)
1591 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1592 << A->getSpelling() <<
Value;
1599 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1600 "Invalid argument in parseArgCutoffs!");
1601 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1602 const char *
Value = A->getValue(i);
1608 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1609 << A->getSpelling() <<
Value;
1614 const llvm::opt::Arg *A,
1615 bool DiagnoseErrors) {
1617 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1618 const char *
Value = A->getValue(i);
1620 llvm::StringSwitch<int>(
Value)
1623 .Case(
"add-unsigned-overflow-test",
1625 .Case(
"add-signed-overflow-test",
1631 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1632 << A->getSpelling() <<
Value;
1639 bool DiagnoseErrors) {
1640 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1641 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1643 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1644 const char *
Value = A->getValue(i);
1645 int F = llvm::StringSwitch<int>(
Value)
1666 if (F == 0 && DiagnoseErrors)
1667 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1668 << A->getSpelling() <<
Value;
1675 bool DiagnoseErrors) {
1677 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1678 A->getOption().matches(
1679 options::OPT_fno_experimental_sanitize_metadata_EQ));
1681 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1682 const char *
Value = A->getValue(i);
1683 int F = llvm::StringSwitch<int>(
Value)
1689 if (F == 0 && DiagnoseErrors)
1690 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1691 << A->getSpelling() <<
Value;
1699 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1702 const auto *Arg = *I;
1703 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1706 if (AddKinds & Mask)
1708 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1711 Mask &= ~RemoveKinds;
1714 llvm_unreachable(
"arg list didn't provide expected value");
1718 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1719 "Invalid argument in describeSanitizerArg!");
1721 std::string Sanitizers;
1722 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1726 if (!Sanitizers.empty())
1728 Sanitizers += A->getValue(i);
1732 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1733 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 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 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 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
@ CoverageInline8bitCounters
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–)
void clear(SanitizerMask K=SanitizerKind::All)
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 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 needsCfiCrossDsoDiagRt() const
bool requiresMinimalRuntime() const
bool needsUnwindTables() const
bool needsDfsanRt() const
bool needsScudoRt() const
bool needsUbsanCXXRt() const
bool needsCfiCrossDsoRt() 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)
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.
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)
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.