Index: include/clang/Basic/Sanitizers.h =================================================================== --- include/clang/Basic/Sanitizers.h +++ include/clang/Basic/Sanitizers.h @@ -15,6 +15,9 @@ #ifndef LLVM_CLANG_BASIC_SANITIZERS_H #define LLVM_CLANG_BASIC_SANITIZERS_H +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" + #include namespace clang { @@ -62,6 +65,14 @@ SanitizerMask Mask; }; +/// Parse a single value from a -fsanitize= or -fno-sanitize= value list. +/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known. +SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); + +/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers +/// this group enables. +SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); + } // end namespace clang #endif Index: lib/Basic/Sanitizers.cpp =================================================================== --- lib/Basic/Sanitizers.cpp +++ lib/Basic/Sanitizers.cpp @@ -11,6 +11,9 @@ // //===----------------------------------------------------------------------===// #include "clang/Basic/Sanitizers.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -31,3 +34,22 @@ bool SanitizerSet::empty() const { return Mask == 0; } + +SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) { + uint64_t ParsedKind = llvm::StringSwitch(Value) +#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) \ + .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : 0) +#include "clang/Basic/Sanitizers.def" + .Default(0); + return ParsedKind; +} + +SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) { +#define SANITIZER(NAME, ID) +#define SANITIZER_GROUP(NAME, ID, ALIAS) \ + if (Kinds & SanitizerKind::ID##Group) \ + Kinds |= SanitizerKind::ID; +#include "clang/Basic/Sanitizers.def" + return Kinds; +} Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Driver/SanitizerArgs.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" @@ -35,10 +36,6 @@ NeedsLTO = CFI, }; -/// Parse a single value from a -fsanitize= or -fno-sanitize= value list. -/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known. -static SanitizerMask parseValue(const char *Value); - /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any /// invalid components. Returns a SanitizerMask. static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, @@ -63,10 +60,6 @@ /// Sanitizers set. static std::string toString(const clang::SanitizerSet &Sanitizers); -/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers -/// this group enables. -static SanitizerMask expandGroups(SanitizerMask Kinds); - static uint64_t getToolchainUnsupportedKinds(const ToolChain &TC) { bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD; bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux; @@ -197,7 +190,7 @@ AllRemove |= Vptr; } - Add = expandGroups(Add); + Add = expandSanitizerGroups(Add); // Group expansion may have enabled a sanitizer which is disabled later. Add &= ~AllRemove; // Silently discard any unsupported sanitizers implicitly enabled through @@ -208,7 +201,7 @@ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { Arg->claim(); uint64_t Remove = parseArgValues(D, Arg, true); - AllRemove |= expandGroups(Remove); + AllRemove |= expandSanitizerGroups(Remove); } } @@ -261,11 +254,11 @@ const char *DeprecatedReplacement = nullptr; if (Arg->getOption().matches(options::OPT_fsanitize_recover)) { DeprecatedReplacement = "-fsanitize-recover=undefined,integer"; - RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask); + RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask); Arg->claim(); } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) { DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer"; - RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask); + RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask); Arg->claim(); } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { uint64_t Add = parseArgValues(D, Arg, true); @@ -279,10 +272,10 @@ << Arg->getOption().getName() << toString(SetToDiagnose); DiagnosedUnrecoverableKinds |= KindsToDiagnose; } - RecoverableKinds |= expandGroups(Add); + RecoverableKinds |= expandSanitizerGroups(Add); Arg->claim(); } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) { - RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true)); + RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true)); Arg->claim(); } if (DeprecatedReplacement) { @@ -446,22 +439,6 @@ CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); } -SanitizerMask parseValue(const char *Value) { - uint64_t ParsedKind = llvm::StringSwitch(Value) -#define SANITIZER(NAME, ID) .Case(NAME, ID) -#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group) -#include "clang/Basic/Sanitizers.def" - .Default(0); - return ParsedKind; -} - -SanitizerMask expandGroups(SanitizerMask Kinds) { -#define SANITIZER(NAME, ID) -#define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID; -#include "clang/Basic/Sanitizers.def" - return Kinds; -} - uint64_t parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors) { assert((A->getOption().matches(options::OPT_fsanitize_EQ) || @@ -478,7 +455,7 @@ 0 == strcmp("all", Value)) Kind = 0; else - Kind = parseValue(Value); + Kind = parseSanitizerValue(Value, /*AllowGroups=*/true); if (Kind) Kinds |= Kind; @@ -496,11 +473,12 @@ I != E; ++I) { const auto *Arg = *I; if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { - uint64_t AddKinds = expandGroups(parseArgValues(D, Arg, false)); + uint64_t AddKinds = expandSanitizerGroups(parseArgValues(D, Arg, false)); if (AddKinds & Mask) return describeSanitizeArg(Arg, Mask); } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { - uint64_t RemoveKinds = expandGroups(parseArgValues(D, Arg, false)); + uint64_t RemoveKinds = + expandSanitizerGroups(parseArgValues(D, Arg, false)); Mask &= ~RemoveKinds; } } @@ -513,7 +491,9 @@ std::string Sanitizers; for (int i = 0, n = A->getNumValues(); i != n; ++i) { - if (expandGroups(parseValue(A->getValue(i))) & Mask) { + if (expandSanitizerGroups( + parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) & + Mask) { if (!Sanitizers.empty()) Sanitizers += ","; Sanitizers += A->getValue(i); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -329,10 +329,7 @@ const std::vector &Sanitizers, DiagnosticsEngine &Diags, SanitizerSet &S) { for (const auto &Sanitizer : Sanitizers) { - SanitizerMask K = llvm::StringSwitch(Sanitizer) -#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID) -#include "clang/Basic/Sanitizers.def" - .Default(0); + SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false); if (K == 0) Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer; else