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