File indexing completed on 2026-05-10 08:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_BASIC_SANITIZERS_H
0015 #define LLVM_CLANG_BASIC_SANITIZERS_H
0016
0017 #include "clang/Basic/LLVM.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/Support/HashBuilder.h"
0020 #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
0021 #include <cassert>
0022 #include <cstdint>
0023
0024 namespace llvm {
0025 class hash_code;
0026 class Triple;
0027 namespace opt {
0028 class ArgList;
0029 }
0030 }
0031
0032 namespace clang {
0033
0034 class SanitizerMask {
0035
0036
0037
0038
0039
0040 static constexpr unsigned kNumElem = 2;
0041
0042 uint64_t maskLoToHigh[kNumElem]{};
0043
0044 static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
0045
0046 static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
0047
0048 constexpr SanitizerMask(uint64_t mask1, uint64_t mask2)
0049 : maskLoToHigh{mask1, mask2} {}
0050
0051 public:
0052 SanitizerMask() = default;
0053
0054 static constexpr bool checkBitPos(const unsigned Pos) {
0055 return Pos < kNumBits;
0056 }
0057
0058
0059 static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
0060 uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
0061 uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
0062 ? 1ULL << (Pos % kNumBitElem)
0063 : 0;
0064 return SanitizerMask(mask1, mask2);
0065 }
0066
0067 unsigned countPopulation() const;
0068
0069 void flipAllBits() {
0070 for (auto &Val : maskLoToHigh)
0071 Val = ~Val;
0072 }
0073
0074 bool isPowerOf2() const {
0075 return countPopulation() == 1;
0076 }
0077
0078 llvm::hash_code hash_value() const;
0079
0080 template <typename HasherT, llvm::endianness Endianness>
0081 friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
0082 const SanitizerMask &SM) {
0083 HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]);
0084 }
0085
0086 constexpr explicit operator bool() const {
0087 return maskLoToHigh[0] || maskLoToHigh[1];
0088 }
0089
0090 constexpr bool operator==(const SanitizerMask &V) const {
0091 return maskLoToHigh[0] == V.maskLoToHigh[0] &&
0092 maskLoToHigh[1] == V.maskLoToHigh[1];
0093 }
0094
0095 SanitizerMask &operator&=(const SanitizerMask &RHS) {
0096 for (unsigned k = 0; k < kNumElem; k++)
0097 maskLoToHigh[k] &= RHS.maskLoToHigh[k];
0098 return *this;
0099 }
0100
0101 SanitizerMask &operator|=(const SanitizerMask &RHS) {
0102 for (unsigned k = 0; k < kNumElem; k++)
0103 maskLoToHigh[k] |= RHS.maskLoToHigh[k];
0104 return *this;
0105 }
0106
0107 constexpr bool operator!() const { return !bool(*this); }
0108
0109 constexpr bool operator!=(const SanitizerMask &RHS) const {
0110 return !((*this) == RHS);
0111 }
0112
0113 friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
0114 return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
0115 }
0116
0117 friend constexpr inline SanitizerMask operator&(SanitizerMask a,
0118 const SanitizerMask &b) {
0119 return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
0120 a.maskLoToHigh[1] & b.maskLoToHigh[1]);
0121 }
0122
0123 friend constexpr inline SanitizerMask operator|(SanitizerMask a,
0124 const SanitizerMask &b) {
0125 return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
0126 a.maskLoToHigh[1] | b.maskLoToHigh[1]);
0127 }
0128 };
0129
0130
0131 llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
0132
0133
0134
0135 struct SanitizerKind {
0136
0137
0138 enum SanitizerOrdinal : uint64_t {
0139 #define SANITIZER(NAME, ID) SO_##ID,
0140 #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
0141 #include "clang/Basic/Sanitizers.def"
0142 SO_Count
0143 };
0144
0145 #define SANITIZER(NAME, ID) \
0146 static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID); \
0147 static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
0148 #define SANITIZER_GROUP(NAME, ID, ALIAS) \
0149 static constexpr SanitizerMask ID = SanitizerMask(ALIAS); \
0150 static constexpr SanitizerMask ID##Group = \
0151 SanitizerMask::bitPosToMask(SO_##ID##Group); \
0152 static_assert(SanitizerMask::checkBitPos(SO_##ID##Group), \
0153 "Bit position too big.");
0154 #include "clang/Basic/Sanitizers.def"
0155 };
0156
0157 class SanitizerMaskCutoffs {
0158 std::vector<double> Cutoffs;
0159
0160 public:
0161 std::optional<double> operator[](unsigned Kind) const;
0162
0163 void set(SanitizerMask K, double V);
0164 void clear(SanitizerMask K = SanitizerKind::All);
0165 };
0166
0167 struct SanitizerSet {
0168
0169 bool has(SanitizerMask K) const {
0170 assert(K.isPowerOf2() && "Has to be a single sanitizer.");
0171 return static_cast<bool>(Mask & K);
0172 }
0173
0174 bool has(SanitizerKind::SanitizerOrdinal O) const {
0175 return has(SanitizerMask::bitPosToMask(O));
0176 }
0177
0178
0179 bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
0180
0181
0182 void set(SanitizerMask K, bool Value) {
0183 assert(K.isPowerOf2() && "Has to be a single sanitizer.");
0184 Mask = Value ? (Mask | K) : (Mask & ~K);
0185 }
0186
0187 void set(SanitizerMask K) { Mask = K; }
0188
0189
0190 void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
0191
0192
0193 bool empty() const { return !Mask; }
0194
0195
0196 SanitizerMask Mask;
0197 };
0198
0199
0200
0201 SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
0202
0203
0204
0205
0206
0207
0208
0209 bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
0210 SanitizerMaskCutoffs &Cutoffs);
0211
0212
0213 void serializeSanitizerSet(SanitizerSet Set,
0214 SmallVectorImpl<StringRef> &Values);
0215
0216
0217
0218 void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs,
0219 SmallVectorImpl<std::string> &Values);
0220
0221
0222
0223 SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
0224
0225
0226 inline SanitizerMask getPPTransparentSanitizers() {
0227 return SanitizerKind::CFI | SanitizerKind::Integer |
0228 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
0229 SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
0230 }
0231
0232 StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
0233
0234 llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
0235
0236 StringRef AsanDetectStackUseAfterReturnModeToString(
0237 llvm::AsanDetectStackUseAfterReturnMode mode);
0238
0239 llvm::AsanDetectStackUseAfterReturnMode
0240 AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
0241
0242 }
0243
0244 #endif