Coverage Report

Created: 2021-08-24 07:12

/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/Transforms/Instrumentation/AddressSanitizerOptions.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
59.0M
      : maskLoToHigh{mask1, mask2} {}
45
46
public:
47
9.43M
  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
  unsigned countPopulation() const;
63
64
0
  void flipAllBits() {
65
0
    for (auto &Val : maskLoToHigh)
66
0
      Val = ~Val;
67
0
  }
68
69
44.1M
  bool isPowerOf2() const {
70
44.1M
    return countPopulation() == 1;
71
44.1M
  }
72
73
  llvm::hash_code hash_value() const;
74
75
51.7M
  constexpr explicit operator bool() const {
76
51.7M
    return maskLoToHigh[0] || 
maskLoToHigh[1]50.4M
;
77
51.7M
  }
78
79
24.5k
  constexpr bool operator==(const SanitizerMask &V) const {
80
24.5k
    return maskLoToHigh[0] == V.maskLoToHigh[0] &&
81
24.5k
           
maskLoToHigh[1] == V.maskLoToHigh[1]7.23k
;
82
24.5k
  }
83
84
232k
  SanitizerMask &operator&=(const SanitizerMask &RHS) {
85
698k
    for (unsigned k = 0; k < kNumElem; 
k++465k
)
86
465k
      maskLoToHigh[k] &= RHS.maskLoToHigh[k];
87
232k
    return *this;
88
232k
  }
89
90
1.62M
  SanitizerMask &operator|=(const SanitizerMask &RHS) {
91
4.88M
    for (unsigned k = 0; k < kNumElem; 
k++3.25M
)
92
3.25M
      maskLoToHigh[k] |= RHS.maskLoToHigh[k];
93
1.62M
    return *this;
94
1.62M
  }
95
96
1.54M
  constexpr bool operator!() const { return !bool(*this); }
97
98
7.08k
  constexpr bool operator!=(const SanitizerMask &RHS) const {
99
7.08k
    return !((*this) == RHS);
100
7.08k
  }
101
102
968k
  friend constexpr inline SanitizerMask operator~(SanitizerMask v) {
103
968k
    return SanitizerMask(~v.maskLoToHigh[0], ~v.maskLoToHigh[1]);
104
968k
  }
105
106
  friend constexpr inline SanitizerMask operator&(SanitizerMask a,
107
51.8M
                                                  const SanitizerMask &b) {
108
51.8M
    return SanitizerMask(a.maskLoToHigh[0] & b.maskLoToHigh[0],
109
51.8M
                         a.maskLoToHigh[1] & b.maskLoToHigh[1]);
110
51.8M
  }
111
112
  friend constexpr inline SanitizerMask operator|(SanitizerMask a,
113
6.21M
                                                  const SanitizerMask &b) {
114
6.21M
    return SanitizerMask(a.maskLoToHigh[0] | b.maskLoToHigh[0],
115
6.21M
                         a.maskLoToHigh[1] | b.maskLoToHigh[1]);
116
6.21M
  }
117
};
118
119
// Declaring in clang namespace so that it can be found by ADL.
120
llvm::hash_code hash_value(const clang::SanitizerMask &Arg);
121
122
// Define the set of sanitizer kinds, as well as the set of sanitizers each
123
// sanitizer group expands into.
124
struct SanitizerKind {
125
  // Assign ordinals to possible values of -fsanitize= flag, which we will use
126
  // as bit positions.
127
  enum SanitizerOrdinal : uint64_t {
128
#define SANITIZER(NAME, ID) SO_##ID,
129
#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
130
#include "clang/Basic/Sanitizers.def"
131
    SO_Count
132
  };
133
134
#define SANITIZER(NAME, ID)                                                    \
135
  static constexpr SanitizerMask ID = SanitizerMask::bitPosToMask(SO_##ID);    \
136
  static_assert(SanitizerMask::checkBitPos(SO_##ID), "Bit position too big.");
137
#define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
138
  static constexpr SanitizerMask ID = SanitizerMask(ALIAS);                    \
139
  static constexpr SanitizerMask ID##Group =                                   \
140
      SanitizerMask::bitPosToMask(SO_##ID##Group);                             \
141
  static_assert(SanitizerMask::checkBitPos(SO_##ID##Group),                    \
142
                "Bit position too big.");
143
#include "clang/Basic/Sanitizers.def"
144
}; // SanitizerKind
145
146
struct SanitizerSet {
147
  /// Check if a certain (single) sanitizer is enabled.
148
43.3M
  bool has(SanitizerMask K) const {
149
43.3M
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
150
0
    return static_cast<bool>(Mask & K);
151
43.3M
  }
152
153
  /// Check if one or more sanitizers are enabled.
154
4.21M
  bool hasOneOf(SanitizerMask K) const { return static_cast<bool>(Mask & K); }
155
156
  /// Enable or disable a certain (single) sanitizer.
157
762k
  void set(SanitizerMask K, bool Value) {
158
762k
    assert(K.isPowerOf2() && "Has to be a single sanitizer.");
159
762k
    Mask = Value ? 
(Mask | K)309k
:
(Mask & ~K)452k
;
160
762k
  }
161
162
  /// Disable the sanitizers specified in \p K.
163
27.8k
  void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; }
164
165
  /// Returns true if no sanitizers are enabled.
166
678k
  bool empty() const { return !Mask; }
167
168
  /// Bitmask of enabled sanitizers.
169
  SanitizerMask Mask;
170
};
171
172
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
173
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
174
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
175
176
/// Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
177
void serializeSanitizerSet(SanitizerSet Set,
178
                           SmallVectorImpl<StringRef> &Values);
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
20.7k
inline SanitizerMask getPPTransparentSanitizers() {
186
20.7k
  return SanitizerKind::CFI | SanitizerKind::Integer |
187
20.7k
         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
188
20.7k
         SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
189
20.7k
}
190
191
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
192
193
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
194
195
StringRef AsanDetectStackUseAfterReturnModeToString(
196
    llvm::AsanDetectStackUseAfterReturnMode mode);
197
198
llvm::AsanDetectStackUseAfterReturnMode
199
AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
200
201
} // namespace clang
202
203
#endif // LLVM_CLANG_BASIC_SANITIZERS_H