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;
35 SanitizerKind::Vptr | SanitizerKind::CFI;
39 SanitizerKind::Function | SanitizerKind::KCFI;
41 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
42 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
43 SanitizerKind::NumericalStability;
45 SanitizerKind::Address | SanitizerKind::HWAddress |
46 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
47 SanitizerKind::Type | SanitizerKind::MemtagStack |
48 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
49 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
50 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
51 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
52 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
53 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
54 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
55 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
56 SanitizerKind::NumericalStability;
58 SanitizerKind::Undefined | SanitizerKind::Integer |
59 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
60 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
62 SanitizerKind::Unreachable | SanitizerKind::Return;
64 SanitizerKind::KernelHWAddress |
68 (SanitizerKind::Undefined &
~SanitizerKind::Vptr) | SanitizerKind::Integer |
69 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
70 SanitizerKind::LocalBounds | SanitizerKind::CFI |
71 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
74 SanitizerKind::CFI | SanitizerKind::LocalBounds;
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);
126 bool DiagnoseErrors);
131 const llvm::opt::Arg *A,
132 bool DiagnoseErrors);
137 bool DiagnoseErrors);
144 const llvm::opt::ArgList &Args,
161 const llvm::opt::ArgList &Args) {
164 return Args.hasFlagNoClaim(options::OPT_mexecute_only,
165 options::OPT_mno_execute_only,
false);
169 std::vector<std::string> &SCLFiles,
170 unsigned MalformedSCLErrorDiagID,
171 bool DiagnoseErrors) {
172 if (SCLFiles.empty())
176 std::unique_ptr<llvm::SpecialCaseList> SCL(
177 llvm::SpecialCaseList::create(SCLFiles,
D.getVFS(), BLError));
178 if (!SCL.get() && DiagnoseErrors)
179 D.Diag(MalformedSCLErrorDiagID) << BLError;
183 std::vector<std::string> &IgnorelistFiles,
184 bool DiagnoseErrors) {
188 } Ignorelists[] = {{
"asan_ignorelist.txt", SanitizerKind::Address},
189 {
"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
190 {
"memtag_ignorelist.txt", SanitizerKind::MemTag},
191 {
"msan_ignorelist.txt", SanitizerKind::Memory},
192 {
"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
193 {
"tsan_ignorelist.txt", SanitizerKind::Thread},
194 {
"tysan_blacklist.txt", SanitizerKind::Type},
195 {
"dfsan_abilist.txt", SanitizerKind::DataFlow},
196 {
"cfi_ignorelist.txt", SanitizerKind::CFI},
197 {
"ubsan_ignorelist.txt",
198 SanitizerKind::Undefined | SanitizerKind::Integer |
199 SanitizerKind::Nullability |
200 SanitizerKind::FloatDivideByZero}};
202 for (
auto BL : Ignorelists) {
203 if (!(Kinds & BL.Mask))
207 llvm::sys::path::append(
Path,
"share", BL.File);
208 if (
D.getVFS().exists(
Path))
209 IgnorelistFiles.push_back(std::string(
Path));
210 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
213 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) <<
Path;
216 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
223 const llvm::opt::ArgList &Args,
224 std::vector<std::string> &SCLFiles,
225 llvm::opt::OptSpecifier SCLOptionID,
226 llvm::opt::OptSpecifier NoSCLOptionID,
227 unsigned MalformedSCLErrorDiagID,
228 bool DiagnoseErrors) {
229 for (
const auto *Arg : Args) {
231 if (Arg->getOption().matches(SCLOptionID)) {
233 std::string SCLPath = Arg->getValue();
234 if (
D.getVFS().exists(SCLPath)) {
235 SCLFiles.push_back(SCLPath);
236 }
else if (DiagnoseErrors) {
237 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
240 }
else if (Arg->getOption().matches(NoSCLOptionID)) {
252#define SANITIZER(NAME, ID)
253#define SANITIZER_GROUP(NAME, ID, ALIAS) \
254 if (Kinds & SanitizerKind::ID) \
255 Kinds |= SanitizerKind::ID##Group;
256#include "clang/Basic/Sanitizers.def"
271 assert(!(AlwaysIn & AlwaysOut) &&
272 "parseSanitizeArgs called with contradictory in/out requirements");
279 for (
const auto *Arg : Args) {
280 if (Arg->getOption().matches(OptInID)) {
285 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
286 if (DiagnoseErrors) {
288 SetToDiagnose.
Mask |= KindsToDiagnose;
289 D.Diag(diag::err_drv_unsupported_option_argument)
290 << Arg->getSpelling() <<
toString(SetToDiagnose);
291 DiagnosedAlwaysOutViolations |= KindsToDiagnose;
296 }
else if (Arg->getOption().matches(OptOutID)) {
301 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
302 if (DiagnoseErrors) {
304 SetToDiagnose.
Mask |= KindsToDiagnose;
305 D.Diag(diag::err_drv_unsupported_option_argument)
306 << Arg->getSpelling() <<
toString(SetToDiagnose);
307 DiagnosedAlwaysInViolations |= KindsToDiagnose;
310 Output &= ~expandSanitizerGroups(Remove);
319 const llvm::opt::ArgList &Args,
320 bool DiagnoseErrors) {
329 NeverTrap, options::OPT_fsanitize_trap_EQ,
330 options::OPT_fno_sanitize_trap_EQ);
335 bool DiagnoseErrors) {
337 for (
const auto *Arg : Args)
338 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {
366 ~TrapSanitizers.Mask);
370 return !(Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
371 CfiCrossDso && !ImplicitCfiRuntime;
375 return (Sanitizers.
Mask & SanitizerKind::CFI & ~TrapSanitizers.
Mask) &&
376 CfiCrossDso && !ImplicitCfiRuntime;
390 const llvm::opt::ArgList &Args,
391 bool DiagnoseErrors) {
405 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
406 options::OPT_fno_sanitize_cfi_cross_dso,
false);
415 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,
416 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);
419 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);
420 bool RemoveObjectSizeAtO0 =
421 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);
423 for (
const llvm::opt::Arg *Arg : llvm::reverse(Args)) {
424 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
428 if (RemoveObjectSizeAtO0) {
429 AllRemove |= SanitizerKind::ObjectSize;
433 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)
434 D.Diag(diag::warn_drv_object_size_disabled_O0)
435 << Arg->getAsString(Args);
446 Add & InvalidTrappingKinds & ~DiagnosedKinds) {
447 if (DiagnoseErrors) {
449 D.Diag(diag::err_drv_argument_not_allowed_with)
450 << Desc <<
"-fsanitize-trap=undefined";
452 DiagnosedKinds |= KindsToDiagnose;
454 Add &= ~InvalidTrappingKinds;
456 if (MinimalRuntime) {
459 if (DiagnoseErrors) {
461 D.Diag(diag::err_drv_argument_not_allowed_with)
462 << Desc <<
"-fsanitize-minimal-runtime";
464 DiagnosedKinds |= KindsToDiagnose;
466 Add &= ~NotAllowedWithMinimalRuntime;
469 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
470 StringRef CM = A->getValue();
472 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
474 D.Diag(diag::err_drv_argument_only_allowed_with)
475 <<
"-fsanitize=function"
478 DiagnosedKinds |= SanitizerKind::Function;
484 const llvm::Triple &Triple = TC.
getTriple();
488 if (DiagnoseErrors) {
490 llvm::opt::Arg *A = Args.getLastArgNoClaim(
491 options::OPT_mexecute_only, options::OPT_mno_execute_only);
492 if (A && A->getOption().matches(options::OPT_mexecute_only))
493 D.Diag(diag::err_drv_argument_not_allowed_with)
494 << Desc << A->getAsString(Args);
496 D.Diag(diag::err_drv_unsupported_opt_for_target)
497 << Desc << Triple.str();
499 DiagnosedKinds |= KindsToDiagnose;
501 Add &= ~NotAllowedWithExecuteOnly;
514 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
516 D.Diag(diag::err_drv_argument_not_allowed_with)
517 <<
"-fsanitize=cfi-mfcall"
518 <<
"-fsanitize-cfi-cross-dso";
520 DiagnosedKinds |= SanitizerKind::CFIMFCall;
523 if (
SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
524 if (DiagnoseErrors) {
526 D.Diag(diag::err_drv_unsupported_opt_for_target)
529 DiagnosedKinds |= KindsToDiagnose;
537 if (
const llvm::opt::Arg *NoRTTIArg = TC.
getRTTIArg()) {
538 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
539 "RTTI disabled without -fno-rtti option?");
543 D.Diag(diag::err_drv_argument_not_allowed_with)
544 <<
"-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
549 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
553 AllRemove |= SanitizerKind::Vptr;
561 Add &= ~InvalidTrappingKinds;
562 if (MinimalRuntime) {
563 Add &= ~NotAllowedWithMinimalRuntime;
568 Add &= ~NotAllowedWithExecuteOnly;
573 if (Add & SanitizerKind::UndefinedGroup) {
574 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,
575 options::OPT_fstrict_overflow,
false);
576 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
581 if (Add & SanitizerKind::Fuzzer)
582 Add |= SanitizerKind::FuzzerNoLink;
585 if (Add & SanitizerKind::FuzzerNoLink) {
594 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
601 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
602 std::make_pair(SanitizerKind::Address,
603 SanitizerKind::Thread | SanitizerKind::Memory),
604 std::make_pair(SanitizerKind::Type,
605 SanitizerKind::Address | SanitizerKind::KernelAddress |
606 SanitizerKind::Memory | SanitizerKind::Leak |
607 SanitizerKind::Thread | SanitizerKind::KernelAddress),
608 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
609 std::make_pair(SanitizerKind::Leak,
610 SanitizerKind::Thread | SanitizerKind::Memory),
611 std::make_pair(SanitizerKind::KernelAddress,
612 SanitizerKind::Address | SanitizerKind::Leak |
613 SanitizerKind::Thread | SanitizerKind::Memory),
614 std::make_pair(SanitizerKind::HWAddress,
615 SanitizerKind::Address | SanitizerKind::Thread |
616 SanitizerKind::Memory | SanitizerKind::KernelAddress),
617 std::make_pair(SanitizerKind::Scudo,
618 SanitizerKind::Address | SanitizerKind::HWAddress |
619 SanitizerKind::Leak | SanitizerKind::Thread |
620 SanitizerKind::Memory | SanitizerKind::KernelAddress),
621 std::make_pair(SanitizerKind::SafeStack,
623 : SanitizerKind::Leak) |
624 SanitizerKind::Address | SanitizerKind::HWAddress |
625 SanitizerKind::Thread | SanitizerKind::Memory |
626 SanitizerKind::KernelAddress),
627 std::make_pair(SanitizerKind::KernelHWAddress,
628 SanitizerKind::Address | SanitizerKind::HWAddress |
629 SanitizerKind::Leak | SanitizerKind::Thread |
630 SanitizerKind::Memory | SanitizerKind::KernelAddress |
631 SanitizerKind::SafeStack),
632 std::make_pair(SanitizerKind::KernelMemory,
633 SanitizerKind::Address | SanitizerKind::HWAddress |
634 SanitizerKind::Leak | SanitizerKind::Thread |
635 SanitizerKind::Memory | SanitizerKind::KernelAddress |
636 SanitizerKind::Scudo | SanitizerKind::SafeStack),
637 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |
638 SanitizerKind::KernelAddress |
639 SanitizerKind::HWAddress |
640 SanitizerKind::KernelHWAddress),
641 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),
642 std::make_pair(SanitizerKind::Realtime,
643 SanitizerKind::Address | SanitizerKind::Thread |
644 SanitizerKind::Undefined | SanitizerKind::Memory)};
651 for (
auto G : IncompatibleGroups) {
653 if ((
Default & Group) && (Kinds & G.second))
666 if ((Kinds &
NeedsLTO) && !
D.isUsingLTO() && DiagnoseErrors) {
667 D.Diag(diag::err_drv_argument_only_allowed_with)
671 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.
getTriple().isAArch64() &&
672 !llvm::AArch64::isX18ReservedByDefault(TC.
getTriple()) &&
673 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
674 D.Diag(diag::err_drv_argument_only_allowed_with)
683 if (~Supported & SanitizerKind::Vptr) {
689 if (KindsToDiagnose) {
691 S.Mask = KindsToDiagnose;
693 D.Diag(diag::err_drv_unsupported_opt_for_target)
695 Kinds &= ~KindsToDiagnose;
700 for (
auto G : IncompatibleGroups) {
705 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
708 Kinds &= ~Incompatible;
721 options::OPT_fno_sanitize_recover_EQ);
723 RecoverableKinds &= ~Unrecoverable;
724 RecoverableKinds &= Kinds;
726 TrappingKinds &= Kinds;
727 RecoverableKinds &= ~TrappingKinds;
732 options::OPT_fsanitize_merge_handlers_EQ,
733 options::OPT_fno_sanitize_merge_handlers_EQ);
742 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
748 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,
749 options::OPT_fno_sanitize_ignorelist,
750 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);
753 if (AllAddedKinds & SanitizerKind::Memory) {
755 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
756 options::OPT_fno_sanitize_memory_track_origins)) {
757 if (!A->getOption().matches(
758 options::OPT_fno_sanitize_memory_track_origins)) {
759 StringRef S = A->getValue();
760 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
761 MsanTrackOrigins > 2) {
763 D.Diag(clang::diag::err_drv_invalid_value)
764 << A->getAsString(Args) << S;
768 MsanUseAfterDtor = Args.hasFlag(
769 options::OPT_fsanitize_memory_use_after_dtor,
770 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
771 MsanParamRetval = Args.hasFlag(
772 options::OPT_fsanitize_memory_param_retval,
773 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
774 }
else if (AllAddedKinds & SanitizerKind::KernelMemory) {
775 MsanUseAfterDtor =
false;
776 MsanParamRetval = Args.hasFlag(
777 options::OPT_fsanitize_memory_param_retval,
778 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
780 MsanUseAfterDtor =
false;
781 MsanParamRetval =
false;
784 if (AllAddedKinds & SanitizerKind::MemTag) {
786 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ,
"sync");
787 if (S ==
"async" || S ==
"sync") {
788 MemtagMode = S.str();
790 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
791 <<
"-fsanitize-memtag-mode=" << S <<
"{async, sync}";
796 if (AllAddedKinds & SanitizerKind::Thread) {
797 TsanMemoryAccess = Args.hasFlag(
798 options::OPT_fsanitize_thread_memory_access,
799 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
800 TsanFuncEntryExit = Args.hasFlag(
801 options::OPT_fsanitize_thread_func_entry_exit,
802 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
804 Args.hasFlag(options::OPT_fsanitize_thread_atomics,
805 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
808 if (AllAddedKinds & SanitizerKind::CFI) {
811 NeedPIE |= CfiCrossDso;
812 CfiICallGeneralizePointers =
813 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
815 CfiICallNormalizeIntegers =
816 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
818 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
819 D.Diag(diag::err_drv_argument_not_allowed_with)
820 <<
"-fsanitize-cfi-cross-dso"
821 <<
"-fsanitize-cfi-icall-generalize-pointers";
823 CfiCanonicalJumpTables =
824 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,
825 options::OPT_fno_sanitize_cfi_canonical_jump_tables,
true);
828 if (AllAddedKinds & SanitizerKind::KCFI) {
829 CfiICallNormalizeIntegers =
830 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
832 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
833 D.Diag(diag::err_drv_argument_not_allowed_with)
838 Stats = Args.hasFlag(options::OPT_fsanitize_stats,
839 options::OPT_fno_sanitize_stats,
false);
841 if (MinimalRuntime) {
844 if (IncompatibleMask && DiagnoseErrors)
845 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
846 <<
"-fsanitize-minimal-runtime"
849 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
850 if (NonTrappingCfi && DiagnoseErrors)
851 D.Diag(clang::diag::err_drv_argument_only_allowed_with)
852 <<
"fsanitize-minimal-runtime"
853 <<
"fsanitize-trap=cfi";
856 for (
const auto *Arg : Args.filtered(
857 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {
859 OverflowPatternExclusions |=
865 for (
const auto *Arg : Args) {
866 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {
867 int LegacySanitizeCoverage;
868 if (Arg->getNumValues() == 1 &&
869 !StringRef(Arg->getValue(0))
870 .getAsInteger(0, LegacySanitizeCoverage)) {
871 CoverageFeatures = 0;
873 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
874 D.Diag(diag::warn_drv_deprecated_arg)
875 << Arg->getAsString(Args) <<
true
876 <<
"-fsanitize-coverage=trace-pc-guard";
887 CoverageFeatures = 0;
889 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {
891 CoverageFeatures &= ~parseCoverageFeatures(
D, Arg, DiagnoseErrors);
895 if (DiagnoseErrors) {
897 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
898 <<
"-fsanitize-coverage=func"
899 <<
"-fsanitize-coverage=bb";
901 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
902 <<
"-fsanitize-coverage=func"
903 <<
"-fsanitize-coverage=edge";
905 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
906 <<
"-fsanitize-coverage=bb"
907 <<
"-fsanitize-coverage=edge";
911 D.Diag(clang::diag::warn_drv_deprecated_arg)
912 <<
"-fsanitize-coverage=trace-bb" <<
true
913 <<
"-fsanitize-coverage=trace-pc-guard";
915 D.Diag(clang::diag::warn_drv_deprecated_arg)
916 <<
"-fsanitize-coverage=8bit-counters" <<
true
917 <<
"-fsanitize-coverage=trace-pc-guard";
925 if ((CoverageFeatures & InsertionPointTypes) &&
926 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
927 D.Diag(clang::diag::warn_drv_deprecated_arg)
928 <<
"-fsanitize-coverage=[func|bb|edge]" <<
true
929 <<
"-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
934 if (!(CoverageFeatures & InsertionPointTypes)) {
935 if (CoverageFeatures &
948 if (CoverageFeatures) {
950 D, Args, CoverageAllowlistFiles,
951 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
952 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,
955 D, Args, CoverageIgnorelistFiles,
956 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
957 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,
962 for (
const auto *Arg :
963 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,
964 options::OPT_fno_experimental_sanitize_metadata_EQ)) {
965 if (Arg->getOption().matches(
966 options::OPT_fexperimental_sanitize_metadata_EQ)) {
968 BinaryMetadataFeatures |=
972 BinaryMetadataFeatures &=
973 ~parseBinaryMetadataFeatures(
D, Arg, DiagnoseErrors);
978 if (BinaryMetadataFeatures) {
980 D, Args, BinaryMetadataIgnorelistFiles,
981 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,
983 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,
987 SharedRuntime = Args.hasFlag(
988 options::OPT_shared_libsan, options::OPT_static_libsan,
991 if (!SharedRuntime && TC.
getTriple().isOSWindows()) {
993 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
994 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
995 << A->getSpelling() << TC.
getTriple().str();
998 ImplicitCfiRuntime = TC.
getTriple().isAndroid();
1000 if (AllAddedKinds & SanitizerKind::Address) {
1001 NeedPIE |= TC.
getTriple().isOSFuchsia();
1003 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
1004 StringRef S = A->getValue();
1006 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
1007 AsanFieldPadding > 2) &&
1009 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1013 if (Arg *WindowsDebugRTArg =
1014 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,
1015 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,
1016 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {
1017 switch (WindowsDebugRTArg->getOption().getID()) {
1018 case options::OPT__SLASH_MTd:
1019 case options::OPT__SLASH_MDd:
1020 case options::OPT__SLASH_LDd:
1021 if (DiagnoseErrors) {
1022 D.Diag(clang::diag::err_drv_argument_not_allowed_with)
1023 << WindowsDebugRTArg->getAsString(Args)
1025 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
1030 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,
1031 options::OPT_fno_sanitize_stable_abi,
false);
1033 AsanUseAfterScope = Args.hasFlag(
1034 options::OPT_fsanitize_address_use_after_scope,
1035 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
1037 AsanPoisonCustomArrayCookie = Args.hasFlag(
1038 options::OPT_fsanitize_address_poison_custom_array_cookie,
1039 options::OPT_fno_sanitize_address_poison_custom_array_cookie,
1040 AsanPoisonCustomArrayCookie);
1042 AsanOutlineInstrumentation =
1043 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
1044 options::OPT_fno_sanitize_address_outline_instrumentation,
1045 AsanOutlineInstrumentation);
1047 AsanGlobalsDeadStripping = Args.hasFlag(
1048 options::OPT_fsanitize_address_globals_dead_stripping,
1049 options::OPT_fno_sanitize_address_globals_dead_stripping,
true);
1055 AsanUseOdrIndicator =
1056 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
1057 options::OPT_fno_sanitize_address_use_odr_indicator,
1060 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {
1061 AsanInvalidPointerCmp =
true;
1064 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {
1065 AsanInvalidPointerSub =
true;
1069 (Args.hasArg(options::OPT_mkernel) ||
1070 Args.hasArg(options::OPT_fapple_kext))) {
1071 AsanDtorKind = llvm::AsanDtorKind::None;
1074 if (
const auto *Arg =
1075 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
1077 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {
1078 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1079 << Arg->getSpelling() << Arg->getValue();
1081 AsanDtorKind = parsedAsanDtorKind;
1084 if (
const auto *Arg = Args.getLastArg(
1085 options::OPT_sanitize_address_use_after_return_EQ)) {
1086 auto parsedAsanUseAfterReturn =
1088 if (parsedAsanUseAfterReturn ==
1089 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&
1091 TC.
getDriver().
Diag(clang::diag::err_drv_unsupported_option_argument)
1092 << Arg->getSpelling() << Arg->getValue();
1094 AsanUseAfterReturn = parsedAsanUseAfterReturn;
1098 AsanUseAfterScope =
false;
1101 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;
1102 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&
1104 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1106 SanitizerKind::PointerCompare |
1107 SanitizerKind::PointerSubtract)
1108 <<
"-fsanitize=address";
1112 if (AllAddedKinds & SanitizerKind::HWAddress) {
1113 if (Arg *HwasanAbiArg =
1114 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
1115 HwasanAbi = HwasanAbiArg->getValue();
1116 if (HwasanAbi !=
"platform" && HwasanAbi !=
"interceptor" &&
1118 D.Diag(clang::diag::err_drv_invalid_value)
1119 << HwasanAbiArg->getAsString(Args) << HwasanAbi;
1121 HwasanAbi =
"interceptor";
1123 if (TC.
getTriple().getArch() == llvm::Triple::x86_64)
1124 HwasanUseAliases = Args.hasFlag(
1125 options::OPT_fsanitize_hwaddress_experimental_aliasing,
1126 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
1130 if (AllAddedKinds & SanitizerKind::SafeStack) {
1137 Args.hasFlag(options::OPT_fsanitize_link_runtime,
1138 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
1141 LinkCXXRuntimes =
D.CCCIsCXX();
1143 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
1144 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
1146 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
1147 options::OPT_fmemory_profile_EQ,
1148 options::OPT_fno_memory_profile,
false);
1151 Sanitizers.
Mask |= Kinds;
1152 RecoverableSanitizers.
Mask |= RecoverableKinds;
1153 TrapSanitizers.
Mask |= TrappingKinds;
1154 assert(!(RecoverableKinds & TrappingKinds) &&
1155 "Overlap between recoverable and trapping sanitizers");
1157 MergeHandlers.
Mask |= MergeKinds;
1165#define SANITIZER(NAME, ID) \
1166 if (Sanitizers.has(SanitizerKind::ID)) { \
1171#include "clang/Basic/Sanitizers.def"
1178 return llvm::join(Res,
",");
1182 llvm::opt::ArgStringList &CmdArgs,
1183 const char *SCLOptFlag,
1184 const std::vector<std::string> &SCLFiles) {
1185 for (
const auto &SCLPath : SCLFiles) {
1188 CmdArgs.push_back(Args.MakeArgString(SCLOpt));
1193 const llvm::opt::ArgList &Args,
1194 llvm::opt::ArgStringList &CmdArgs,
1195 StringRef SymbolName) {
1197 LinkerOptionFlag =
"--linker-option=/include:";
1198 if (TC.
getTriple().getArch() == llvm::Triple::x86) {
1200 LinkerOptionFlag +=
'_';
1202 LinkerOptionFlag += SymbolName;
1203 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));
1207 for (
auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
1209 auto It = std::find(Start, End, StringRef(
"+mte"));
1212 if (It > Start && *std::prev(It) == StringRef(
"-target-feature"))
1220 llvm::opt::ArgStringList &CmdArgs,
1228 bool GPUSanitize =
false;
1230 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
1239 std::pair<int, const char *> CoverageFlags[] = {
1240 std::make_pair(
CoverageFunc,
"-fsanitize-coverage-type=1"),
1241 std::make_pair(
CoverageBB,
"-fsanitize-coverage-type=2"),
1242 std::make_pair(
CoverageEdge,
"-fsanitize-coverage-type=3"),
1251 "-fsanitize-coverage-trace-pc-guard"),
1253 "-fsanitize-coverage-inline-8bit-counters"),
1255 "-fsanitize-coverage-inline-bool-flag"),
1262 for (
auto F : CoverageFlags) {
1263 if (CoverageFeatures & F.first)
1264 CmdArgs.push_back(F.second);
1267 Args, CmdArgs,
"-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
1269 CoverageIgnorelistFiles);
1274 const std::pair<int, std::string> BinaryMetadataFlags[] = {
1278 for (
const auto &F : BinaryMetadataFlags) {
1279 if (BinaryMetadataFeatures & F.first)
1281 Args.MakeArgString(
"-fexperimental-sanitize-metadata=" + F.second));
1284 "-fexperimental-sanitize-metadata-ignorelist=",
1285 BinaryMetadataIgnorelistFiles);
1289 Args.hasFlag(options::OPT_frtlib_defaultlib,
1290 options::OPT_fno_rtlib_defaultlib,
true)) {
1294 Args.MakeArgString(
"--dependent-lib=" +
1297 CmdArgs.push_back(Args.MakeArgString(
1298 "--dependent-lib=" +
1302 Args.hasFlag(options::OPT_frtlib_defaultlib,
1303 options::OPT_fno_rtlib_defaultlib,
true)) {
1304 CmdArgs.push_back(Args.MakeArgString(
1311 CmdArgs.push_back(Args.MakeArgString(
1316 if (Sanitizers.
empty())
1318 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize=" +
toString(Sanitizers)));
1320 if (!RecoverableSanitizers.
empty())
1321 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-recover=" +
1324 if (!TrapSanitizers.
empty())
1326 Args.MakeArgString(
"-fsanitize-trap=" +
toString(TrapSanitizers)));
1328 if (!MergeHandlers.
empty())
1330 Args.MakeArgString(
"-fsanitize-merge=" +
toString(MergeHandlers)));
1332 std::string SkipHotCutoffsStr =
toString(SkipHotCutoffs);
1333 if (!SkipHotCutoffsStr.empty())
1335 Args.MakeArgString(
"-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
1338 "-fsanitize-ignorelist=", UserIgnorelistFiles);
1340 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
1342 if (OverflowPatternExclusions)
1344 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);
1346 if (MsanTrackOrigins)
1347 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-memory-track-origins=" +
1348 Twine(MsanTrackOrigins)));
1350 if (MsanUseAfterDtor)
1351 CmdArgs.push_back(
"-fsanitize-memory-use-after-dtor");
1353 if (!MsanParamRetval)
1354 CmdArgs.push_back(
"-fno-sanitize-memory-param-retval");
1357 if (!TsanMemoryAccess) {
1358 CmdArgs.push_back(
"-mllvm");
1359 CmdArgs.push_back(
"-tsan-instrument-memory-accesses=0");
1360 CmdArgs.push_back(
"-mllvm");
1361 CmdArgs.push_back(
"-tsan-instrument-memintrinsics=0");
1363 if (!TsanFuncEntryExit) {
1364 CmdArgs.push_back(
"-mllvm");
1365 CmdArgs.push_back(
"-tsan-instrument-func-entry-exit=0");
1368 CmdArgs.push_back(
"-mllvm");
1369 CmdArgs.push_back(
"-tsan-instrument-atomics=0");
1372 if (HwasanUseAliases) {
1373 CmdArgs.push_back(
"-mllvm");
1374 CmdArgs.push_back(
"-hwasan-experimental-use-page-aliases=1");
1378 CmdArgs.push_back(
"-fsanitize-cfi-cross-dso");
1380 if (CfiICallGeneralizePointers)
1381 CmdArgs.push_back(
"-fsanitize-cfi-icall-generalize-pointers");
1383 if (CfiICallNormalizeIntegers)
1384 CmdArgs.push_back(
"-fsanitize-cfi-icall-experimental-normalize-integers");
1386 if (CfiCanonicalJumpTables)
1387 CmdArgs.push_back(
"-fsanitize-cfi-canonical-jump-tables");
1390 CmdArgs.push_back(
"-fsanitize-stats");
1393 CmdArgs.push_back(
"-fsanitize-minimal-runtime");
1395 if (AsanFieldPadding)
1396 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-field-padding=" +
1397 Twine(AsanFieldPadding)));
1399 if (AsanUseAfterScope)
1400 CmdArgs.push_back(
"-fsanitize-address-use-after-scope");
1402 if (AsanPoisonCustomArrayCookie)
1403 CmdArgs.push_back(
"-fsanitize-address-poison-custom-array-cookie");
1405 if (AsanGlobalsDeadStripping)
1406 CmdArgs.push_back(
"-fsanitize-address-globals-dead-stripping");
1408 if (!AsanUseOdrIndicator)
1409 CmdArgs.push_back(
"-fno-sanitize-address-use-odr-indicator");
1411 if (AsanInvalidPointerCmp) {
1412 CmdArgs.push_back(
"-mllvm");
1413 CmdArgs.push_back(
"-asan-detect-invalid-pointer-cmp");
1416 if (AsanInvalidPointerSub) {
1417 CmdArgs.push_back(
"-mllvm");
1418 CmdArgs.push_back(
"-asan-detect-invalid-pointer-sub");
1421 if (AsanOutlineInstrumentation) {
1422 CmdArgs.push_back(
"-mllvm");
1423 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1430 CmdArgs.push_back(
"-mllvm");
1431 CmdArgs.push_back(
"-asan-instrumentation-with-call-threshold=0");
1432 CmdArgs.push_back(
"-mllvm");
1433 CmdArgs.push_back(
"-asan-max-inline-poisoning-size=0");
1434 CmdArgs.push_back(
"-mllvm");
1435 CmdArgs.push_back(
"-asan-guard-against-version-mismatch=0");
1440 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
1441 CmdArgs.push_back(Args.MakeArgString(
"-fsanitize-address-destructor=" +
1445 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
1446 CmdArgs.push_back(Args.MakeArgString(
1447 "-fsanitize-address-use-after-return=" +
1451 if (!HwasanAbi.empty()) {
1452 CmdArgs.push_back(
"-default-function-attr");
1453 CmdArgs.push_back(Args.MakeArgString(
"hwasan-abi=" + HwasanAbi));
1456 if (Sanitizers.
has(SanitizerKind::HWAddress) && !HwasanUseAliases) {
1457 CmdArgs.push_back(
"-target-feature");
1458 CmdArgs.push_back(
"+tagged-globals");
1466 if (Sanitizers.
has(SanitizerKind::Memory) ||
1467 Sanitizers.
has(SanitizerKind::Address))
1468 CmdArgs.push_back(
"-fno-assume-sane-operator-new");
1475 if (Sanitizers.
has(SanitizerKind::FuzzerNoLink)) {
1476 CmdArgs.push_back(
"-fno-builtin-bcmp");
1477 CmdArgs.push_back(
"-fno-builtin-memcmp");
1478 CmdArgs.push_back(
"-fno-builtin-strncmp");
1479 CmdArgs.push_back(
"-fno-builtin-strcmp");
1480 CmdArgs.push_back(
"-fno-builtin-strncasecmp");
1481 CmdArgs.push_back(
"-fno-builtin-strcasecmp");
1482 CmdArgs.push_back(
"-fno-builtin-strstr");
1483 CmdArgs.push_back(
"-fno-builtin-strcasestr");
1484 CmdArgs.push_back(
"-fno-builtin-memmem");
1490 !Args.hasArg(options::OPT_fvisibility_EQ)) {
1491 TC.
getDriver().
Diag(clang::diag::err_drv_argument_only_allowed_with)
1497 if (Sanitizers.
has(SanitizerKind::MemtagStack) &&
1499 TC.
getDriver().
Diag(diag::err_stack_tagging_requires_hardware_feature);
1503 bool DiagnoseErrors) {
1505 (A->getOption().matches(options::OPT_fsanitize_EQ) ||
1506 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
1507 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
1508 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
1509 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
1510 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
1511 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1512 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
1513 "Invalid argument in parseArgValues!");
1515 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1516 const char *
Value = A->getValue(i);
1519 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
1520 0 == strcmp(
"all",
Value))
1527 else if (DiagnoseErrors)
1528 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1529 << A->getSpelling() <<
Value;
1536 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&
1537 "Invalid argument in parseArgCutoffs!");
1538 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1539 const char *
Value = A->getValue(i);
1545 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1546 << A->getSpelling() <<
Value;
1551 const llvm::opt::Arg *A,
1552 bool DiagnoseErrors) {
1554 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1555 const char *
Value = A->getValue(i);
1557 llvm::StringSwitch<int>(
Value)
1560 .Case(
"add-unsigned-overflow-test",
1562 .Case(
"add-signed-overflow-test",
1568 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1569 << A->getSpelling() <<
Value;
1576 bool DiagnoseErrors) {
1577 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||
1578 A->getOption().matches(options::OPT_fno_sanitize_coverage));
1580 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1581 const char *
Value = A->getValue(i);
1582 int F = llvm::StringSwitch<int>(
Value)
1603 if (F == 0 && DiagnoseErrors)
1604 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1605 << A->getSpelling() <<
Value;
1612 bool DiagnoseErrors) {
1614 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||
1615 A->getOption().matches(
1616 options::OPT_fno_experimental_sanitize_metadata_EQ));
1618 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1619 const char *
Value = A->getValue(i);
1620 int F = llvm::StringSwitch<int>(
Value)
1626 if (F == 0 && DiagnoseErrors)
1627 D.Diag(clang::diag::err_drv_unsupported_option_argument)
1628 << A->getSpelling() <<
Value;
1636 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
1639 const auto *Arg = *I;
1640 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
1643 if (AddKinds & Mask)
1645 }
else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
1648 Mask &= ~RemoveKinds;
1651 llvm_unreachable(
"arg list didn't provide expected value");
1655 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
1656 "Invalid argument in describeSanitizerArg!");
1658 std::string Sanitizers;
1659 for (
int i = 0, n = A->getNumValues(); i != n; ++i) {
1663 if (!Sanitizers.empty())
1665 Sanitizers += A->getValue(i);
1669 assert(!Sanitizers.empty() &&
"arg didn't provide expected value");
1670 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 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 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 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
bool needsUbsanCXXRt() 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...
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 values for -fsanitize= or -fno-sanitize=.
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.