1 //===--- VariantValue.cpp - Polymorphic value type -*- 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 /// Polymorphic value type.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/STLExtras.h"
17
18 namespace clang {
19 namespace ast_matchers {
20 namespace dynamic {
21
asString() const22 std::string ArgKind::asString() const {
23 switch (getArgKind()) {
24 case AK_Matcher:
25 return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
26 case AK_Boolean:
27 return "boolean";
28 case AK_Double:
29 return "double";
30 case AK_Unsigned:
31 return "unsigned";
32 case AK_String:
33 return "string";
34 }
35 llvm_unreachable("unhandled ArgKind");
36 }
37
isConvertibleTo(ArgKind To,unsigned * Specificity) const38 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
39 if (K != To.K)
40 return false;
41 if (K != AK_Matcher) {
42 if (Specificity)
43 *Specificity = 1;
44 return true;
45 }
46 unsigned Distance;
47 if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
48 return false;
49
50 if (Specificity)
51 *Specificity = 100 - Distance;
52 return true;
53 }
54
55 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const56 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
57 bool &IsExactMatch) const {
58 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
59 return Matcher.canConvertTo(NodeKind);
60 }
61
62 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const63 VariantMatcher::MatcherOps::constructVariadicOperator(
64 DynTypedMatcher::VariadicOperator Op,
65 ArrayRef<VariantMatcher> InnerMatchers) const {
66 std::vector<DynTypedMatcher> DynMatchers;
67 for (const auto &InnerMatcher : InnerMatchers) {
68 // Abort if any of the inner matchers can't be converted to
69 // Matcher<T>.
70 if (!InnerMatcher.Value)
71 return llvm::None;
72 llvm::Optional<DynTypedMatcher> Inner =
73 InnerMatcher.Value->getTypedMatcher(*this);
74 if (!Inner)
75 return llvm::None;
76 DynMatchers.push_back(*Inner);
77 }
78 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
79 }
80
~Payload()81 VariantMatcher::Payload::~Payload() {}
82
83 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
84 public:
SinglePayload(const DynTypedMatcher & Matcher)85 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
86
getSingleMatcher() const87 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
88 return Matcher;
89 }
90
getTypeAsString() const91 std::string getTypeAsString() const override {
92 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
93 .str();
94 }
95
96 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const97 getTypedMatcher(const MatcherOps &Ops) const override {
98 bool Ignore;
99 if (Ops.canConstructFrom(Matcher, Ignore))
100 return Matcher;
101 return llvm::None;
102 }
103
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const104 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
105 unsigned *Specificity) const override {
106 return ArgKind(Matcher.getSupportedKind())
107 .isConvertibleTo(Kind, Specificity);
108 }
109
110 private:
111 const DynTypedMatcher Matcher;
112 };
113
114 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
115 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)116 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
117 : Matchers(std::move(MatchersIn)) {}
118
~PolymorphicPayload()119 ~PolymorphicPayload() override {}
120
getSingleMatcher() const121 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
122 if (Matchers.size() != 1)
123 return llvm::Optional<DynTypedMatcher>();
124 return Matchers[0];
125 }
126
getTypeAsString() const127 std::string getTypeAsString() const override {
128 std::string Inner;
129 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
130 if (i != 0)
131 Inner += "|";
132 Inner += Matchers[i].getSupportedKind().asStringRef();
133 }
134 return (Twine("Matcher<") + Inner + ">").str();
135 }
136
137 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const138 getTypedMatcher(const MatcherOps &Ops) const override {
139 bool FoundIsExact = false;
140 const DynTypedMatcher *Found = nullptr;
141 int NumFound = 0;
142 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
143 bool IsExactMatch;
144 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
145 if (Found) {
146 if (FoundIsExact) {
147 assert(!IsExactMatch && "We should not have two exact matches.");
148 continue;
149 }
150 }
151 Found = &Matchers[i];
152 FoundIsExact = IsExactMatch;
153 ++NumFound;
154 }
155 }
156 // We only succeed if we found exactly one, or if we found an exact match.
157 if (Found && (FoundIsExact || NumFound == 1))
158 return *Found;
159 return llvm::None;
160 }
161
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const162 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
163 unsigned *Specificity) const override {
164 unsigned MaxSpecificity = 0;
165 for (const DynTypedMatcher &Matcher : Matchers) {
166 unsigned ThisSpecificity;
167 if (ArgKind(Matcher.getSupportedKind())
168 .isConvertibleTo(Kind, &ThisSpecificity)) {
169 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
170 }
171 }
172 if (Specificity)
173 *Specificity = MaxSpecificity;
174 return MaxSpecificity > 0;
175 }
176
177 const std::vector<DynTypedMatcher> Matchers;
178 };
179
180 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
181 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)182 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
183 std::vector<VariantMatcher> Args)
184 : Op(Op), Args(std::move(Args)) {}
185
getSingleMatcher() const186 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
187 return llvm::Optional<DynTypedMatcher>();
188 }
189
getTypeAsString() const190 std::string getTypeAsString() const override {
191 std::string Inner;
192 for (size_t i = 0, e = Args.size(); i != e; ++i) {
193 if (i != 0)
194 Inner += "&";
195 Inner += Args[i].getTypeAsString();
196 }
197 return Inner;
198 }
199
200 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const201 getTypedMatcher(const MatcherOps &Ops) const override {
202 return Ops.constructVariadicOperator(Op, Args);
203 }
204
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const205 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
206 unsigned *Specificity) const override {
207 for (const VariantMatcher &Matcher : Args) {
208 if (!Matcher.isConvertibleTo(Kind, Specificity))
209 return false;
210 }
211 return true;
212 }
213
214 private:
215 const DynTypedMatcher::VariadicOperator Op;
216 const std::vector<VariantMatcher> Args;
217 };
218
VariantMatcher()219 VariantMatcher::VariantMatcher() {}
220
SingleMatcher(const DynTypedMatcher & Matcher)221 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
222 return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
223 }
224
225 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)226 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
227 return VariantMatcher(
228 std::make_shared<PolymorphicPayload>(std::move(Matchers)));
229 }
230
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)231 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
232 DynTypedMatcher::VariadicOperator Op,
233 std::vector<VariantMatcher> Args) {
234 return VariantMatcher(
235 std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
236 }
237
getSingleMatcher() const238 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
239 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
240 }
241
reset()242 void VariantMatcher::reset() { Value.reset(); }
243
getTypeAsString() const244 std::string VariantMatcher::getTypeAsString() const {
245 if (Value) return Value->getTypeAsString();
246 return "<Nothing>";
247 }
248
VariantValue(const VariantValue & Other)249 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
250 *this = Other;
251 }
252
VariantValue(bool Boolean)253 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
254 setBoolean(Boolean);
255 }
256
VariantValue(double Double)257 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
258 setDouble(Double);
259 }
260
VariantValue(unsigned Unsigned)261 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
262 setUnsigned(Unsigned);
263 }
264
VariantValue(StringRef String)265 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
266 setString(String);
267 }
268
VariantValue(const VariantMatcher & Matcher)269 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
270 setMatcher(Matcher);
271 }
272
~VariantValue()273 VariantValue::~VariantValue() { reset(); }
274
operator =(const VariantValue & Other)275 VariantValue &VariantValue::operator=(const VariantValue &Other) {
276 if (this == &Other) return *this;
277 reset();
278 switch (Other.Type) {
279 case VT_Boolean:
280 setBoolean(Other.getBoolean());
281 break;
282 case VT_Double:
283 setDouble(Other.getDouble());
284 break;
285 case VT_Unsigned:
286 setUnsigned(Other.getUnsigned());
287 break;
288 case VT_String:
289 setString(Other.getString());
290 break;
291 case VT_Matcher:
292 setMatcher(Other.getMatcher());
293 break;
294 case VT_Nothing:
295 Type = VT_Nothing;
296 break;
297 }
298 return *this;
299 }
300
reset()301 void VariantValue::reset() {
302 switch (Type) {
303 case VT_String:
304 delete Value.String;
305 break;
306 case VT_Matcher:
307 delete Value.Matcher;
308 break;
309 // Cases that do nothing.
310 case VT_Boolean:
311 case VT_Double:
312 case VT_Unsigned:
313 case VT_Nothing:
314 break;
315 }
316 Type = VT_Nothing;
317 }
318
isBoolean() const319 bool VariantValue::isBoolean() const {
320 return Type == VT_Boolean;
321 }
322
getBoolean() const323 bool VariantValue::getBoolean() const {
324 assert(isBoolean());
325 return Value.Boolean;
326 }
327
setBoolean(bool NewValue)328 void VariantValue::setBoolean(bool NewValue) {
329 reset();
330 Type = VT_Boolean;
331 Value.Boolean = NewValue;
332 }
333
isDouble() const334 bool VariantValue::isDouble() const {
335 return Type == VT_Double;
336 }
337
getDouble() const338 double VariantValue::getDouble() const {
339 assert(isDouble());
340 return Value.Double;
341 }
342
setDouble(double NewValue)343 void VariantValue::setDouble(double NewValue) {
344 reset();
345 Type = VT_Double;
346 Value.Double = NewValue;
347 }
348
isUnsigned() const349 bool VariantValue::isUnsigned() const {
350 return Type == VT_Unsigned;
351 }
352
getUnsigned() const353 unsigned VariantValue::getUnsigned() const {
354 assert(isUnsigned());
355 return Value.Unsigned;
356 }
357
setUnsigned(unsigned NewValue)358 void VariantValue::setUnsigned(unsigned NewValue) {
359 reset();
360 Type = VT_Unsigned;
361 Value.Unsigned = NewValue;
362 }
363
isString() const364 bool VariantValue::isString() const {
365 return Type == VT_String;
366 }
367
getString() const368 const std::string &VariantValue::getString() const {
369 assert(isString());
370 return *Value.String;
371 }
372
setString(StringRef NewValue)373 void VariantValue::setString(StringRef NewValue) {
374 reset();
375 Type = VT_String;
376 Value.String = new std::string(NewValue);
377 }
378
isMatcher() const379 bool VariantValue::isMatcher() const {
380 return Type == VT_Matcher;
381 }
382
getMatcher() const383 const VariantMatcher &VariantValue::getMatcher() const {
384 assert(isMatcher());
385 return *Value.Matcher;
386 }
387
setMatcher(const VariantMatcher & NewValue)388 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
389 reset();
390 Type = VT_Matcher;
391 Value.Matcher = new VariantMatcher(NewValue);
392 }
393
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const394 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
395 switch (Kind.getArgKind()) {
396 case ArgKind::AK_Boolean:
397 if (!isBoolean())
398 return false;
399 *Specificity = 1;
400 return true;
401
402 case ArgKind::AK_Double:
403 if (!isDouble())
404 return false;
405 *Specificity = 1;
406 return true;
407
408 case ArgKind::AK_Unsigned:
409 if (!isUnsigned())
410 return false;
411 *Specificity = 1;
412 return true;
413
414 case ArgKind::AK_String:
415 if (!isString())
416 return false;
417 *Specificity = 1;
418 return true;
419
420 case ArgKind::AK_Matcher:
421 if (!isMatcher())
422 return false;
423 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
424 }
425 llvm_unreachable("Invalid Type");
426 }
427
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const428 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
429 unsigned *Specificity) const {
430 unsigned MaxSpecificity = 0;
431 for (const ArgKind& Kind : Kinds) {
432 unsigned ThisSpecificity;
433 if (!isConvertibleTo(Kind, &ThisSpecificity))
434 continue;
435 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
436 }
437 if (Specificity && MaxSpecificity > 0) {
438 *Specificity = MaxSpecificity;
439 }
440 return MaxSpecificity > 0;
441 }
442
getTypeAsString() const443 std::string VariantValue::getTypeAsString() const {
444 switch (Type) {
445 case VT_String: return "String";
446 case VT_Matcher: return getMatcher().getTypeAsString();
447 case VT_Boolean: return "Boolean";
448 case VT_Double: return "Double";
449 case VT_Unsigned: return "Unsigned";
450 case VT_Nothing: return "Nothing";
451 }
452 llvm_unreachable("Invalid Type");
453 }
454
455 } // end namespace dynamic
456 } // end namespace ast_matchers
457 } // end namespace clang
458