Coverage Report

Created: 2020-02-25 14:32

/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.9M
      : maskLoToHigh{mask1, mask2} {}
45
46
public:
47
4.87M
  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.4M
  unsigned countPopulation() const {
63
19.4M
    unsigned total = 0;
64
19.4M
    for (const auto &Val : maskLoToHigh)
65
38.8M
      total += llvm::countPopulation(Val);
66
19.4M
    return total;
67
19.4M
  }
68
69
0
  void flipAllBits() {
70
0
    for (auto &Val : maskLoToHigh)
71
0
      Val = ~Val;
72
0
  }
73
74
19.4M
  bool isPowerOf2() const {
75
19.4M
    return countPopulation() == 1;
76
19.4M
  }
77
78
  llvm::hash_code hash_value() const;
79
80
29.0M
  constexpr explicit operator bool() const {
81
29.0M
    return maskLoToHigh[0] || 
maskLoToHigh[1]28.1M
;
82
29.0M
  }
83
84
20.9k
  constexpr bool operator==(const SanitizerMask &V) const {
85
20.9k
    return maskLoToHigh[0] == V.maskLoToHigh[0] &&
86
20.9k
           
maskLoToHigh[1] == V.maskLoToHigh[1]6.83k
;
87
20.9k
  }
88
89
144k
  SanitizerMask &operator&=(const SanitizerMask &RHS) {
90
434k
    for (unsigned k = 0; k < kNumElem; 
k++289k
)
91
289k
      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
92
144k
    return *this;
93
144k
  }
94
95
1.06M
  SanitizerMask &operator|=(const SanitizerMask &RHS) {
96
3.19M
    for (unsigned k = 0; k < kNumElem; 
k++2.13M
)
97
2.13M
      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
98
1.06M
    return *this;
99
1.06M
  }
100
101
1.14M
  constexpr bool operator!() const { return !bool(*this); }
102
103
6.70k
  constexpr bool operator!=(const SanitizerMask &RHS) const {
104
6.70k
    return !((*this) == RHS);
105
6.70k
  }
106
107
723k
  friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
108
723k
    return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
109
723k
  }
110
111
  friend constexpr inline SanitizerMask operator&(SanitizerMask a,
112
29.2M
                                                  const SanitizerMask &b) {
113
29.2M
    return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
114
29.2M
                         a.maskLoToHigh[1] & b.maskLoToHigh[1]);
115
29.2M
  }
116
117
  friend constexpr inline SanitizerMask operator|(SanitizerMask a,
118
7.04M
                                                  const SanitizerMask &b) {
119
7.04M
    return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
120
7.04M
                         a.maskLoToHigh[1] | b.maskLoToHigh[1]);
121
7.04M
  }
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.7M
  bool has(SanitizerMask K) const {
154
18.7M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
155
18.7M
    return static_cast<bool>(Mask & K);
156
18.7M
  }
157
158
  /// Check if one or more sanitizers are enabled.
159
7.53M
  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
160
161
  /// Enable or disable a certain (single) sanitizer.
162
674k
  void set(SanitizerMask K, bool Value) {
163
674k
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
164
674k
    Mask = Value ? 
(Mask | K)261k
:
(Mask & ~K)412k
;
165
674k
  }
166
167
  /// Disable the sanitizers specified in \p K.
168
22.4k
  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
169
170
  /// Returns true if no sanitizers are enabled.
171
494k
  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
15.7k
inline SanitizerMask getPPTransparentSanitizers() {
187
15.7k
  return SanitizerKind::CFI | SanitizerKind::Integer |
188
15.7k
         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
189
15.7k
         SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
190
15.7k
}
191
192
} // namespace clang
193
194
#endif // LLVM_CLANG_BASIC_SANITIZERS_H