1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_BASIC_SANITIZERS_H |
15 | #define LLVM_CLANG_BASIC_SANITIZERS_H |
16 | |
17 | #include "clang/Basic/LLVM.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/Support/MathExtras.h" |
20 | #include <cassert> |
21 | #include <cstdint> |
22 | |
23 | namespace llvm { |
24 | class hash_code; |
25 | } |
26 | |
27 | namespace clang { |
28 | |
29 | class SanitizerMask { |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | static constexpr unsigned kNumElem = 2; |
36 | |
37 | uint64_t maskLoToHigh[kNumElem]{}; |
38 | |
39 | static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8; |
40 | |
41 | static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8; |
42 | |
43 | constexpr SanitizerMask(uint64_t mask1, uint64_t mask2) |
44 | : maskLoToHigh{mask1, mask2} {} |
45 | |
46 | public: |
47 | SanitizerMask() = default; |
48 | |
49 | static constexpr bool checkBitPos(const unsigned Pos) { |
50 | return Pos < kNumBits; |
51 | } |
52 | |
53 | |
54 | static constexpr SanitizerMask bitPosToMask(const unsigned Pos) { |
55 | return SanitizerMask((Pos < kNumBitElem) ? 1ULL << Pos % kNumBitElem : 0, |
56 | (Pos >= kNumBitElem && Pos < kNumBitElem * 2) |
57 | ? 1ULL << Pos % kNumBitElem |
58 | : 0); |
59 | } |
60 | |
61 | unsigned countPopulation() const { |
62 | unsigned total = 0; |
63 | for (const auto &Val : maskLoToHigh) |
64 | total += llvm::countPopulation(Val); |
65 | return total; |
66 | } |
67 | |
68 | void flipAllBits() { |
69 | for (auto &Val : maskLoToHigh) |
70 | Val = ~Val; |
71 | } |
72 | |
73 | bool isPowerOf2() const { |
74 | return countPopulation() == 1; |
75 | } |
76 | |
77 | llvm::hash_code hash_value() const; |
78 | |
79 | constexpr explicit operator bool() const { |
80 | return maskLoToHigh[0] || maskLoToHigh[1]; |
81 | } |
82 | |
83 | constexpr bool operator==(const SanitizerMask &V) const { |
84 | return maskLoToHigh[0] == V.maskLoToHigh[0] && |
85 | maskLoToHigh[1] == V.maskLoToHigh[1]; |
86 | } |
87 | |
88 | SanitizerMask &operator&=(const SanitizerMask &RHS) { |
89 | for (unsigned k = 0; k < kNumElem; k++) |
90 | maskLoToHigh[k] &= RHS.maskLoToHigh[k]; |
91 | return *this; |
92 | } |
93 | |
94 | SanitizerMask &operator|=(const SanitizerMask &RHS) { |
95 | for (unsigned k = 0; k < kNumElem; k++) |
96 | maskLoToHigh[k] |= RHS.maskLoToHigh[k]; |
97 | return *this; |
98 | } |
99 | |
100 | constexpr bool operator!() const { return !bool(*this); } |
101 | |
102 | constexpr bool operator!=(const SanitizerMask &RHS) const { |
103 | return !((*this) == RHS); |
104 | } |
105 | |
106 | friend constexpr inline SanitizerMask operator~(SanitizerMask v) { |
107 | return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]); |
108 | } |
109 | |
110 | friend constexpr inline SanitizerMask operator&(SanitizerMask a, |
111 | const SanitizerMask &b) { |
112 | return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0], |
113 | a.maskLoToHigh[1] & b.maskLoToHigh[1]); |
114 | } |
115 | |
116 | friend constexpr inline SanitizerMask operator|(SanitizerMask a, |
117 | const SanitizerMask &b) { |
118 | return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0], |
119 | a.maskLoToHigh[1] | b.maskLoToHigh[1]); |
120 | } |
121 | }; |
122 | |
123 | |
124 | llvm::hash_code hash_value(const clang::SanitizerMask &Arg); |
125 | |
126 | |
127 | |
128 | struct SanitizerKind { |
129 | |
130 | |
131 | enum SanitizerOrdinal : uint64_t { |
132 | #define SANITIZER(NAME, ID) SO_##ID, |
133 | #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group, |
134 | #include "clang/Basic/Sanitizers.def" |
135 | SO_Count |
136 | }; |
137 | |
138 | #define SANITIZER(NAME, ID) \ |
139 | static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID); \ |
140 | static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big."); |
141 | #define SANITIZER_GROUP(NAME, ID, ALIAS) \ |
142 | static constexpr SanitizerMask ID = SanitizerMask(ALIAS); \ |
143 | static constexpr SanitizerMask ID##Group = \ |
144 | SanitizerMask::bitPosToMask(SO_##ID##Group); \ |
145 | static_assert(SanitizerMask::checkBitPos(SO_##ID##Group), \ |
146 | "Bit position too big."); |
147 | #include "clang/Basic/Sanitizers.def" |
148 | }; |
149 | |
150 | struct SanitizerSet { |
151 | |
152 | bool has(SanitizerMask K) const { |
153 | (0) . __assert_fail ("K.isPowerOf2() && \"Has to be a single sanitizer.\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Basic/Sanitizers.h", 153, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.isPowerOf2() && "Has to be a single sanitizer."); |
154 | return static_cast<bool>(Mask & K); |
155 | } |
156 | |
157 | |
158 | bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); } |
159 | |
160 | |
161 | void set(SanitizerMask K, bool Value) { |
162 | (0) . __assert_fail ("K.isPowerOf2() && \"Has to be a single sanitizer.\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Basic/Sanitizers.h", 162, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.isPowerOf2() && "Has to be a single sanitizer."); |
163 | Mask = Value ? (Mask | K) : (Mask & ~K); |
164 | } |
165 | |
166 | |
167 | void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } |
168 | |
169 | |
170 | bool empty() const { return !Mask; } |
171 | |
172 | |
173 | SanitizerMask Mask; |
174 | }; |
175 | |
176 | |
177 | |
178 | SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); |
179 | |
180 | |
181 | |
182 | SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); |
183 | |
184 | |
185 | inline SanitizerMask getPPTransparentSanitizers() { |
186 | return SanitizerKind::CFI | SanitizerKind::Integer | |
187 | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | |
188 | SanitizerKind::Undefined; |
189 | } |
190 | |
191 | } |
192 | |
193 | #endif |
194 | |