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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits