Clang Project

clang_source_code/include/clang/Basic/Sanitizers.h
1//===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Defines the clang::SanitizerKind enum.
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
23namespace llvm {
24class hash_code;
25}
26
27namespace clang {
28
29class SanitizerMask {
30  // NOTE: this class assumes kNumElem == 2 in most of the constexpr functions,
31  // in order to work within the C++11 constexpr function constraints. If you
32  // change kNumElem, you'll need to update those member functions as well.
33
34  /// Number of array elements.
35  static constexpr unsigned kNumElem = 2;
36  /// Mask value initialized to 0.
37  uint64_t maskLoToHigh[kNumElem]{};
38  /// Number of bits in a mask.
39  static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
40  /// Number of bits in a mask element.
41  static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
42
43  constexpr SanitizerMask(uint64_t mask1uint64_t mask2)
44      : maskLoToHigh{mask1mask2} {}
45
46public:
47  SanitizerMask() = default;
48
49  static constexpr bool checkBitPos(const unsigned Pos) {
50    return Pos < kNumBits;
51  }
52
53  /// Create a mask with a bit enabled at position Pos.
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 &Vconst {
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 = 0k < kNumElemk++)
90      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
91    return *this;
92  }
93
94  SanitizerMask &operator|=(const SanitizerMask &RHS) {
95    for (unsigned k = 0k < kNumElemk++)
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 &RHSconst {
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// Declaring in clang namespace so that it can be found by ADL.
124llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
125
126// Define the set of sanitizer kinds, as well as the set of sanitizers each
127// sanitizer group expands into.
128struct SanitizerKind {
129  // Assign ordinals to possible values of -fsanitize= flag, which we will use
130  // as bit positions.
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}; // SanitizerKind
149
150struct SanitizerSet {
151  /// Check if a certain (single) sanitizer is enabled.
152  bool has(SanitizerMask Kconst {
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  /// Check if one or more sanitizers are enabled.
158  bool hasOneOf(SanitizerMask Kconst { return static_cast<bool>(Mask & K); }
159
160  /// Enable or disable a certain (single) sanitizer.
161  void set(SanitizerMask Kbool 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  /// Disable the sanitizers specified in \p K.
167  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
168
169  /// Returns true if no sanitizers are enabled.
170  bool empty() const { return !Mask; }
171
172  /// Bitmask of enabled sanitizers.
173  SanitizerMask Mask;
174};
175
176/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
177/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
178SanitizerMask parseSanitizerValue(StringRef Valuebool AllowGroups);
179
180/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
181/// this group enables.
182SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
183
184/// Return the sanitizers which do not affect preprocessing.
185inline SanitizerMask getPPTransparentSanitizers() {
186  return SanitizerKind::CFI | SanitizerKind::Integer |
187         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
188         SanitizerKind::Undefined;
189}
190
191// namespace clang
192
193#endif // LLVM_CLANG_BASIC_SANITIZERS_H
194
clang::SanitizerMask::kNumElem
clang::SanitizerMask::maskLoToHigh
clang::SanitizerMask::kNumBits
clang::SanitizerMask::kNumBitElem
clang::SanitizerMask::checkBitPos
clang::SanitizerMask::bitPosToMask
clang::SanitizerMask::countPopulation
clang::SanitizerMask::flipAllBits
clang::SanitizerMask::isPowerOf2
clang::SanitizerMask::hash_value
clang::SanitizerKind::SanitizerOrdinal
clang::SanitizerSet::has
clang::SanitizerSet::hasOneOf
clang::SanitizerSet::set
clang::SanitizerSet::clear
clang::SanitizerSet::empty
clang::SanitizerSet::Mask