Coverage Report

Created: 2019-03-22 08:08

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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
0
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
59.5M
      : maskLoToHigh{mask1, mask2} {}
45
46
public:
47
2.98M
  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
    return SanitizerMask((Pos < kNumBitElem) ? 1ULL << Pos % kNumBitElem : 0,
56
0
                         (Pos >= kNumBitElem && Pos < kNumBitElem * 2)
57
0
                             ? 1ULL << Pos % kNumBitElem
58
0
                             : 0);
59
0
  }
60
61
0
  unsigned countPopulation() const {
62
0
    unsigned total = 0;
63
0
    for (const auto &Val : maskLoToHigh)
64
0
      total += llvm::countPopulation(Val);
65
0
    return total;
66
0
  }
67
68
0
  void flipAllBits() {
69
0
    for (auto &Val : maskLoToHigh)
70
0
      Val = ~Val;
71
0
  }
72
73
0
  bool isPowerOf2() const {
74
0
    return countPopulation() == 1;
75
0
  }
76
77
  llvm::hash_code hash_value() const;
78
79
48.9M
  constexpr explicit operator bool() const {
80
48.9M
    return maskLoToHigh[0] || 
maskLoToHigh[1]48.1M
;
81
48.9M
  }
82
83
12.9k
  constexpr bool operator==(const SanitizerMask &V) const {
84
12.9k
    return maskLoToHigh[0] == V.maskLoToHigh[0] &&
85
12.9k
           
maskLoToHigh[1] == V.maskLoToHigh[1]3.66k
;
86
12.9k
  }
87
88
135k
  SanitizerMask &operator&=(const SanitizerMask &RHS) {
89
405k
    for (unsigned k = 0; k < kNumElem; 
k++270k
)
90
270k
      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
91
135k
    return *this;
92
135k
  }
93
94
1.03M
  SanitizerMask &operator|=(const SanitizerMask &RHS) {
95
3.11M
    for (unsigned k = 0; k < kNumElem; 
k++2.07M
)
96
2.07M
      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
97
1.03M
    return *this;
98
1.03M
  }
99
100
1.03M
  constexpr bool operator!() const { return !bool(*this); }
101
102
3.59k
  constexpr bool operator!=(const SanitizerMask &RHS) const {
103
3.59k
    return !((*this) == RHS);
104
3.59k
  }
105
106
506k
  friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
107
506k
    return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
108
506k
  }
109
110
  friend constexpr inline SanitizerMask operator&(SanitizerMask a,
111
48.8M
                                                  const SanitizerMask &b) {
112
48.8M
    return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
113
48.8M
                         a.maskLoToHigh[1] & b.maskLoToHigh[1]);
114
48.8M
  }
115
116
  friend constexpr inline SanitizerMask operator|(SanitizerMask a,
117
10.1M
                                                  const SanitizerMask &b) {
118
10.1M
    return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
119
10.1M
                         a.maskLoToHigh[1] | b.maskLoToHigh[1]);
120
10.1M
  }
121
};
122
123
// Declaring in clang namespace so that it can be found by ADL.
124
llvm::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.
128
struct 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
150
struct SanitizerSet {
151
  /// Check if a certain (single) sanitizer is enabled.
152
34.4M
  bool has(SanitizerMask K) const {
153
34.4M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
154
34.4M
    return static_cast<bool>(Mask & K);
155
34.4M
  }
156
157
  /// Check if one or more sanitizers are enabled.
158
11.8M
  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
159
160
  /// Enable or disable a certain (single) sanitizer.
161
1.16M
  void set(SanitizerMask K, bool Value) {
162
1.16M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
163
1.16M
    Mask = Value ? 
(Mask | K)928k
:
(Mask & ~K)232k
;
164
1.16M
  }
165
166
  /// Disable the sanitizers specified in \p K.
167
9.20k
  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
168
169
  /// Returns true if no sanitizers are enabled.
170
554k
  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.
178
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
179
180
/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
181
/// this group enables.
182
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
183
184
/// Return the sanitizers which do not affect preprocessing.
185
5.61k
inline SanitizerMask getPPTransparentSanitizers() {
186
5.61k
  return SanitizerKind::CFI | SanitizerKind::Integer |
187
5.61k
         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
188
5.61k
         SanitizerKind::Undefined;
189
5.61k
}
190
191
} // namespace clang
192
193
#endif // LLVM_CLANG_BASIC_SANITIZERS_H