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<") + NodeKind.asStringRef() + ">").str();
26 case AK_Node:
27 return NodeKind.asStringRef().str();
28 case AK_Boolean:
29 return "boolean";
30 case AK_Double:
31 return "double";
32 case AK_Unsigned:
33 return "unsigned";
34 case AK_String:
35 return "string";
36 }
37 llvm_unreachable("unhandled ArgKind");
38 }
39
isConvertibleTo(ArgKind To,unsigned * Specificity) const40 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
41 if (K != To.K)
42 return false;
43 if (K != AK_Matcher && K != AK_Node) {
44 if (Specificity)
45 *Specificity = 1;
46 return true;
47 }
48 unsigned Distance;
49 if (!NodeKind.isBaseOf(To.NodeKind, &Distance))
50 return false;
51
52 if (Specificity)
53 *Specificity = 100 - Distance;
54 return true;
55 }
56
57 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const58 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
59 bool &IsExactMatch) const {
60 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
61 return Matcher.canConvertTo(NodeKind);
62 }
63
convertMatcher(const DynTypedMatcher & Matcher) const64 DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
65 const DynTypedMatcher &Matcher) const {
66 return Matcher.dynCastTo(NodeKind);
67 }
68
69 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const70 VariantMatcher::MatcherOps::constructVariadicOperator(
71 DynTypedMatcher::VariadicOperator Op,
72 ArrayRef<VariantMatcher> InnerMatchers) const {
73 std::vector<DynTypedMatcher> DynMatchers;
74 for (const auto &InnerMatcher : InnerMatchers) {
75 // Abort if any of the inner matchers can't be converted to
76 // Matcher<T>.
77 if (!InnerMatcher.Value)
78 return llvm::None;
79 llvm::Optional<DynTypedMatcher> Inner =
80 InnerMatcher.Value->getTypedMatcher(*this);
81 if (!Inner)
82 return llvm::None;
83 DynMatchers.push_back(*Inner);
84 }
85 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
86 }
87
~Payload()88 VariantMatcher::Payload::~Payload() {}
89
90 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
91 public:
SinglePayload(const DynTypedMatcher & Matcher)92 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
93
getSingleMatcher() const94 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
95 return Matcher;
96 }
97
getTypeAsString() const98 std::string getTypeAsString() const override {
99 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
100 .str();
101 }
102
103 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const104 getTypedMatcher(const MatcherOps &Ops) const override {
105 bool Ignore;
106 if (Ops.canConstructFrom(Matcher, Ignore))
107 return Matcher;
108 return llvm::None;
109 }
110
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const111 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
112 return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
113 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);
114 }
115
116 private:
117 const DynTypedMatcher Matcher;
118 };
119
120 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
121 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)122 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
123 : Matchers(std::move(MatchersIn)) {}
124
~PolymorphicPayload()125 ~PolymorphicPayload() override {}
126
getSingleMatcher() const127 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
128 if (Matchers.size() != 1)
129 return llvm::Optional<DynTypedMatcher>();
130 return Matchers[0];
131 }
132
getTypeAsString() const133 std::string getTypeAsString() const override {
134 std::string Inner;
135 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
136 if (i != 0)
137 Inner += "|";
138 Inner += Matchers[i].getSupportedKind().asStringRef();
139 }
140 return (Twine("Matcher<") + Inner + ">").str();
141 }
142
143 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const144 getTypedMatcher(const MatcherOps &Ops) const override {
145 bool FoundIsExact = false;
146 const DynTypedMatcher *Found = nullptr;
147 int NumFound = 0;
148 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
149 bool IsExactMatch;
150 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
151 if (Found) {
152 if (FoundIsExact) {
153 assert(!IsExactMatch && "We should not have two exact matches.");
154 continue;
155 }
156 }
157 Found = &Matchers[i];
158 FoundIsExact = IsExactMatch;
159 ++NumFound;
160 }
161 }
162 // We only succeed if we found exactly one, or if we found an exact match.
163 if (Found && (FoundIsExact || NumFound == 1))
164 return *Found;
165 return llvm::None;
166 }
167
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const168 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
169 unsigned MaxSpecificity = 0;
170 for (const DynTypedMatcher &Matcher : Matchers) {
171 unsigned ThisSpecificity;
172 if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
173 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind),
174 &ThisSpecificity)) {
175 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
176 }
177 }
178 if (Specificity)
179 *Specificity = MaxSpecificity;
180 return MaxSpecificity > 0;
181 }
182
183 const std::vector<DynTypedMatcher> Matchers;
184 };
185
186 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
187 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)188 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
189 std::vector<VariantMatcher> Args)
190 : Op(Op), Args(std::move(Args)) {}
191
getSingleMatcher() const192 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
193 return llvm::Optional<DynTypedMatcher>();
194 }
195
getTypeAsString() const196 std::string getTypeAsString() const override {
197 std::string Inner;
198 for (size_t i = 0, e = Args.size(); i != e; ++i) {
199 if (i != 0)
200 Inner += "&";
201 Inner += Args[i].getTypeAsString();
202 }
203 return Inner;
204 }
205
206 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const207 getTypedMatcher(const MatcherOps &Ops) const override {
208 return Ops.constructVariadicOperator(Op, Args);
209 }
210
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const211 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
212 for (const VariantMatcher &Matcher : Args) {
213 if (!Matcher.isConvertibleTo(Kind, Specificity))
214 return false;
215 }
216 return true;
217 }
218
219 private:
220 const DynTypedMatcher::VariadicOperator Op;
221 const std::vector<VariantMatcher> Args;
222 };
223
VariantMatcher()224 VariantMatcher::VariantMatcher() {}
225
SingleMatcher(const DynTypedMatcher & Matcher)226 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
227 return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
228 }
229
230 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)231 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
232 return VariantMatcher(
233 std::make_shared<PolymorphicPayload>(std::move(Matchers)));
234 }
235
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)236 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
237 DynTypedMatcher::VariadicOperator Op,
238 std::vector<VariantMatcher> Args) {
239 return VariantMatcher(
240 std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
241 }
242
getSingleMatcher() const243 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
244 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
245 }
246
reset()247 void VariantMatcher::reset() { Value.reset(); }
248
getTypeAsString() const249 std::string VariantMatcher::getTypeAsString() const {
250 if (Value) return Value->getTypeAsString();
251 return "<Nothing>";
252 }
253
VariantValue(const VariantValue & Other)254 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
255 *this = Other;
256 }
257
VariantValue(bool Boolean)258 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
259 setBoolean(Boolean);
260 }
261
VariantValue(double Double)262 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
263 setDouble(Double);
264 }
265
VariantValue(unsigned Unsigned)266 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
267 setUnsigned(Unsigned);
268 }
269
VariantValue(StringRef String)270 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
271 setString(String);
272 }
273
VariantValue(ASTNodeKind NodeKind)274 VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
275 setNodeKind(NodeKind);
276 }
277
VariantValue(const VariantMatcher & Matcher)278 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
279 setMatcher(Matcher);
280 }
281
~VariantValue()282 VariantValue::~VariantValue() { reset(); }
283
operator =(const VariantValue & Other)284 VariantValue &VariantValue::operator=(const VariantValue &Other) {
285 if (this == &Other) return *this;
286 reset();
287 switch (Other.Type) {
288 case VT_Boolean:
289 setBoolean(Other.getBoolean());
290 break;
291 case VT_Double:
292 setDouble(Other.getDouble());
293 break;
294 case VT_Unsigned:
295 setUnsigned(Other.getUnsigned());
296 break;
297 case VT_String:
298 setString(Other.getString());
299 break;
300 case VT_NodeKind:
301 setNodeKind(Other.getNodeKind());
302 break;
303 case VT_Matcher:
304 setMatcher(Other.getMatcher());
305 break;
306 case VT_Nothing:
307 Type = VT_Nothing;
308 break;
309 }
310 return *this;
311 }
312
reset()313 void VariantValue::reset() {
314 switch (Type) {
315 case VT_String:
316 delete Value.String;
317 break;
318 case VT_Matcher:
319 delete Value.Matcher;
320 break;
321 case VT_NodeKind:
322 delete Value.NodeKind;
323 break;
324 // Cases that do nothing.
325 case VT_Boolean:
326 case VT_Double:
327 case VT_Unsigned:
328 case VT_Nothing:
329 break;
330 }
331 Type = VT_Nothing;
332 }
333
isBoolean() const334 bool VariantValue::isBoolean() const {
335 return Type == VT_Boolean;
336 }
337
getBoolean() const338 bool VariantValue::getBoolean() const {
339 assert(isBoolean());
340 return Value.Boolean;
341 }
342
setBoolean(bool NewValue)343 void VariantValue::setBoolean(bool NewValue) {
344 reset();
345 Type = VT_Boolean;
346 Value.Boolean = NewValue;
347 }
348
isDouble() const349 bool VariantValue::isDouble() const {
350 return Type == VT_Double;
351 }
352
getDouble() const353 double VariantValue::getDouble() const {
354 assert(isDouble());
355 return Value.Double;
356 }
357
setDouble(double NewValue)358 void VariantValue::setDouble(double NewValue) {
359 reset();
360 Type = VT_Double;
361 Value.Double = NewValue;
362 }
363
isUnsigned() const364 bool VariantValue::isUnsigned() const {
365 return Type == VT_Unsigned;
366 }
367
getUnsigned() const368 unsigned VariantValue::getUnsigned() const {
369 assert(isUnsigned());
370 return Value.Unsigned;
371 }
372
setUnsigned(unsigned NewValue)373 void VariantValue::setUnsigned(unsigned NewValue) {
374 reset();
375 Type = VT_Unsigned;
376 Value.Unsigned = NewValue;
377 }
378
isString() const379 bool VariantValue::isString() const {
380 return Type == VT_String;
381 }
382
getString() const383 const std::string &VariantValue::getString() const {
384 assert(isString());
385 return *Value.String;
386 }
387
setString(StringRef NewValue)388 void VariantValue::setString(StringRef NewValue) {
389 reset();
390 Type = VT_String;
391 Value.String = new std::string(NewValue);
392 }
393
isNodeKind() const394 bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
395
getNodeKind() const396 const ASTNodeKind &VariantValue::getNodeKind() const {
397 assert(isNodeKind());
398 return *Value.NodeKind;
399 }
400
setNodeKind(ASTNodeKind NewValue)401 void VariantValue::setNodeKind(ASTNodeKind NewValue) {
402 reset();
403 Type = VT_NodeKind;
404 Value.NodeKind = new ASTNodeKind(NewValue);
405 }
406
isMatcher() const407 bool VariantValue::isMatcher() const {
408 return Type == VT_Matcher;
409 }
410
getMatcher() const411 const VariantMatcher &VariantValue::getMatcher() const {
412 assert(isMatcher());
413 return *Value.Matcher;
414 }
415
setMatcher(const VariantMatcher & NewValue)416 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
417 reset();
418 Type = VT_Matcher;
419 Value.Matcher = new VariantMatcher(NewValue);
420 }
421
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const422 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
423 switch (Kind.getArgKind()) {
424 case ArgKind::AK_Boolean:
425 if (!isBoolean())
426 return false;
427 *Specificity = 1;
428 return true;
429
430 case ArgKind::AK_Double:
431 if (!isDouble())
432 return false;
433 *Specificity = 1;
434 return true;
435
436 case ArgKind::AK_Unsigned:
437 if (!isUnsigned())
438 return false;
439 *Specificity = 1;
440 return true;
441
442 case ArgKind::AK_String:
443 if (!isString())
444 return false;
445 *Specificity = 1;
446 return true;
447
448 case ArgKind::AK_Node:
449 if (!isNodeKind())
450 return false;
451 return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);
452
453 case ArgKind::AK_Matcher:
454 if (!isMatcher())
455 return false;
456 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
457 }
458 llvm_unreachable("Invalid Type");
459 }
460
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const461 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
462 unsigned *Specificity) const {
463 unsigned MaxSpecificity = 0;
464 for (const ArgKind& Kind : Kinds) {
465 unsigned ThisSpecificity;
466 if (!isConvertibleTo(Kind, &ThisSpecificity))
467 continue;
468 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
469 }
470 if (Specificity && MaxSpecificity > 0) {
471 *Specificity = MaxSpecificity;
472 }
473 return MaxSpecificity > 0;
474 }
475
getTypeAsString() const476 std::string VariantValue::getTypeAsString() const {
477 switch (Type) {
478 case VT_String: return "String";
479 case VT_Matcher: return getMatcher().getTypeAsString();
480 case VT_Boolean: return "Boolean";
481 case VT_Double: return "Double";
482 case VT_Unsigned: return "Unsigned";
483 case VT_NodeKind:
484 return getNodeKind().asStringRef().str();
485 case VT_Nothing: return "Nothing";
486 }
487 llvm_unreachable("Invalid Type");
488 }
489
490 } // end namespace dynamic
491 } // end namespace ast_matchers
492 } // end namespace clang
493