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 
22 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 
40 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
58 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
59                                              bool &IsExactMatch) const {
60   IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
61   return Matcher.canConvertTo(NodeKind);
62 }
63 
64 DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
65     const DynTypedMatcher &Matcher) const {
66   return Matcher.dynCastTo(NodeKind);
67 }
68 
69 llvm::Optional<DynTypedMatcher>
70 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 
88 VariantMatcher::Payload::~Payload() {}
89 
90 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
91 public:
92   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
93 
94   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
95     return Matcher;
96   }
97 
98   std::string getTypeAsString() const override {
99     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
100         .str();
101   }
102 
103   llvm::Optional<DynTypedMatcher>
104   getTypedMatcher(const MatcherOps &Ops) const override {
105     bool Ignore;
106     if (Ops.canConstructFrom(Matcher, Ignore))
107       return Matcher;
108     return llvm::None;
109   }
110 
111   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:
122   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
123       : Matchers(std::move(MatchersIn)) {}
124 
125   ~PolymorphicPayload() override {}
126 
127   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
128     if (Matchers.size() != 1)
129       return llvm::Optional<DynTypedMatcher>();
130     return Matchers[0];
131   }
132 
133   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>
144   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 
168   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:
188   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
189                     std::vector<VariantMatcher> Args)
190       : Op(Op), Args(std::move(Args)) {}
191 
192   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
193     return llvm::Optional<DynTypedMatcher>();
194   }
195 
196   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>
207   getTypedMatcher(const MatcherOps &Ops) const override {
208     return Ops.constructVariadicOperator(Op, Args);
209   }
210 
211   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 
224 VariantMatcher::VariantMatcher() {}
225 
226 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
227   return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
228 }
229 
230 VariantMatcher
231 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
232   return VariantMatcher(
233       std::make_shared<PolymorphicPayload>(std::move(Matchers)));
234 }
235 
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 
243 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
244   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
245 }
246 
247 void VariantMatcher::reset() { Value.reset(); }
248 
249 std::string VariantMatcher::getTypeAsString() const {
250   if (Value) return Value->getTypeAsString();
251   return "<Nothing>";
252 }
253 
254 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
255   *this = Other;
256 }
257 
258 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
259   setBoolean(Boolean);
260 }
261 
262 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
263   setDouble(Double);
264 }
265 
266 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
267   setUnsigned(Unsigned);
268 }
269 
270 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
271   setString(String);
272 }
273 
274 VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
275   setNodeKind(NodeKind);
276 }
277 
278 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
279   setMatcher(Matcher);
280 }
281 
282 VariantValue::~VariantValue() { reset(); }
283 
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 
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 
334 bool VariantValue::isBoolean() const {
335   return Type == VT_Boolean;
336 }
337 
338 bool VariantValue::getBoolean() const {
339   assert(isBoolean());
340   return Value.Boolean;
341 }
342 
343 void VariantValue::setBoolean(bool NewValue) {
344   reset();
345   Type = VT_Boolean;
346   Value.Boolean = NewValue;
347 }
348 
349 bool VariantValue::isDouble() const {
350   return Type == VT_Double;
351 }
352 
353 double VariantValue::getDouble() const {
354   assert(isDouble());
355   return Value.Double;
356 }
357 
358 void VariantValue::setDouble(double NewValue) {
359   reset();
360   Type = VT_Double;
361   Value.Double = NewValue;
362 }
363 
364 bool VariantValue::isUnsigned() const {
365   return Type == VT_Unsigned;
366 }
367 
368 unsigned VariantValue::getUnsigned() const {
369   assert(isUnsigned());
370   return Value.Unsigned;
371 }
372 
373 void VariantValue::setUnsigned(unsigned NewValue) {
374   reset();
375   Type = VT_Unsigned;
376   Value.Unsigned = NewValue;
377 }
378 
379 bool VariantValue::isString() const {
380   return Type == VT_String;
381 }
382 
383 const std::string &VariantValue::getString() const {
384   assert(isString());
385   return *Value.String;
386 }
387 
388 void VariantValue::setString(StringRef NewValue) {
389   reset();
390   Type = VT_String;
391   Value.String = new std::string(NewValue);
392 }
393 
394 bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
395 
396 const ASTNodeKind &VariantValue::getNodeKind() const {
397   assert(isNodeKind());
398   return *Value.NodeKind;
399 }
400 
401 void VariantValue::setNodeKind(ASTNodeKind NewValue) {
402   reset();
403   Type = VT_NodeKind;
404   Value.NodeKind = new ASTNodeKind(NewValue);
405 }
406 
407 bool VariantValue::isMatcher() const {
408   return Type == VT_Matcher;
409 }
410 
411 const VariantMatcher &VariantValue::getMatcher() const {
412   assert(isMatcher());
413   return *Value.Matcher;
414 }
415 
416 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
417   reset();
418   Type = VT_Matcher;
419   Value.Matcher = new VariantMatcher(NewValue);
420 }
421 
422 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 
461 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 
476 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