clang 20.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/SmallVector.h"
16#include "llvm/ADT/StringSwitch.h"
17#include "llvm/Support/Format.h"
18#include "llvm/Support/MathExtras.h"
19#include "llvm/Support/raw_ostream.h"
20#include <algorithm>
21#include <optional>
22
23using namespace clang;
24
25static const double SanitizerMaskCutoffsEps = 0.000000001f;
26
28 if (V < SanitizerMaskCutoffsEps && Cutoffs.empty())
29 return;
30 for (unsigned int i = 0; i < SanitizerKind::SO_Count; ++i)
31 if (K & SanitizerMask::bitPosToMask(i)) {
32 Cutoffs.resize(SanitizerKind::SO_Count);
33 Cutoffs[i] = V;
34 }
35}
36
37std::optional<double> SanitizerMaskCutoffs::operator[](unsigned Kind) const {
38 if (Cutoffs.empty() || Cutoffs[Kind] < SanitizerMaskCutoffsEps)
39 return std::nullopt;
40
41 return Cutoffs[Kind];
42}
43
45
46// Once LLVM switches to C++17, the constexpr variables can be inline and we
47// won't need this.
48#define SANITIZER(NAME, ID) constexpr SanitizerMask SanitizerKind::ID;
49#define SANITIZER_GROUP(NAME, ID, ALIAS) \
50 constexpr SanitizerMask SanitizerKind::ID; \
51 constexpr SanitizerMask SanitizerKind::ID##Group;
52#include "clang/Basic/Sanitizers.def"
53
54SanitizerMask clang::parseSanitizerValue(StringRef Value, bool AllowGroups) {
55 SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
56#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
57#define SANITIZER_GROUP(NAME, ID, ALIAS) \
58 .Case(NAME, AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
59#include "clang/Basic/Sanitizers.def"
60 .Default(SanitizerMask());
61 return ParsedKind;
62}
63
64bool clang::parseSanitizerWeightedValue(StringRef Value, bool AllowGroups,
65 SanitizerMaskCutoffs &Cutoffs) {
66 SanitizerMask ParsedKind = llvm::StringSwitch<SanitizerMask>(Value)
67#define SANITIZER(NAME, ID) .StartsWith(NAME "=", SanitizerKind::ID)
68#define SANITIZER_GROUP(NAME, ID, ALIAS) \
69 .StartsWith(NAME "=", \
70 AllowGroups ? SanitizerKind::ID##Group : SanitizerMask())
71#include "clang/Basic/Sanitizers.def"
72 .Default(SanitizerMask());
73
74 if (!ParsedKind)
75 return false;
76 auto [N, W] = Value.split('=');
77 double A;
78 if (W.getAsDouble(A))
79 return false;
80 A = std::clamp(A, 0.0, 1.0);
81 // AllowGroups is already taken into account for ParsedKind,
82 // hence we unconditionally expandSanitizerGroups.
83 Cutoffs.set(expandSanitizerGroups(ParsedKind), A);
84 return true;
85}
86
89#define SANITIZER(NAME, ID) \
90 if (Set.has(SanitizerKind::ID)) \
91 Values.push_back(NAME);
92#include "clang/Basic/Sanitizers.def"
93}
94
96 const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl<std::string> &Values) {
97#define SANITIZER(NAME, ID) \
98 if (auto C = Cutoffs[SanitizerKind::SO_##ID]) { \
99 std::string Str; \
100 llvm::raw_string_ostream OS(Str); \
101 OS << NAME "=" << llvm::format("%.8f", *C); \
102 Values.emplace_back(StringRef(Str).rtrim('0')); \
103 }
104#include "clang/Basic/Sanitizers.def"
105}
106