Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Basic/Sanitizers.h
Line
Count
Source (jump to first uncovered line)
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/HashBuilder.h"
20
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
21
#include <cassert>
22
#include <cstdint>
23
24
namespace llvm {
25
class hash_code;
26
}
27
28
namespace clang {
29
30
class SanitizerMask {
31
  // NOTE: this class assumes kNumElem == 2 in most of the constexpr functions,
32
  // in order to work within the C++11 constexpr function constraints. If you
33
  // change kNumElem, you'll need to update those member functions as well.
34
35
  /// Number of array elements.
36
  static constexpr unsigned kNumElem = 2;
37
  /// Mask value initialized to 0.
38
  uint64_t maskLoToHigh[kNumElem]{};
39
  /// Number of bits in a mask.
40
  static constexpr unsigned kNumBits = sizeof(decltype(maskLoToHigh)) * 8;
41
  /// Number of bits in a mask element.
42
  static constexpr unsigned kNumBitElem = sizeof(decltype(maskLoToHigh[0])) * 8;
43
44
  constexpr SanitizerMask(uint64_t mask1, uint64_t mask2)
45
59.3M
      : maskLoToHigh{mask1, mask2} {}
46
47
public:
48
12.7M
  SanitizerMask() = default;
49
50
0
  static constexpr bool checkBitPos(const unsigned Pos) {
51
0
    return Pos < kNumBits;
52
0
  }
53
54
  /// Create a mask with a bit enabled at position Pos.
55
0
  static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
56
0
    uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
57
0
    uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
58
0
                         ? 1ULL << (Pos % kNumBitElem)
59
0
                         : 0;
60
0
    return SanitizerMask(mask1, mask2);
61
0
  }
62
63
  unsigned countPopulation() const;
64
65
0
  void flipAllBits() {
66
0
    for (auto &Val : maskLoToHigh)
67
0
      Val = ~Val;
68
0
  }
69
70
43.3M
  bool isPowerOf2() const {
71
43.3M
    return countPopulation() == 1;
72
43.3M
  }
73
74
  llvm::hash_code hash_value() const;
75
76
  template <typename HasherT, llvm::support::endianness Endianness>
77
  friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
78
9
                      const SanitizerMask &SM) {
79
9
    HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]);
80
9
  }
81
82
51.6M
  constexpr explicit operator bool() const {
83
51.6M
    return maskLoToHigh[0] || 
maskLoToHigh[1]50.1M
;
84
51.6M
  }
85
86
24.3k
  constexpr bool operator==(const SanitizerMask &V) const {
87
24.3k
    return maskLoToHigh[0] == V.maskLoToHigh[0] &&
88
24.3k
           
maskLoToHigh[1] == V.maskLoToHigh[1]7.57k
;
89
24.3k
  }
90
91
275k
  SanitizerMask &operator&=(const SanitizerMask &RHS) {
92
825k
    for (unsigned k = 0; k < kNumElem; 
k++550k
)
93
550k
      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
94
275k
    return *this;
95
275k
  }
96
97
1.92M
  SanitizerMask &operator|=(const SanitizerMask &RHS) {
98
5.76M
    for (unsigned k = 0; k < kNumElem; 
k++3.84M
)
99
3.84M
      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
100
1.92M
    return *this;
101
1.92M
  }
102
103
1.52M
  constexpr bool operator!() const { return !bool(*this); }
104
105
7.36k
  constexpr bool operator!=(const SanitizerMask &RHS) const {
106
7.36k
    return !((*this) == RHS);
107
7.36k
  }
108
109
1.08M
  friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
110
1.08M
    return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
111
1.08M
  }
112
113
  friend constexpr inline SanitizerMask operator&(SanitizerMask a,
114
51.9M
                                                  const SanitizerMask &b) {
115
51.9M
    return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
116
51.9M
                         a.maskLoToHigh[1] & b.maskLoToHigh[1]);
117
51.9M
  }
118
119
  friend constexpr inline SanitizerMask operator|(SanitizerMask a,
120
6.31M
                                                  const SanitizerMask &b) {
121
6.31M
    return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
122
6.31M
                         a.maskLoToHigh[1] | b.maskLoToHigh[1]);
123
6.31M
  }
124
};
125
126
// Declaring in clang namespace so that it can be found by ADL.
127
llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
128
129
// Define the set of sanitizer kinds, as well as the set of sanitizers each
130
// sanitizer group expands into.
131
struct SanitizerKind {
132
  // Assign ordinals to possible values of -fsanitize= flag, which we will use
133
  // as bit positions.
134
  enum SanitizerOrdinal : uint64_t {
135
#define SANITIZER(NAME, ID) SO_##ID,
136
#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
137
#include "clang/Basic/Sanitizers.def"
138
    SO_Count
139
  };
140
141
#define SANITIZER(NAME, ID)                                                    \
142
  static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \
143
  static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
144
#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
145
  static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \
146
  static constexpr SanitizerMask ID##Group =                                   \
147
      SanitizerMask::bitPosToMask(SO_##ID##Group);                             \
148
  static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
149
                "Bit position too big.");
150
#include "clang/Basic/Sanitizers.def"
151
}; // SanitizerKind
152
153
struct SanitizerSet {
154
  /// Check if a certain (single) sanitizer is enabled.
155
42.5M
  bool has(SanitizerMask K) const {
156
42.5M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
157
0
    return static_cast<bool>(Mask & K);
158
42.5M
  }
159
160
  /// Check if one or more sanitizers are enabled.
161
4.28M
  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
162
163
  /// Enable or disable a certain (single) sanitizer.
164
793k
  void set(SanitizerMask K, bool Value) {
165
793k
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
166
793k
    Mask = Value ? 
(Mask | K)307k
:
(Mask & ~K)486k
;
167
793k
  }
168
169
  /// Disable the sanitizers specified in \p K.
170
29.3k
  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
171
172
  /// Returns true if no sanitizers are enabled.
173
590k
  bool empty() const { return !Mask; }
174
175
  /// Bitmask of enabled sanitizers.
176
  SanitizerMask Mask;
177
};
178
179
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
180
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
181
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
182
183
/// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
184
void serializeSanitizerSet(SanitizerSet Set,
185
                           SmallVectorImpl<StringRef> &Values);
186
187
/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
188
/// this group enables.
189
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
190
191
/// Return the sanitizers which do not affect preprocessing.
192
21.9k
inline SanitizerMask getPPTransparentSanitizers() {
193
21.9k
  return SanitizerKind::CFI | SanitizerKind::Integer |
194
21.9k
         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
195
21.9k
         SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
196
21.9k
}
197
198
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
199
200
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
201
202
StringRef AsanDetectStackUseAfterReturnModeToString(
203
    llvm::AsanDetectStackUseAfterReturnMode mode);
204
205
llvm::AsanDetectStackUseAfterReturnMode
206
AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
207
208
} // namespace clang
209
210
#endif // LLVM_CLANG_BASIC_SANITIZERS_H