Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
35292 views
1
//===--- Marshallers.cpp ----------------------------------------*- 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
#include "Marshallers.h"
10
#include "llvm/ADT/ArrayRef.h"
11
#include "llvm/ADT/StringRef.h"
12
#include "llvm/Support/Regex.h"
13
#include <optional>
14
#include <string>
15
16
static std::optional<std::string>
17
getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed,
18
llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) {
19
if (MaxEditDistance != ~0U)
20
++MaxEditDistance;
21
llvm::StringRef Res;
22
for (const llvm::StringRef &Item : Allowed) {
23
if (Item.equals_insensitive(Search)) {
24
assert(Item != Search && "This should be handled earlier on.");
25
MaxEditDistance = 1;
26
Res = Item;
27
continue;
28
}
29
unsigned Distance = Item.edit_distance(Search);
30
if (Distance < MaxEditDistance) {
31
MaxEditDistance = Distance;
32
Res = Item;
33
}
34
}
35
if (!Res.empty())
36
return Res.str();
37
if (!DropPrefix.empty()) {
38
--MaxEditDistance; // Treat dropping the prefix as 1 edit
39
for (const llvm::StringRef &Item : Allowed) {
40
auto NoPrefix = Item;
41
if (!NoPrefix.consume_front(DropPrefix))
42
continue;
43
if (NoPrefix.equals_insensitive(Search)) {
44
if (NoPrefix == Search)
45
return Item.str();
46
MaxEditDistance = 1;
47
Res = Item;
48
continue;
49
}
50
unsigned Distance = NoPrefix.edit_distance(Search);
51
if (Distance < MaxEditDistance) {
52
MaxEditDistance = Distance;
53
Res = Item;
54
}
55
}
56
if (!Res.empty())
57
return Res.str();
58
}
59
return std::nullopt;
60
}
61
62
std::optional<std::string>
63
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
64
clang::attr::Kind>::getBestGuess(const VariantValue &Value) {
65
static constexpr llvm::StringRef Allowed[] = {
66
#define ATTR(X) "attr::" #X,
67
#include "clang/Basic/AttrList.inc"
68
};
69
if (Value.isString())
70
return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "attr::");
71
return std::nullopt;
72
}
73
74
std::optional<std::string>
75
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
76
clang::CastKind>::getBestGuess(const VariantValue &Value) {
77
static constexpr llvm::StringRef Allowed[] = {
78
#define CAST_OPERATION(Name) "CK_" #Name,
79
#include "clang/AST/OperationKinds.def"
80
};
81
if (Value.isString())
82
return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "CK_");
83
return std::nullopt;
84
}
85
86
std::optional<std::string>
87
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
88
clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {
89
static constexpr llvm::StringRef Allowed[] = {
90
#define GEN_CLANG_CLAUSE_CLASS
91
#define CLAUSE_CLASS(Enum, Str, Class) #Enum,
92
#include "llvm/Frontend/OpenMP/OMP.inc"
93
};
94
if (Value.isString())
95
return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "OMPC_");
96
return std::nullopt;
97
}
98
99
std::optional<std::string>
100
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
101
clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) {
102
static constexpr llvm::StringRef Allowed[] = {
103
#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
104
#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
105
#include "clang/Basic/TokenKinds.def"
106
};
107
if (Value.isString())
108
return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "UETT_");
109
return std::nullopt;
110
}
111
112
static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>
113
RegexMap[] = {
114
{"NoFlags", llvm::Regex::RegexFlags::NoFlags},
115
{"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},
116
{"Newline", llvm::Regex::RegexFlags::Newline},
117
{"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},
118
};
119
120
static std::optional<llvm::Regex::RegexFlags>
121
getRegexFlag(llvm::StringRef Flag) {
122
for (const auto &StringFlag : RegexMap) {
123
if (Flag == StringFlag.first)
124
return StringFlag.second;
125
}
126
return std::nullopt;
127
}
128
129
static std::optional<llvm::StringRef> getCloseRegexMatch(llvm::StringRef Flag) {
130
for (const auto &StringFlag : RegexMap) {
131
if (Flag.edit_distance(StringFlag.first) < 3)
132
return StringFlag.first;
133
}
134
return std::nullopt;
135
}
136
137
std::optional<llvm::Regex::RegexFlags>
138
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
139
llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {
140
std::optional<llvm::Regex::RegexFlags> Flag;
141
SmallVector<StringRef, 4> Split;
142
Flags.split(Split, '|', -1, false);
143
for (StringRef OrFlag : Split) {
144
if (std::optional<llvm::Regex::RegexFlags> NextFlag =
145
getRegexFlag(OrFlag.trim()))
146
Flag = Flag.value_or(llvm::Regex::NoFlags) | *NextFlag;
147
else
148
return std::nullopt;
149
}
150
return Flag;
151
}
152
153
std::optional<std::string>
154
clang::ast_matchers::dynamic::internal::ArgTypeTraits<
155
llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {
156
if (!Value.isString())
157
return std::nullopt;
158
SmallVector<StringRef, 4> Split;
159
llvm::StringRef(Value.getString()).split(Split, '|', -1, false);
160
for (llvm::StringRef &Flag : Split) {
161
if (std::optional<llvm::StringRef> BestGuess =
162
getCloseRegexMatch(Flag.trim()))
163
Flag = *BestGuess;
164
else
165
return std::nullopt;
166
}
167
if (Split.empty())
168
return std::nullopt;
169
return llvm::join(Split, " | ");
170
}
171
172