clang 22.0.0git
Sanitizers.cpp
Go to the documentation of this file.
1//===- Sanitizers.cpp - C Language Family Language Options ----------------===//
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// This file defines the classes from Sanitizers.h
10//
11//===----------------------------------------------------------------------===//
12
14#include "llvm/ADT/Hashing.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/Format.h"
17#include "llvm/Support/raw_ostream.h"
18#include <algorithm>
19#include <cmath>
20#include <optional>
21
22using namespace clang;
23
24static const double SanitizerMaskCutoffsEps = 0.000000001f;
25
27 if (V < SanitizerMaskCutoffsEps && Cutoffs.empty())
28 return;
29 for (unsigned int i = 0; i < SanitizerKind::SO_Count; ++i)
30 if (K & SanitizerMask::bitPosToMask(i)) {
31 Cutoffs.resize(SanitizerKind::SO_Count);
32 Cutoffs[i] = V;
33 }
34}
35
36std::optional<double> SanitizerMaskCutoffs::operator[](unsigned Kind) const {
37 if (Cutoffs.empty() || Cutoffs[Kind] < SanitizerMaskCutoffsEps)
38 return std::nullopt;
39
40 return Cutoffs[Kind];
41}
42
44
45std::optional<std::vector<unsigned>>
46SanitizerMaskCutoffs::getAllScaled(unsigned ScalingFactor) const {
47 std::vector<unsigned> ScaledCutoffs;
48
49 bool AnyCutoff = false;
50 for (unsigned int i = 0; i < SanitizerKind::SO_Count; ++i) {
51 auto C = (*this)[i];
52 if (C.has_value()) {
53 ScaledCutoffs.push_back(lround(std::clamp(*C, 0.0, 1.0) * ScalingFactor));
54 AnyCutoff = true;
55 } else {
56 ScaledCutoffs.push_back(0);
57 }
58 }
59
60 if (AnyCutoff)
61 return ScaledCutoffs;
62
63 return std::nullopt;
64}
65
66// Once LLVM switches to C++17, the constexpr variables can be inline and we
67// won't need this.
68#define SANITIZER(NAME, ID) constexpr SanitizerMask SanitizerKind::ID;
69#define SANITIZER_GROUP(NAME, ID, ALIAS) \
70 constexpr SanitizerMask SanitizerKind::ID; \
71 constexpr SanitizerMask SanitizerKind::ID##Group;
72#include "clang/Basic/Sanitizers.def"
73
74SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
75 SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
76#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
77#define SANITIZER_GROUP(NAME, ID, ALIAS) \
78 .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
79#include "clang/Basic/Sanitizers.def"
80 .Default(SanitizerMask());
81 return ParsedKind;
82}
83
84bool clang::parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
85 SanitizerMaskCutoffs &Cutoffs) {
86 SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
87#define SANITIZER(NAME, ID) .StartsWith(NAME "=", SanitizerKind::ID)
88#define SANITIZER_GROUP(NAME, ID, ALIAS) \
89 .StartsWith(NAME "=", \
90 AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
91#include "clang/Basic/Sanitizers.def"
92 .Default(SanitizerMask());
93
94 if (!ParsedKind)
95 return false;
96 auto [N, W] = Value.split('=');
97 double A;
98 if (W.getAsDouble(A) || A < 0.0 || A > 1.0)
99 return false;
100 // AllowGroups is already taken into account for ParsedKind,
101 // hence we unconditionally expandSanitizerGroups.
102 Cutoffs.set(expandSanitizerGroups(ParsedKind), A);
103 return true;
104}
105
108#define SANITIZER(NAME, ID) \
109 if (Set.has(SanitizerKind::ID)) \
110 Values.push_back(NAME);
111#include "clang/Basic/Sanitizers.def"
112}
113
115 const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl<std::string> &Values) {
116#define SANITIZER(NAME, ID) \
117 if (auto C = Cutoffs[SanitizerKind::SO_##ID]) { \
118 std::string Str; \
119 llvm::raw_string_ostream OS(Str); \
120 OS << NAME "=" << llvm::format("%.8f", *C); \
121 Values.emplace_back(StringRef(Str).rtrim('0')); \
122 }
123#include "clang/Basic/Sanitizers.def"
124}
125
127#define SANITIZER(NAME, ID)
128#define SANITIZER_GROUP(NAME, ID, ALIAS) \
129 if (Kinds & SanitizerKind::ID##Group) \
130 Kinds |= SanitizerKind::ID;
131#include "clang/Basic/Sanitizers.def"
132 return Kinds;
133}
134
135llvm::hash_code SanitizerMask::hash_value() const {
136 return llvm::hash_combine_range(&maskLoToHigh[0], &maskLoToHigh[kNumElem]);
137}
138
139namespace clang {
141 unsigned total = 0;
142 for (const auto &Val : maskLoToHigh)
143 total += llvm::popcount(Val);
144 return total;
145}
146
147llvm::hash_code hash_value(const clang::SanitizerMask &Arg) {
148 return Arg.hash_value();
149}
150
151StringRef AsanDtorKindToString(llvm::AsanDtorKind kind) {
152 switch (kind) {
153 case llvm::AsanDtorKind::None:
154 return "none";
155 case llvm::AsanDtorKind::Global:
156 return "global";
157 case llvm::AsanDtorKind::Invalid:
158 return "invalid";
159 }
160 return "invalid";
161}
162
163llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) {
164 return llvm::StringSwitch<llvm::AsanDtorKind>(kindStr)
165 .Case("none", llvm::AsanDtorKind::None)
166 .Case("global", llvm::AsanDtorKind::Global)
167 .Default(llvm::AsanDtorKind::Invalid);
168}
169
171 llvm::AsanDetectStackUseAfterReturnMode mode) {
172 switch (mode) {
173 case llvm::AsanDetectStackUseAfterReturnMode::Always:
174 return "always";
175 case llvm::AsanDetectStackUseAfterReturnMode::Runtime:
176 return "runtime";
177 case llvm::AsanDetectStackUseAfterReturnMode::Never:
178 return "never";
179 case llvm::AsanDetectStackUseAfterReturnMode::Invalid:
180 return "invalid";
181 }
182 return "invalid";
183}
184
185llvm::AsanDetectStackUseAfterReturnMode
187 return llvm::StringSwitch<llvm::AsanDetectStackUseAfterReturnMode>(modeStr)
188 .Case("always", llvm::AsanDetectStackUseAfterReturnMode::Always)
189 .Case("runtime", llvm::AsanDetectStackUseAfterReturnMode::Runtime)
190 .Case("never", llvm::AsanDetectStackUseAfterReturnMode::Never)
191 .Default(llvm::AsanDetectStackUseAfterReturnMode::Invalid);
192}
193
194} // namespace clang
#define V(N, I)
Definition: ASTContext.h:3597
static const double SanitizerMaskCutoffsEps
Definition: Sanitizers.cpp:24
Defines the clang::SanitizerKind enum.
void clear(SanitizerMask K=SanitizerKind::All)
Definition: Sanitizers.cpp:43
void set(SanitizerMask K, double V)
Definition: Sanitizers.cpp:26
std::optional< double > operator[](unsigned Kind) const
Definition: Sanitizers.cpp:36
std::optional< std::vector< unsigned > > getAllScaled(unsigned ScalingFactor) const
Definition: Sanitizers.cpp:46
llvm::hash_code hash_value() const
Definition: Sanitizers.cpp:135
unsigned countPopulation() const
Definition: Sanitizers.cpp:140
static constexpr SanitizerMask bitPosToMask(const unsigned Pos)
Create a mask with a bit enabled at position Pos.
Definition: Sanitizers.h:59
The JSON file list parser is used to communicate input to InstallAPI.
StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)
Definition: Sanitizers.cpp:151
void serializeSanitizerSet(SanitizerSet Set, SmallVectorImpl< StringRef > &Values)
Serialize a SanitizerSet into values for -fsanitize= or -fno-sanitize=.
Definition: Sanitizers.cpp:106
bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups, SanitizerMaskCutoffs &Cutoffs)
Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or -fno-sanitize= value lis...
Definition: Sanitizers.cpp:84
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)
For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.
Definition: Sanitizers.cpp:126
void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl< std::string > &Values)
Serialize a SanitizerMaskCutoffs into command line arguments.
Definition: Sanitizers.cpp:114
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)
Parse a single value from a -fsanitize= or -fno-sanitize= value list.
Definition: Sanitizers.cpp:74
llvm::hash_code hash_value(const CustomizableOptional< T > &O)
llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind)
Definition: Sanitizers.cpp:163
llvm::AsanDetectStackUseAfterReturnMode AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr)
Definition: Sanitizers.cpp:186
StringRef AsanDetectStackUseAfterReturnModeToString(llvm::AsanDetectStackUseAfterReturnMode mode)
Definition: Sanitizers.cpp:170
#define lround(__x)
Definition: tgmath.h:1021