r355190 - [Driver] Allow enum SanitizerOrdinal to represent more than 64 different sanitizer checks, NFC.

Pierre Gousseau via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 1 02:05:15 PST 2019


Author: pgousseau
Date: Fri Mar  1 02:05:15 2019
New Revision: 355190

URL: http://llvm.org/viewvc/llvm-project?rev=355190&view=rev
Log:
[Driver] Allow enum SanitizerOrdinal to represent more than 64 different sanitizer checks, NFC.

enum SanitizerOrdinal has reached maximum capacity, this change extends the capacity to 128 sanitizer checks.
This can eventually allow us to add gcc 8's options "-fsanitize=pointer-substract" and "-fsanitize=pointer-compare".

This is a recommit of r354873 but with a fix for unqualified lookup error in lldb cmake build bot.

Fixes: https://llvm.org/PR39425

Differential Revision: https://reviews.llvm.org/D57914

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/Sanitizers.def
    cfe/trunk/include/clang/Basic/Sanitizers.h
    cfe/trunk/include/clang/Driver/ToolChain.h
    cfe/trunk/lib/Basic/SanitizerSpecialCaseList.cpp
    cfe/trunk/lib/Basic/Sanitizers.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/Driver/SanitizerArgs.cpp
    cfe/trunk/lib/Driver/ToolChain.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Mar  1 02:05:15 2019
