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
convertMatcher(const DynTypedMatcher & Matcher) const62 DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
63 const DynTypedMatcher &Matcher) const {
64 return Matcher.dynCastTo(NodeKind);
65 }
66
67 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const68 VariantMatcher::MatcherOps::constructVariadicOperator(
69 DynTypedMatcher::VariadicOperator Op,
70 ArrayRef<VariantMatcher> InnerMatchers) const {
71 std::vector<DynTypedMatcher> DynMatchers;
72 for (const auto &InnerMatcher : InnerMatchers) {
73 // Abort if any of the inner matchers can't be converted to
74 // Matcher<T>.
75 if (!InnerMatcher.Value)
76 return llvm::None;
77 llvm::Optional<DynTypedMatcher> Inner =
78 InnerMatcher.Value->getTypedMatcher(*this);
79 if (!Inner)
80 return llvm::None;
81 DynMatchers.push_back(*Inner);
82 }
83 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
84 }
85
~Payload()86 VariantMatcher::Payload::~Payload() {}
87
88 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
89 public:
SinglePayload(const DynTypedMatcher & Matcher)90 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
91
getSingleMatcher() const92 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
93 return Matcher;
94 }
95
getTypeAsString() const96 std::string getTypeAsString() const override {
97 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
98 .str();
99 }
100
101 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const102 getTypedMatcher(const MatcherOps &Ops) const override {
103 bool Ignore;
104 if (Ops.canConstructFrom(Matcher, Ignore))
105 return Matcher;
106 return llvm::None;
107 }
108
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const109 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
110 return ArgKind(Matcher.getSupportedKind())
111 .isConvertibleTo(Kind, Specificity);
112 }
113
114 private:
115 const DynTypedMatcher Matcher;
116 };
117
118 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
119 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)120 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
121 : Matchers(std::move(MatchersIn)) {}
122
~PolymorphicPayload()123 ~PolymorphicPayload() override {}
124
getSingleMatcher() const125 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
126 if (Matchers.size() != 1)
127 return llvm::Optional<DynTypedMatcher>();
128 return Matchers[0];
129 }
130
getTypeAsString() const131 std::string getTypeAsString() const override {
132 std::string Inner;
133 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
134 if (i != 0)
135 Inner += "|";
136 Inner += Matchers[i].getSupportedKind().asStringRef();
137 }
138 return (Twine("Matcher<") + Inner + ">").str();
139 }
140
141 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const142 getTypedMatcher(const MatcherOps &Ops) const override {
143 bool FoundIsExact = false;
144 const DynTypedMatcher *Found = nullptr;
145 int NumFound = 0;
146 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
147 bool IsExactMatch;
148 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
149 if (Found) {
150 if (FoundIsExact) {
151 assert(!IsExactMatch && "We should not have two exact matches.");
152 continue;
153 }
154 }
155 Found = &Matchers[i];
156 FoundIsExact = IsExactMatch;
157 ++NumFound;
158 }
159 }
160 // We only succeed if we found exactly one, or if we found an exact match.
161 if (Found && (FoundIsExact || NumFound == 1))
162 return *Found;
163 return llvm::None;
164 }
165
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const166 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
167 unsigned MaxSpecificity = 0;
168 for (const DynTypedMatcher &Matcher : Matchers) {
169 unsigned ThisSpecificity;
170 if (ArgKind(Matcher.getSupportedKind())
171 .isConvertibleTo(Kind, &ThisSpecificity)) {
172 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
173 }
174 }
175 if (Specificity)
176 *Specificity = MaxSpecificity;
177 return MaxSpecificity > 0;
178 }
179
180 const std::vector<DynTypedMatcher> Matchers;
181 };
182
183 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
184 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)185 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
186 std::vector<VariantMatcher> Args)
187 : Op(Op), Args(std::move(Args)) {}
188
getSingleMatcher() const189 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
190 return llvm::Optional<DynTypedMatcher>();
191 }
192
getTypeAsString() const193 std::string getTypeAsString() const override {
194 std::string Inner;
195 for (size_t i = 0, e = Args.size(); i != e; ++i) {
196 if (i != 0)
197 Inner += "&";
198 Inner += Args[i].getTypeAsString();
199 }
200 return Inner;
201 }
202
203 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const204 getTypedMatcher(const MatcherOps &Ops) const override {
205 return Ops.constructVariadicOperator(Op, Args);
206 }
207
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const208 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
209 for (const VariantMatcher &Matcher : Args) {
210 if (!Matcher.isConvertibleTo(Kind, Specificity))
211 return false;
212 }
213 return true;
214 }
215
216 private:
217 const DynTypedMatcher::VariadicOperator Op;
218 const std::vector<VariantMatcher> Args;
219 };
220
VariantMatcher()221 VariantMatcher::VariantMatcher() {}
222
SingleMatcher(const DynTypedMatcher & Matcher)223 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
224 return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
225 }
226
227 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)228 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
229 return VariantMatcher(
230 std::make_shared<PolymorphicPayload>(std::move(Matchers)));
231 }
232
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)233 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
234 DynTypedMatcher::VariadicOperator Op,
235 std::vector<VariantMatcher> Args) {
236 return VariantMatcher(
237 std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
238 }
239
getSingleMatcher() const240 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
241 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
242 }
243
reset()244 void VariantMatcher::reset() { Value.reset(); }
245
getTypeAsString() const246 std::string VariantMatcher::getTypeAsString() const {
247 if (Value) return Value->getTypeAsString();
248 return "<Nothing>";
249 }
250
VariantValue(const VariantValue & Other)251 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
252 *this = Other;
253 }
254
VariantValue(bool Boolean)255 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
256 setBoolean(Boolean);
257 }
258
VariantValue(double Double)259 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
260 setDouble(Double);
261 }
262
VariantValue(unsigned Unsigned)263 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
264 setUnsigned(Unsigned);
265 }
266
VariantValue(StringRef String)267 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
268 setString(String);
269 }
270
VariantValue(ASTNodeKind NodeKind)271 VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
272 setNodeKind(NodeKind);
273 }
274
VariantValue(const VariantMatcher & Matcher)275 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
276 setMatcher(Matcher);
277 }
278
~VariantValue()279 VariantValue::~VariantValue() { reset(); }
280
operator =(const VariantValue & Other)281 VariantValue &VariantValue::operator=(const VariantValue &Other) {
282 if (this == &Other) return *this;
283 reset();
284 switch (Other.Type) {
285 case VT_Boolean:
286 setBoolean(Other.getBoolean());
287 break;
288 case VT_Double:
289 setDouble(Other.getDouble());
290 break;
291 case VT_Unsigned:
292 setUnsigned(Other.getUnsigned());
293 break;
294 case VT_String:
295 setString(Other.getString());
296 break;
297 case VT_NodeKind:
298 setNodeKind(Other.getNodeKind());
299 break;
300 case VT_Matcher:
301 setMatcher(Other.getMatcher());
302 break;
303 case VT_Nothing:
304 Type = VT_Nothing;
305 break;
306 }
307 return *this;
308 }
309
reset()310 void VariantValue::reset() {
311 switch (Type) {
312 case VT_String:
313 delete Value.String;
314 break;
315 case VT_Matcher:
316 delete Value.Matcher;
317 break;
318 case VT_NodeKind:
319 delete Value.NodeKind;
320 break;
321 // Cases that do nothing.
322 case VT_Boolean:
323 case VT_Double:
324 case VT_Unsigned:
325 case VT_Nothing:
326 break;
327 }
328 Type = VT_Nothing;
329 }
330
isBoolean() const331 bool VariantValue::isBoolean() const {
332 return Type == VT_Boolean;
333 }
334
getBoolean() const335 bool VariantValue::getBoolean() const {
336 assert(isBoolean());
337 return Value.Boolean;
338 }
339
setBoolean(bool NewValue)340 void VariantValue::setBoolean(bool NewValue) {
341 reset();
342 Type = VT_Boolean;
343 Value.Boolean = NewValue;
344 }
345
isDouble() const346 bool VariantValue::isDouble() const {
347 return Type == VT_Double;
348 }
349
getDouble() const350 double VariantValue::getDouble() const {
351 assert(isDouble());
352 return Value.Double;
353 }
354
setDouble(double NewValue)355 void VariantValue::setDouble(double NewValue) {
356 reset();
357 Type = VT_Double;
358 Value.Double = NewValue;
359 }
360
isUnsigned() const361 bool VariantValue::isUnsigned() const {
362 return Type == VT_Unsigned;
363 }
364
getUnsigned() const365 unsigned VariantValue::getUnsigned() const {
366 assert(isUnsigned());
367 return Value.Unsigned;
368 }
369
setUnsigned(unsigned NewValue)370 void VariantValue::setUnsigned(unsigned NewValue) {
371 reset();
372 Type = VT_Unsigned;
373 Value.Unsigned = NewValue;
374 }
375
isString() const376 bool VariantValue::isString() const {
377 return Type == VT_String;
378 }
379
getString() const380 const std::string &VariantValue::getString() const {
381 assert(isString());
382 return *Value.String;
383 }
384
setString(StringRef NewValue)385 void VariantValue::setString(StringRef NewValue) {
386 reset();
387 Type = VT_String;
388 Value.String = new std::string(NewValue);
389 }
390
isNodeKind() const391 bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
392
getNodeKind() const393 const ASTNodeKind &VariantValue::getNodeKind() const {
394 assert(isNodeKind());
395 return *Value.NodeKind;
396 }
397
setNodeKind(ASTNodeKind NewValue)398 void VariantValue::setNodeKind(ASTNodeKind NewValue) {
399 reset();
400 Type = VT_NodeKind;
401 Value.NodeKind = new ASTNodeKind(NewValue);
402 }
403
isMatcher() const404 bool VariantValue::isMatcher() const {
405 return Type == VT_Matcher;
406 }
407
getMatcher() const408 const VariantMatcher &VariantValue::getMatcher() const {
409 assert(isMatcher());
410 return *Value.Matcher;
411 }
412
setMatcher(const VariantMatcher & NewValue)413 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
414 reset();
415 Type = VT_Matcher;
416 Value.Matcher = new VariantMatcher(NewValue);
417 }
418
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const419 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
420 switch (Kind.getArgKind()) {
421 case ArgKind::AK_Boolean:
422 if (!isBoolean())
423 return false;
424 *Specificity = 1;
425 return true;
426
427 case ArgKind::AK_Double:
428 if (!isDouble())
429 return false;
430 *Specificity = 1;
431 return true;
432
433 case ArgKind::AK_Unsigned:
434 if (!isUnsigned())
435 return false;
436 *Specificity = 1;
437 return true;
438
439 case ArgKind::AK_String:
440 if (!isString())
441 return false;
442 *Specificity = 1;
443 return true;
444
445 case ArgKind::AK_Matcher:
446 if (!isMatcher())
447 return false;
448 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
449 }
450 llvm_unreachable("Invalid Type");
451 }
452
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const453 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
454 unsigned *Specificity) const {
455 unsigned MaxSpecificity = 0;
456 for (const ArgKind& Kind : Kinds) {
457 unsigned ThisSpecificity;
458 if (!isConvertibleTo(Kind, &ThisSpecificity))
459 continue;
460 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
461 }
462 if (Specificity && MaxSpecificity > 0) {
463 *Specificity = MaxSpecificity;
464 }
465 return MaxSpecificity > 0;
466 }
467
getTypeAsString() const468 std::string VariantValue::getTypeAsString() const {
469 switch (Type) {
470 case VT_String: return "String";
471 case VT_Matcher: return getMatcher().getTypeAsString();
472 case VT_Boolean: return "Boolean";
473 case VT_Double: return "Double";
474 case VT_Unsigned: return "Unsigned";
475 case VT_NodeKind:
476 return getNodeKind().asStringRef().str();
477 case VT_Nothing: return "Nothing";
478 }
479 llvm_unreachable("Invalid Type");
480 }
481
482 } // end namespace dynamic
483 } // end namespace ast_matchers
484 } // end namespace clang
485