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