@@ -2366,7 +2366,7 @@ def NoSanitize : InheritableAttr {
   let Documentation = [NoSanitizeDocs];
   let AdditionalMembers = [{
     SanitizerMask getMask() const {
-      SanitizerMask Mask = 0;
+      SanitizerMask Mask;
       for (auto SanitizerName : sanitizers()) {
         SanitizerMask ParsedMask =
             parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);

Modified: cfe/trunk/include/clang/Basic/Sanitizers.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Sanitizers.def (original)
+++ cfe/trunk/include/clang/Basic/Sanitizers.def Fri Mar  1 02:05:15 2019
@@ -177,7 +177,7 @@ SANITIZER("scudo", Scudo)
 
 // Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
 // can be used to disable all the sanitizers.
-SANITIZER_GROUP("all", All, ~0ULL)
+SANITIZER_GROUP("all", All, ~SanitizerMask())
 
 #undef SANITIZER
 #undef SANITIZER_GROUP

Modified: cfe/trunk/include/clang/Basic/Sanitizers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.h?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Sanitizers.h (original)
+++ cfe/trunk/include/clang/Basic/Sanitizers.h Fri Mar  1 02:05:15 2019
@@ -20,45 +20,166 @@
 #include <cassert>
 #include <cstdint>
 
+namespace llvm {
+class hash_code;
+}
+
 namespace clang {
 
-using SanitizerMask = uint64_t;
+class SanitizerMask {
+  /// Number of array elements.
+  static constexpr unsigned kNumElem = 2;
+  /// Mask value initialized to 0.
+  uint64_t maskLoToHigh[kNumElem]{};
+  /// Number of bits in a mask.
+  static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
+  /// Number of bits in a mask element.
+  static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
+
+public:
+  static constexpr bool checkBitPos(const unsigned Pos) {
+    return Pos < kNumBits;
+  }
 
-namespace SanitizerKind {
+  /// Create a mask with a bit enabled at position Pos.
+  static SanitizerMask bitPosToMask(const unsigned Pos) {
+    assert(Pos < kNumBits && "Bit position too big.");
+    SanitizerMask mask;
+    mask.maskLoToHigh[Pos / kNumBitElem] = 1ULL << Pos % kNumBitElem;
+    return mask;
+  }
 
-// Assign ordinals to possible values of -fsanitize= flag, which we will use as
-// bit positions.
-enum SanitizerOrdinal : uint64_t {
-#define SANITIZER(NAME, ID) SO_##ID,
-#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
-#include "clang/Basic/Sanitizers.def"
-  SO_Count
+  unsigned countPopulation() const {
+    unsigned total = 0;
+    for (const auto &Val : maskLoToHigh)
+      total += llvm::countPopulation(Val);
+    return total;
+  }
+
+  void flipAllBits() {
+    for (auto &Val : maskLoToHigh)
+      Val = ~Val;
+  }
+
+  bool isPowerOf2() const {
+    return countPopulation() == 1;
+  }
+
+  llvm::hash_code hash_value() const;
+
+  explicit operator bool() const {
+    for (const auto &Val : maskLoToHigh)
+      if (Val)
+        return true;
+    return false;
+  };
+
+  bool operator==(const SanitizerMask &V) const {
+    for (unsigned k = 0; k < kNumElem; k++) {
+      if (maskLoToHigh[k] != V.maskLoToHigh[k])
+        return false;
+    }
+    return true;
+  }
+
+  SanitizerMask &operator&=(const SanitizerMask &RHS) {
+    for (unsigned k = 0; k < kNumElem; k++)
+      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
+    return *this;
+  }
+
+  SanitizerMask &operator|=(const SanitizerMask &RHS) {
+    for (unsigned k = 0; k < kNumElem; k++)
+      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
+    return *this;
+  }
+
+  bool operator!() const {
+    for (const auto &Val : maskLoToHigh)
+      if (Val)
+        return false;
+    return true;
+  }
+
+  bool operator!=(const SanitizerMask &RHS) const { return !((*this) == RHS); }
 };
 
+// Declaring in clang namespace so that it can be found by ADL.
+llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
+
+inline SanitizerMask operator~(SanitizerMask v) {
+  v.flipAllBits();
+  return v;
+}
+
+inline SanitizerMask operator&(SanitizerMask a, const SanitizerMask &b) {
+  a &= b;
+  return a;
+}
+
+inline SanitizerMask operator|(SanitizerMask a, const SanitizerMask &b) {
+  a |= b;
+  return a;
+}
+
 // Define the set of sanitizer kinds, as well as the set of sanitizers each
 // sanitizer group expands into.
-#define SANITIZER(NAME, ID) \
-  const SanitizerMask ID = 1ULL << SO_##ID;
-#define SANITIZER_GROUP(NAME, ID, ALIAS) \
-  const SanitizerMask ID = ALIAS; \
-  const SanitizerMask ID##Group = 1ULL << SO_##ID##Group;
+// Uses static data member of a class template as recommended in second
+// workaround from n4424 to avoid odr issues.
+// FIXME: Can be marked as constexpr once c++14 can be used in llvm.
+// FIXME: n4424 workaround can be replaced by c++17 inline variable.
+template <typename T = void> struct SanitizerMasks {
+
+  // Assign ordinals to possible values of -fsanitize= flag, which we will use
+  // as bit positions.
+  enum SanitizerOrdinal : uint64_t {
+#define SANITIZER(NAME, ID) SO_##ID,
+#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
+#include "clang/Basic/Sanitizers.def"
+    SO_Count
+  };
+
+#define SANITIZER(NAME, ID)                                                    \
+  static const SanitizerMask ID;                                               \
+  static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
+#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
+  static const SanitizerMask ID;                                               \
+  static const SanitizerMask ID##Group;                                        \
+  static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
+                "Bit position too big.");
 #include "clang/Basic/Sanitizers.def"
+}; // SanitizerMasks
+
+#define SANITIZER(NAME, ID)                                                    \
+  template <typename T>                                                        \
+  const SanitizerMask SanitizerMasks<T>::ID =                                  \
+      SanitizerMask::bitPosToMask(SO_##ID);
+#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
+  template <typename T>                                                        \
+  const SanitizerMask SanitizerMasks<T>::ID = SanitizerMask(ALIAS);            \
+  template <typename T>                                                        \
+  const SanitizerMask SanitizerMasks<T>::ID##Group =                           \
+      SanitizerMask::bitPosToMask(SO_##ID##Group);
+#include "clang/Basic/Sanitizers.def"
+
+// Explicit instantiation here to ensure correct initialization order.
+template struct SanitizerMasks<>;
 
-} // namespace SanitizerKind
+using SanitizerKind = SanitizerMasks<>;
 
 struct SanitizerSet {
   /// Check if a certain (single) sanitizer is enabled.
   bool has(SanitizerMask K) const {
-    assert(llvm::isPowerOf2_64(K));
-    return Mask & K;
+    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
+    return static_cast<bool>(Mask & K);
   }
 
   /// Check if one or more sanitizers are enabled.
-  bool hasOneOf(SanitizerMask K) const { return Mask & K; }
+  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
 
   /// Enable or disable a certain (single) sanitizer.
   void set(SanitizerMask K, bool Value) {
-    assert(llvm::isPowerOf2_64(K));
+    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
     Mask = Value ? (Mask | K) : (Mask & ~K);
   }
 
@@ -66,10 +187,10 @@ struct SanitizerSet {
   void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
 
   /// Returns true if no sanitizers are enabled.
-  bool empty() const { return Mask == 0; }
+  bool empty() const { return !Mask; }
 
   /// Bitmask of enabled sanitizers.
-  SanitizerMask Mask = 0;
+  SanitizerMask Mask;
 };
 
 /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.

Modified: cfe/trunk/include/clang/Driver/ToolChain.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/ToolChain.h?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/ToolChain.h (original)
+++ cfe/trunk/include/clang/Driver/ToolChain.h Fri Mar  1 02:05:15 2019
@@ -563,7 +563,9 @@ public:
   virtual SanitizerMask getSupportedSanitizers() const;
 
   /// Return sanitizers which are enabled by default.
-  virtual SanitizerMask getDefaultSanitizers() const { return 0; }
+  virtual SanitizerMask getDefaultSanitizers() const {
+    return SanitizerMask();
+  }
 };
 
 /// Set a ToolChain's effective triple. Reset it when the registration object

Modified: cfe/trunk/lib/Basic/SanitizerSpecialCaseList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SanitizerSpecialCaseList.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SanitizerSpecialCaseList.cpp (original)
+++ cfe/trunk/lib/Basic/SanitizerSpecialCaseList.cpp Fri Mar  1 02:05:15 2019
@@ -36,7 +36,7 @@ SanitizerSpecialCaseList::createOrDie(co
 
 void SanitizerSpecialCaseList::createSanitizerSections() {
   for (auto &S : Sections) {
-    SanitizerMask Mask = 0;
+    SanitizerMask Mask;
 
 #define SANITIZER(NAME, ID)                                                    \
   if (S.SectionMatcher->match(NAME))                                           \

Modified: cfe/trunk/lib/Basic/Sanitizers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Sanitizers.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Sanitizers.cpp (original)
+++ cfe/trunk/lib/Basic/Sanitizers.cpp Fri Mar  1 02:05:15 2019
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Sanitizers.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringSwitch.h"
 
 using namespace clang;
@@ -19,9 +20,9 @@ SanitizerMask clang::parseSanitizerValue
   SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
 #define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
 #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
-  .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : 0)
+  .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
 #include "clang/Basic/Sanitizers.def"
-    .Default(0);
+    .Default(SanitizerMask());
   return ParsedKind;
 }
 
@@ -33,3 +34,13 @@ SanitizerMask clang::expandSanitizerGrou
 #include "clang/Basic/Sanitizers.def"
   return Kinds;
 }
+
+llvm::hash_code SanitizerMask::hash_value() const {
+  return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]);
+}
+
+namespace clang {
+llvm::hash_code hash_value(const clang::SanitizerMask &Arg) {
+  return Arg.hash_value();
+}
+} // namespace clang

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Mar  1 02:05:15 2019
@@ -2855,16 +2855,13 @@ enum class CheckRecoverableKind {
 }
 
 static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) {
-  assert(llvm::countPopulation(Kind) == 1);
-  switch (Kind) {
-  case SanitizerKind::Vptr:
+  assert(Kind.countPopulation() == 1);
+  if (Kind == SanitizerKind::Vptr)
     return CheckRecoverableKind::AlwaysRecoverable;
-  case SanitizerKind::Return:
-  case SanitizerKind::Unreachable:
+  else if (Kind == SanitizerKind::Return || Kind == SanitizerKind::Unreachable)
     return CheckRecoverableKind::Unrecoverable;
-  default:
+  else
     return CheckRecoverableKind::Recoverable;
-  }
 }
 
 namespace {

Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Fri Mar  1 02:05:15 2019
@@ -21,33 +21,52 @@
 #include <memory>
 
 using namespace clang;
-using namespace clang::SanitizerKind;
 using namespace clang::driver;
 using namespace llvm::opt;
 
-enum : SanitizerMask {
-  NeedsUbsanRt = Undefined | Integer | ImplicitConversion | Nullability | CFI,
-  NeedsUbsanCxxRt = Vptr | CFI,
-  NotAllowedWithTrap = Vptr,
-  NotAllowedWithMinimalRuntime = Vptr,
-  RequiresPIE = DataFlow | HWAddress | Scudo,
-  NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
-  SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
-                     Memory | KernelMemory | Leak | Undefined | Integer |
-                     ImplicitConversion | Nullability | DataFlow | Fuzzer |
-                     FuzzerNoLink,
-  RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
-  Unrecoverable = Unreachable | Return,
-  AlwaysRecoverable = KernelAddress | KernelHWAddress,
-  LegacyFsanitizeRecoverMask = Undefined | Integer,
-  NeedsLTO = CFI,
-  TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow |
-                      ImplicitConversion | Nullability | LocalBounds | CFI,
-  TrappingDefault = CFI,
-  CFIClasses =
-      CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast,
-  CompatibleWithMinimalRuntime = TrappingSupported | Scudo | ShadowCallStack,
-};
+static const SanitizerMask NeedsUbsanRt =
+    SanitizerKind::Undefined | SanitizerKind::Integer |
+    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
+    SanitizerKind::CFI;
+static const SanitizerMask NeedsUbsanCxxRt =
+    SanitizerKind::Vptr | SanitizerKind::CFI;
+static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
+static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;
+static const SanitizerMask RequiresPIE =
+    SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo;
+static const SanitizerMask NeedsUnwindTables =
+    SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
+    SanitizerKind::Memory | SanitizerKind::DataFlow;
+static const SanitizerMask SupportsCoverage =
+    SanitizerKind::Address | SanitizerKind::HWAddress |
+    SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
+    SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
+    SanitizerKind::Undefined | SanitizerKind::Integer |
+    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
+    SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
+    SanitizerKind::FuzzerNoLink;
+static const SanitizerMask RecoverableByDefault =
+    SanitizerKind::Undefined | SanitizerKind::Integer |
+    SanitizerKind::ImplicitConversion | SanitizerKind::Nullability;
+static const SanitizerMask Unrecoverable =
+    SanitizerKind::Unreachable | SanitizerKind::Return;
+static const SanitizerMask AlwaysRecoverable =
+    SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
+static const SanitizerMask LegacyFsanitizeRecoverMask =
+    SanitizerKind::Undefined | SanitizerKind::Integer;
+static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
+static const SanitizerMask TrappingSupported =
+    (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
+    SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion |
+    SanitizerKind::Nullability | SanitizerKind::LocalBounds |
+    SanitizerKind::CFI;
+static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
+static const SanitizerMask CFIClasses =
+    SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
+    SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
+    SanitizerKind::CFIUnrelatedCast;
+static const SanitizerMask CompatibleWithMinimalRuntime =
+    TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack;
 
 enum CoverageFeature {
   CoverageFunc = 1 << 0,
@@ -100,13 +119,15 @@ static void addDefaultBlacklists(const D
   struct Blacklist {
     const char *File;
     SanitizerMask Mask;
-  } Blacklists[] = {{"asan_blacklist.txt", Address},
-                    {"hwasan_blacklist.txt", HWAddress},
-                    {"msan_blacklist.txt", Memory},
-                    {"tsan_blacklist.txt", Thread},
-                    {"dfsan_abilist.txt", DataFlow},
-                    {"cfi_blacklist.txt", CFI},
-                    {"ubsan_blacklist.txt", Undefined | Integer | Nullability}};
+  } Blacklists[] = {{"asan_blacklist.txt", SanitizerKind::Address},
+                    {"hwasan_blacklist.txt", SanitizerKind::HWAddress},
+                    {"msan_blacklist.txt", SanitizerKind::Memory},
+                    {"tsan_blacklist.txt", SanitizerKind::Thread},
+                    {"dfsan_abilist.txt", SanitizerKind::DataFlow},
+                    {"cfi_blacklist.txt", SanitizerKind::CFI},
+                    {"ubsan_blacklist.txt", SanitizerKind::Undefined |
+                                                SanitizerKind::Integer |
+                                                SanitizerKind::Nullability}};
 
   for (auto BL : Blacklists) {
     if (!(Kinds & BL.Mask))
@@ -116,7 +137,7 @@ static void addDefaultBlacklists(const D
     llvm::sys::path::append(Path, "share", BL.File);
     if (llvm::sys::fs::exists(Path))
       BlacklistFiles.push_back(Path.str());
-    else if (BL.Mask == CFI)
+    else if (BL.Mask == SanitizerKind::CFI)
       // If cfi_blacklist.txt cannot be found in the resource dir, driver
       // should fail.
       D.Diag(clang::diag::err_drv_no_such_file) << Path;
@@ -136,10 +157,10 @@ static SanitizerMask setGroupBits(Saniti
 
 static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
                                            const llvm::opt::ArgList &Args) {
-  SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
+  SanitizerMask TrapRemove;     // During the loop below, the accumulated set of
                                 // sanitizers disabled by the current sanitizer
                                 // argument or any argument after it.
-  SanitizerMask TrappingKinds = 0;
+  SanitizerMask TrappingKinds;
   SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
 
   for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
@@ -163,11 +184,12 @@ static SanitizerMask parseSanitizeTrapAr
                    options::OPT_fsanitize_undefined_trap_on_error)) {
       Arg->claim();
       TrappingKinds |=
-          expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
+          expandSanitizerGroups(SanitizerKind::UndefinedGroup & ~TrapRemove) &
+          ~TrapRemove;
     } else if (Arg->getOption().matches(
                    options::OPT_fno_sanitize_undefined_trap_on_error)) {
       Arg->claim();
-      TrapRemove |= expandSanitizerGroups(UndefinedGroup);
+      TrapRemove |= expandSanitizerGroups(SanitizerKind::UndefinedGroup);
     }
   }
 
@@ -189,13 +211,13 @@ bool SanitizerArgs::needsUbsanRt() const
 }
 
 bool SanitizerArgs::needsCfiRt() const {
-  return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
-         !ImplicitCfiRuntime;
+  return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
+         CfiCrossDso && !ImplicitCfiRuntime;
 }
 
 bool SanitizerArgs::needsCfiDiagRt() const {
-  return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso &&
-         !ImplicitCfiRuntime;
+  return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&
+         CfiCrossDso && !ImplicitCfiRuntime;
 }
 
 bool SanitizerArgs::requiresPIE() const {
@@ -203,24 +225,26 @@ bool SanitizerArgs::requiresPIE() const
 }
 
 bool SanitizerArgs::needsUnwindTables() const {
-  return Sanitizers.Mask & NeedsUnwindTables;
+  return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);
 }
 
-bool SanitizerArgs::needsLTO() const { return Sanitizers.Mask & NeedsLTO; }
+bool SanitizerArgs::needsLTO() const {
+  return static_cast<bool>(Sanitizers.Mask & NeedsLTO);
+}
 
 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                              const llvm::opt::ArgList &Args) {
-  SanitizerMask AllRemove = 0;  // During the loop below, the accumulated set of
+  SanitizerMask AllRemove;      // During the loop below, the accumulated set of
                                 // sanitizers disabled by the current sanitizer
                                 // argument or any argument after it.
-  SanitizerMask AllAddedKinds = 0;  // Mask of all sanitizers ever enabled by
+  SanitizerMask AllAddedKinds;      // Mask of all sanitizers ever enabled by
                                     // -fsanitize= flags (directly or via group
                                     // expansion), some of which may be disabled
                                     // later. Used to carefully prune
                                     // unused-argument diagnostics.
-  SanitizerMask DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
+  SanitizerMask DiagnosedKinds;      // All Kinds we have diagnosed up to now.
                                      // Used to deduplicate diagnostics.
-  SanitizerMask Kinds = 0;
+  SanitizerMask Kinds;
   const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
 
   CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
@@ -295,12 +319,12 @@ SanitizerArgs::SanitizerArgs(const ToolC
       //   identifiers.
       // Fixing both of those may require changes to the cross-DSO CFI
       // interface.
-      if (CfiCrossDso && (Add & CFIMFCall & ~DiagnosedKinds)) {
+      if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {
         D.Diag(diag::err_drv_argument_not_allowed_with)
             << "-fsanitize=cfi-mfcall"
             << "-fsanitize-cfi-cross-dso";
-        Add &= ~CFIMFCall;
-        DiagnosedKinds |= CFIMFCall;
+        Add &= ~SanitizerKind::CFIMFCall;
+        DiagnosedKinds |= SanitizerKind::CFIMFCall;
       }
 
       if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
@@ -314,7 +338,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
       // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
       // so we don't error out if -fno-rtti and -fsanitize=undefined were
       // passed.
-      if ((Add & Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
+      if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
         if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
           assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
                   "RTTI disabled without -fno-rtti option?");
@@ -329,7 +353,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
         }
 
         // Take out the Vptr sanitizer from the enabled sanitizers
-        AllRemove |= Vptr;
+        AllRemove |= SanitizerKind::Vptr;
       }
 
       Add = expandSanitizerGroups(Add);
@@ -342,14 +366,14 @@ SanitizerArgs::SanitizerArgs(const ToolC
         Add &= ~NotAllowedWithMinimalRuntime;
       }
       if (CfiCrossDso)
-        Add &= ~CFIMFCall;
+        Add &= ~SanitizerKind::CFIMFCall;
       Add &= Supported;
 
-      if (Add & Fuzzer)
-        Add |= FuzzerNoLink;
+      if (Add & SanitizerKind::Fuzzer)
+        Add |= SanitizerKind::FuzzerNoLink;
 
       // Enable coverage if the fuzzing flag is set.
-      if (Add & FuzzerNoLink) {
+      if (Add & SanitizerKind::FuzzerNoLink) {
         CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |
                             CoverageTraceCmp | CoveragePCTable;
         // Due to TLS differences, stack depth tracking is only enabled on Linux
@@ -366,23 +390,42 @@ SanitizerArgs::SanitizerArgs(const ToolC
   }
 
   std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
-      std::make_pair(Address, Thread | Memory),
-      std::make_pair(Thread, Memory),
-      std::make_pair(Leak, Thread | Memory),
-      std::make_pair(KernelAddress, Address | Leak | Thread | Memory),
-      std::make_pair(HWAddress, Address | Thread | Memory | KernelAddress),
-      std::make_pair(Efficiency, Address | HWAddress | Leak | Thread | Memory |
-                                     KernelAddress),
-      std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
-                                KernelAddress | Efficiency),
-      std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
-                                    KernelAddress | Efficiency),
-      std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread |
-                                          Memory | KernelAddress | Efficiency |
-                                          SafeStack),
-      std::make_pair(KernelMemory, Address | HWAddress | Leak | Thread |
-                                       Memory | KernelAddress | Efficiency |
-                                       Scudo | SafeStack)};
+      std::make_pair(SanitizerKind::Address,
+                     SanitizerKind::Thread | SanitizerKind::Memory),
+      std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
+      std::make_pair(SanitizerKind::Leak,
+                     SanitizerKind::Thread | SanitizerKind::Memory),
+      std::make_pair(SanitizerKind::KernelAddress,
+                     SanitizerKind::Address | SanitizerKind::Leak |
+                         SanitizerKind::Thread | SanitizerKind::Memory),
+      std::make_pair(SanitizerKind::HWAddress,
+                     SanitizerKind::Address | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress),
+      std::make_pair(SanitizerKind::Efficiency,
+                     SanitizerKind::Address | SanitizerKind::HWAddress |
+                         SanitizerKind::Leak | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress),
+      std::make_pair(SanitizerKind::Scudo,
+                     SanitizerKind::Address | SanitizerKind::HWAddress |
+                         SanitizerKind::Leak | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
+                         SanitizerKind::Efficiency),
+      std::make_pair(SanitizerKind::SafeStack,
+                     SanitizerKind::Address | SanitizerKind::HWAddress |
+                         SanitizerKind::Leak | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
+                         SanitizerKind::Efficiency),
+      std::make_pair(SanitizerKind::KernelHWAddress,
+                     SanitizerKind::Address | SanitizerKind::HWAddress |
+                         SanitizerKind::Leak | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
+                         SanitizerKind::Efficiency | SanitizerKind::SafeStack),
+      std::make_pair(SanitizerKind::KernelMemory,
+                     SanitizerKind::Address | SanitizerKind::HWAddress |
+                         SanitizerKind::Leak | SanitizerKind::Thread |
+                         SanitizerKind::Memory | SanitizerKind::KernelAddress |
+                         SanitizerKind::Efficiency | SanitizerKind::Scudo |
+                         SanitizerKind::SafeStack)};
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
 
@@ -398,8 +441,8 @@ SanitizerArgs::SanitizerArgs(const ToolC
 
   // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
   // is disabled.
-  if ((Kinds & Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
-    Kinds &= ~Vptr;
+  if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
+    Kinds &= ~SanitizerKind::Vptr;
   }
 
   // Check that LTO is enabled if we need it.
@@ -408,12 +451,12 @@ SanitizerArgs::SanitizerArgs(const ToolC
         << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
   }
 
-  if ((Kinds & ShadowCallStack) &&
+  if ((Kinds & SanitizerKind::ShadowCallStack) &&
       TC.getTriple().getArch() == llvm::Triple::aarch64 &&
       !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
       !Args.hasArg(options::OPT_ffixed_x18)) {
     D.Diag(diag::err_drv_argument_only_allowed_with)
-        << lastArgumentForMask(D, Args, Kinds & ShadowCallStack)
+        << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
         << "-ffixed-x18";
   }
 
@@ -421,12 +464,12 @@ SanitizerArgs::SanitizerArgs(const ToolC
   // c++abi-specific  parts of UBSan runtime, and they are not provided by the
   // toolchain. We don't have a good way to check the latter, so we just
   // check if the toolchan supports vptr.
-  if (~Supported & Vptr) {
+  if (~Supported & SanitizerKind::Vptr) {
     SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;
     // The runtime library supports the Microsoft C++ ABI, but only well enough
     // for CFI. FIXME: Remove this once we support vptr on Windows.
     if (TC.getTriple().isOSWindows())
-      KindsToDiagnose &= ~CFI;
+      KindsToDiagnose &= ~SanitizerKind::CFI;
     if (KindsToDiagnose) {
       SanitizerSet S;
       S.Mask = KindsToDiagnose;
@@ -455,8 +498,8 @@ SanitizerArgs::SanitizerArgs(const ToolC
 
   // Parse -f(no-)?sanitize-recover flags.
   SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;
-  SanitizerMask DiagnosedUnrecoverableKinds = 0;
-  SanitizerMask DiagnosedAlwaysRecoverableKinds = 0;
+  SanitizerMask DiagnosedUnrecoverableKinds;
+  SanitizerMask DiagnosedAlwaysRecoverableKinds;
   for (const auto *Arg : Args) {
     const char *DeprecatedReplacement = nullptr;
     if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
@@ -539,7 +582,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
   }
 
   // Parse -f[no-]sanitize-memory-track-origins[=level] options.
-  if (AllAddedKinds & Memory) {
+  if (AllAddedKinds & SanitizerKind::Memory) {
     if (Arg *A =
             Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
                             options::OPT_fsanitize_memory_track_origins,
@@ -567,19 +610,19 @@ SanitizerArgs::SanitizerArgs(const ToolC
     MsanUseAfterDtor = false;
   }
 
-  if (AllAddedKinds & Thread) {
-    TsanMemoryAccess = Args.hasFlag(options::OPT_fsanitize_thread_memory_access,
-                                    options::OPT_fno_sanitize_thread_memory_access,
-                                    TsanMemoryAccess);
-    TsanFuncEntryExit = Args.hasFlag(options::OPT_fsanitize_thread_func_entry_exit,
-                                     options::OPT_fno_sanitize_thread_func_entry_exit,
-                                     TsanFuncEntryExit);
-    TsanAtomics = Args.hasFlag(options::OPT_fsanitize_thread_atomics,
-                               options::OPT_fno_sanitize_thread_atomics,
-                               TsanAtomics);
+  if (AllAddedKinds & SanitizerKind::Thread) {
+    TsanMemoryAccess = Args.hasFlag(
+        options::OPT_fsanitize_thread_memory_access,
+        options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);
+    TsanFuncEntryExit = Args.hasFlag(
+        options::OPT_fsanitize_thread_func_entry_exit,
+        options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);
+    TsanAtomics =
+        Args.hasFlag(options::OPT_fsanitize_thread_atomics,
+                     options::OPT_fno_sanitize_thread_atomics, TsanAtomics);
   }
 
-  if (AllAddedKinds & CFI) {
+  if (AllAddedKinds & SanitizerKind::CFI) {
     // Without PIE, external function address may resolve to a PLT record, which
     // can not be verified by the target module.
     NeedPIE |= CfiCrossDso;
@@ -603,7 +646,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
           << "-fsanitize-minimal-runtime"
           << lastArgumentForMask(D, Args, IncompatibleMask);
 
-    SanitizerMask NonTrappingCfi = Kinds & CFI & ~TrappingKinds;
+    SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;
     if (NonTrappingCfi)
       D.Diag(clang::diag::err_drv_argument_only_allowed_with)
           << "fsanitize-minimal-runtime"
@@ -691,7 +734,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
 
   ImplicitCfiRuntime = TC.getTriple().isAndroid();
 
-  if (AllAddedKinds & Address) {
+  if (AllAddedKinds & SanitizerKind::Address) {
     NeedPIE |= TC.getTriple().isOSFuchsia();
     if (Arg *A =
             Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
@@ -713,7 +756,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
       case options::OPT__SLASH_LDd:
         D.Diag(clang::diag::err_drv_argument_not_allowed_with)
             << WindowsDebugRTArg->getAsString(Args)
-            << lastArgumentForMask(D, Args, Address);
+            << lastArgumentForMask(D, Args, SanitizerKind::Address);
         D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
       }
     }
@@ -742,7 +785,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
     AsanUseAfterScope = false;
   }
 
-  if (AllAddedKinds & HWAddress) {
+  if (AllAddedKinds & SanitizerKind::HWAddress) {
     if (Arg *HwasanAbiArg =
             Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
       HwasanAbi = HwasanAbiArg->getValue();
@@ -754,7 +797,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
     }
   }
 
-  if (AllAddedKinds & SafeStack) {
+  if (AllAddedKinds & SanitizerKind::SafeStack) {
     // SafeStack runtime is built into the system on Fuchsia.
     SafeStackRuntime = !TC.getTriple().isOSFuchsia();
   }
@@ -774,7 +817,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
 static std::string toString(const clang::SanitizerSet &Sanitizers) {
   std::string Res;
 #define SANITIZER(NAME, ID)                                                    \
-  if (Sanitizers.has(ID)) {                                                    \
+  if (Sanitizers.has(SanitizerKind::ID)) {                                     \
     if (!Res.empty())                                                          \
       Res += ",";                                                              \
     Res += NAME;                                                               \
@@ -936,7 +979,8 @@ void SanitizerArgs::addArgs(const ToolCh
   // https://github.com/google/sanitizers/issues/373
   // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
   // affect compilation.
-  if (Sanitizers.has(Memory) || Sanitizers.has(Address))
+  if (Sanitizers.has(SanitizerKind::Memory) ||
+      Sanitizers.has(SanitizerKind::Address))
     CmdArgs.push_back("-fno-assume-sane-operator-new");
 
   // Require -fvisibility= flag on non-Windows when compiling if vptr CFI is
@@ -959,18 +1003,18 @@ SanitizerMask parseArgValues(const Drive
           A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
           A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
          "Invalid argument in parseArgValues!");
-  SanitizerMask Kinds = 0;
+  SanitizerMask Kinds;
   for (int i = 0, n = A->getNumValues(); i != n; ++i) {
     const char *Value = A->getValue(i);
     SanitizerMask Kind;
     // Special case: don't accept -fsanitize=all.
     if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
         0 == strcmp("all", Value))
-      Kind = 0;
+      Kind = SanitizerMask();
     // Similarly, don't accept -fsanitize=efficiency-all.
     else if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
         0 == strcmp("efficiency-all", Value))
-      Kind = 0;
+      Kind = SanitizerMask();
     else
       Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);
 

Modified: cfe/trunk/lib/Driver/ToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChain.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChain.cpp Fri Mar  1 02:05:15 2019
@@ -818,21 +818,23 @@ SanitizerMask ToolChain::getSupportedSan
   // Return sanitizers which don't require runtime support and are not
   // platform dependent.
 
-  using namespace SanitizerKind;
-
-  SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
-                      CFICastStrict | UnsignedIntegerOverflow |
-                      ImplicitConversion | Nullability | LocalBounds;
+  SanitizerMask Res = (SanitizerKind::Undefined & ~SanitizerKind::Vptr &
+                       ~SanitizerKind::Function) |
+                      (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
+                      SanitizerKind::CFICastStrict |
+                      SanitizerKind::UnsignedIntegerOverflow |
+                      SanitizerKind::ImplicitConversion |
+                      SanitizerKind::Nullability | SanitizerKind::LocalBounds;
   if (getTriple().getArch() == llvm::Triple::x86 ||
       getTriple().getArch() == llvm::Triple::x86_64 ||
       getTriple().getArch() == llvm::Triple::arm ||
       getTriple().getArch() == llvm::Triple::aarch64 ||
       getTriple().getArch() == llvm::Triple::wasm32 ||
       getTriple().getArch() == llvm::Triple::wasm64)
-    Res |= CFIICall;
+    Res |= SanitizerKind::CFIICall;
   if (getTriple().getArch() == llvm::Triple::x86_64 ||
       getTriple().getArch() == llvm::Triple::aarch64)
-    Res |= ShadowCallStack;
+    Res |= SanitizerKind::ShadowCallStack;
   return Res;
 }
 

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Mar  1 02:05:15 2019
@@ -551,7 +551,7 @@ static void parseSanitizerKinds(StringRe
                                 DiagnosticsEngine &Diags, SanitizerSet &S) {
   for (const auto &Sanitizer : Sanitizers) {
     SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
-    if (K == 0)
+    if (K == SanitizerMask())
       Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
     else
       S.set(K, true);

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=355190&r1=355189&r2=355190&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Mar  1 02:05:15 2019
@@ -6301,7 +6301,8 @@ static void handleNoSanitizeAttr(Sema &S
     if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
       return;
 
-    if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0)
+    if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) ==
+        SanitizerMask())
       S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
     else if (isGlobalVar(D) && SanitizerName != "address")
       S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)




More information about the cfe-commits mailing list