Coverage Report

Created: 2021-01-19 06:58

/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/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
  // 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 mask1, uint64_t mask2)
44
36.8M
      : maskLoToHigh{mask1, mask2} {}
45
46
public:
47
8.02M
  SanitizerMask() = default;
48
49
0
  static constexpr bool checkBitPos(const unsigned Pos) {
50
0
    return Pos < kNumBits;
51
0
  }
52
53
  /// Create a mask with a bit enabled at position Pos.
54
0
  static constexpr SanitizerMask bitPosToMask(const unsigned Pos) {
55
0
    uint64_t mask1 = (Pos < kNumBitElem) ? 1ULL << (Pos % kNumBitElem) : 0;
56
0
    uint64_t mask2 = (Pos >= kNumBitElem && Pos < (kNumBitElem * 2))
57
0
                         ? 1ULL << (Pos % kNumBitElem)
58
0
                         : 0;
59
0
    return SanitizerMask(mask1, mask2);
60
0
  }
61
62
19.3M
  unsigned countPopulation() const {
63
19.3M
    unsigned total = 0;
64
19.3M
    for (const auto &Val : maskLoToHigh)
65
38.7M
      total += llvm::countPopulation(Val);
66
19.3M
    return total;
67
19.3M
  }
68
69
0
  void flipAllBits() {
70
0
    for (auto &Val : maskLoToHigh)
71
0
      Val = ~Val;
72
0
  }
73
74
19.3M
  bool isPowerOf2() const {
75
19.3M
    return countPopulation() == 1;
76
19.3M
  }
77
78
  llvm::hash_code hash_value() const;
79
80
28.5M
  constexpr explicit operator bool() const {
81
28.5M
    return maskLoToHigh[0] || 
maskLoToHigh[1]27.2M
;
82
28.5M
  }
83
84
22.6k
  constexpr bool operator==(const SanitizerMask &V) const {
85
22.6k
    return maskLoToHigh[0] == V.maskLoToHigh[0] &&
86
7.84k
           maskLoToHigh[1] == V.maskLoToHigh[1];
87
22.6k
  }
88
89
238k
  SanitizerMask &operator&=(const SanitizerMask &RHS) {
90
714k
    for (unsigned k = 0; k < kNumElem; 
k++476k
)
91
476k
      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
92
238k
    return *this;
93
238k
  }
94
95
1.67M
  SanitizerMask &operator|=(const SanitizerMask &RHS) {
96
5.03M
    for (unsigned k = 0; k < kNumElem; 
k++3.35M
)
97
3.35M
      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
98
1.67M
    return *this;
99
1.67M
  }
100
101
1.38M
  constexpr bool operator!() const { return !bool(*this); }
102
103
7.72k
  constexpr bool operator!=(const SanitizerMask &RHS) const {
104
7.72k
    return !((*this) == RHS);
105
7.72k
  }
106
107
1.01M
  friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
108
1.01M
    return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
109
1.01M
  }
110
111
  friend constexpr inline SanitizerMask operator&(SanitizerMask a,
112
28.8M
                                                  const SanitizerMask &b) {
113
28.8M
    return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
114
28.8M
                         a.maskLoToHigh[1] & b.maskLoToHigh[1]);
115
28.8M
  }
116
117
  friend constexpr inline SanitizerMask operator|(SanitizerMask a,
118
7.01M
                                                  const SanitizerMask &b) {
119
7.01M
    return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
120
7.01M
                         a.maskLoToHigh[1] | b.maskLoToHigh[1]);
121
7.01M
  }
122
};
123
124
// Declaring in clang namespace so that it can be found by ADL.
125
llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
126
127
// Define the set of sanitizer kinds, as well as the set of sanitizers each
128
// sanitizer group expands into.
129
struct SanitizerKind {
130
  // Assign ordinals to possible values of -fsanitize= flag, which we will use
131
  // as bit positions.
132
  enum SanitizerOrdinal : uint64_t {
133
#define SANITIZER(NAME, ID) SO_##ID,
134
#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
135
#include "clang/Basic/Sanitizers.def"
136
    SO_Count
137
  };
138
139
#define SANITIZER(NAME, ID)                                                    \
140
  static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \
141
  static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
142
#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
143
  static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \
144
  static constexpr SanitizerMask ID##Group =                                   \
145
      SanitizerMask::bitPosToMask(SO_##ID##Group);                             \
146
  static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
147
                "Bit position too big.");
148
#include "clang/Basic/Sanitizers.def"
149
}; // SanitizerKind
150
151
struct SanitizerSet {
152
  /// Check if a certain (single) sanitizer is enabled.
153
18.5M
  bool has(SanitizerMask K) const {
154
18.5M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
155
18.5M
    return static_cast<bool>(Mask & K);
156
18.5M
  }
157
158
  /// Check if one or more sanitizers are enabled.
159
5.90M
  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
160
161
  /// Enable or disable a certain (single) sanitizer.
162
770k
  void set(SanitizerMask K, bool Value) {
163
770k
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
164
485k
    Mask = Value ? 
(Mask | K)284k
: (Mask & ~K);
165
770k
  }
166
167
  /// Disable the sanitizers specified in \p K.
168
29.5k
  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
169
170
  /// Returns true if no sanitizers are enabled.
171
589k
  bool empty() const { return !Mask; }
172
173
  /// Bitmask of enabled sanitizers.
174
  SanitizerMask Mask;
175
};
176
177
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
178
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
179
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
180
181
/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
182
/// this group enables.
183
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
184
185
/// Return the sanitizers which do not affect preprocessing.
186
21.7k
inline SanitizerMask getPPTransparentSanitizers() {
187
21.7k
  return SanitizerKind::CFI | SanitizerKind::Integer |
188
21.7k
         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
189
21.7k
         SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
190
21.7k
}
191
192
} // namespace clang
193
194
#endif // LLVM_CLANG_BASIC_SANITIZERS_H