pgousseau updated this revision to Diff 187553.
pgousseau added a comment.

Applied suggested changes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57914/new/

https://reviews.llvm.org/D57914

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

Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -6199,7 +6199,8 @@
     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)
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -551,7 +551,7 @@
                                 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);
Index: lib/Driver/SanitizerArgs.cpp
===================================================================
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -25,29 +25,32 @@
 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,
-};
+const SanitizerMask NeedsUbsanRt =
+    Undefined | Integer | ImplicitConversion | Nullability | CFI;
+const SanitizerMask NeedsUbsanCxxRt = Vptr | CFI;
+const SanitizerMask NotAllowedWithTrap = Vptr;
+const SanitizerMask NotAllowedWithMinimalRuntime = Vptr;
+const SanitizerMask RequiresPIE = DataFlow | HWAddress | Scudo;
+const SanitizerMask NeedsUnwindTables =
+    Address | HWAddress | Thread | Memory | DataFlow;
+const SanitizerMask SupportsCoverage =
+    Address | HWAddress | KernelAddress | KernelHWAddress | Memory |
+    KernelMemory | Leak | Undefined | Integer | ImplicitConversion |
+    Nullability | DataFlow | Fuzzer | FuzzerNoLink;
+const SanitizerMask RecoverableByDefault =
+    Undefined | Integer | ImplicitConversion | Nullability;
+const SanitizerMask Unrecoverable = Unreachable | Return;
+const SanitizerMask AlwaysRecoverable = KernelAddress | KernelHWAddress;
+const SanitizerMask LegacyFsanitizeRecoverMask = Undefined | Integer;
+const SanitizerMask NeedsLTO = CFI;
+const SanitizerMask TrappingSupported =
+    (Undefined & ~Vptr) | UnsignedIntegerOverflow | ImplicitConversion |
+    Nullability | LocalBounds | CFI;
+const SanitizerMask TrappingDefault = CFI;
+const SanitizerMask CFIClasses =
+    CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast;
+const SanitizerMask CompatibleWithMinimalRuntime =
+    TrappingSupported | Scudo | ShadowCallStack;
 
 enum CoverageFeature {
   CoverageFunc = 1 << 0,
@@ -136,10 +139,10 @@
 
 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();
@@ -203,24 +206,26 @@
 }
 
 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,
@@ -455,8 +460,8 @@
 
   // 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)) {
@@ -959,18 +964,18 @@
           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);
 
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -2856,16 +2856,13 @@
 }
 
 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 {
Index: lib/Basic/Sanitizers.cpp
===================================================================
--- lib/Basic/Sanitizers.cpp
+++ lib/Basic/Sanitizers.cpp
@@ -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 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 @@
 #include "clang/Basic/Sanitizers.def"
   return Kinds;
 }
+
+llvm::hash_code SanitizerMask::hash_value() const {
+  return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]);
+}
+
+namespace llvm {
+hash_code hash_value(const clang::SanitizerMask &Arg) {
+  return Arg.hash_value();
+}
+} // namespace llvm
Index: lib/Basic/SanitizerSpecialCaseList.cpp
===================================================================
--- lib/Basic/SanitizerSpecialCaseList.cpp
+++ lib/Basic/SanitizerSpecialCaseList.cpp
@@ -36,7 +36,7 @@
 
 void SanitizerSpecialCaseList::createSanitizerSections() {
   for (auto &S : Sections) {
-    SanitizerMask Mask = 0;
+    SanitizerMask Mask;
 
 #define SANITIZER(NAME, ID)                                                    \
   if (S.SectionMatcher->match(NAME))                                           \
Index: include/clang/Driver/ToolChain.h
===================================================================
--- include/clang/Driver/ToolChain.h
+++ include/clang/Driver/ToolChain.h
@@ -563,7 +563,9 @@
   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
Index: include/clang/Basic/Sanitizers.h
===================================================================
--- include/clang/Basic/Sanitizers.h
+++ include/clang/Basic/Sanitizers.h
@@ -21,8 +21,114 @@
 #include <cstdint>
 
 namespace clang {
+class SanitizerMask;
+}
+
+namespace llvm {
+class hashcode;
+hash_code hash_value(const clang::SanitizerMask &Arg);
+} // namespace llvm
+
+namespace clang {
+
+namespace SanitizerKind {
+enum SanitizerOrdinal : 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(maskLoToHigh) * 8;
+  /// Number of bits in a mask element.
+  static constexpr unsigned kNumBitElem = sizeof(maskLoToHigh[0]) * 8;
+
+public:
+  static constexpr bool
+  checkBitPos(const SanitizerKind::SanitizerOrdinal Pos) {
+    return Pos < kNumBits;
+  }
+
+  /// Create a mask with a bit enabled at position Pos.
+  static SanitizerMask
+  bitPosToMask(const SanitizerKind::SanitizerOrdinal Pos) {
+    assert(Pos < kNumBits && "Bit position too big.");
+    SanitizerMask mask;
+    mask.maskLoToHigh[Pos / kNumBitElem] = 1ULL << Pos % kNumBitElem;
+    return mask;
+  }
+
+  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() {
+    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); }
+};
+
+inline SanitizerMask operator~(SanitizerMask v) {
+  v.flipAllBits();
+  return v;
+}
+
+inline SanitizerMask operator&(SanitizerMask a, const SanitizerMask &b) {
+  a &= b;
+  return a;
+}
 
-using SanitizerMask = uint64_t;
+inline SanitizerMask operator|(SanitizerMask a, const SanitizerMask &b) {
+  a |= b;
+  return a;
+}
 
 namespace SanitizerKind {
 
@@ -37,11 +143,15 @@
 
 // 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;
+#define SANITIZER(NAME, ID)                                                    \
+  static_assert(SanitizerMask::checkBitPos(SO_##ID),                           \
+                "Bit position too big.");                                      \
+  const SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);
+#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
+  static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
+                "Bit position too big.");                                      \
+  const SanitizerMask ID = SanitizerMask(ALIAS);                               \
+  const SanitizerMask ID##Group = SanitizerMask::bitPosToMask(SO_##ID##Group);
 #include "clang/Basic/Sanitizers.def"
 
 } // namespace SanitizerKind
@@ -49,16 +159,16 @@
 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 +176,10 @@
   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.
Index: include/clang/Basic/Sanitizers.def
===================================================================
--- include/clang/Basic/Sanitizers.def
+++ include/clang/Basic/Sanitizers.def
@@ -177,7 +177,7 @@
 
 // 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
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2360,7 +2360,7 @@
   let Documentation = [NoSanitizeDocs];
   let AdditionalMembers = [{
     SanitizerMask getMask() const {
-      SanitizerMask Mask = 0;
+      SanitizerMask Mask;
       for (auto SanitizerName : sanitizers()) {
         SanitizerMask ParsedMask =
             parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to