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