• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Polymorphic value type.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/STLExtras.h"
18 
19 namespace clang {
20 namespace ast_matchers {
21 namespace dynamic {
22 
asString() const23 std::string ArgKind::asString() const {
24   switch (getArgKind()) {
25   case AK_Matcher:
26     return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
27   case AK_Unsigned:
28     return "unsigned";
29   case AK_String:
30     return "string";
31   }
32   llvm_unreachable("unhandled ArgKind");
33 }
34 
isConvertibleTo(ArgKind To,unsigned * Specificity) const35 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
36   if (K != To.K)
37     return false;
38   if (K != AK_Matcher) {
39     if (Specificity)
40       *Specificity = 1;
41     return true;
42   }
43   unsigned Distance;
44   if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
45     return false;
46 
47   if (Specificity)
48     *Specificity = 100 - Distance;
49   return true;
50 }
51 
52 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const53 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54                                              bool &IsExactMatch) const {
55   IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56   return Matcher.canConvertTo(NodeKind);
57 }
58 
59 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const60 VariantMatcher::MatcherOps::constructVariadicOperator(
61     DynTypedMatcher::VariadicOperator Op,
62     ArrayRef<VariantMatcher> InnerMatchers) const {
63   std::vector<DynTypedMatcher> DynMatchers;
64   for (const auto &InnerMatcher : InnerMatchers) {
65     // Abort if any of the inner matchers can't be converted to
66     // Matcher<T>.
67     if (!InnerMatcher.Value)
68       return llvm::None;
69     llvm::Optional<DynTypedMatcher> Inner =
70         InnerMatcher.Value->getTypedMatcher(*this);
71     if (!Inner)
72       return llvm::None;
73     DynMatchers.push_back(*Inner);
74   }
75   return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
76 }
77 
~Payload()78 VariantMatcher::Payload::~Payload() {}
79 
80 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81 public:
SinglePayload(const DynTypedMatcher & Matcher)82   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
83 
getSingleMatcher() const84   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
85     return Matcher;
86   }
87 
getTypeAsString() const88   std::string getTypeAsString() const override {
89     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
90         .str();
91   }
92 
93   llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const94   getTypedMatcher(const MatcherOps &Ops) const override {
95     bool Ignore;
96     if (Ops.canConstructFrom(Matcher, Ignore))
97       return Matcher;
98     return llvm::None;
99   }
100 
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const101   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
102                        unsigned *Specificity) const override {
103     return ArgKind(Matcher.getSupportedKind())
104         .isConvertibleTo(Kind, Specificity);
105   }
106 
107 private:
108   const DynTypedMatcher Matcher;
109 };
110 
111 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)113   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114       : Matchers(std::move(MatchersIn)) {}
115 
~PolymorphicPayload()116   ~PolymorphicPayload() override {}
117 
getSingleMatcher() const118   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
119     if (Matchers.size() != 1)
120       return llvm::Optional<DynTypedMatcher>();
121     return Matchers[0];
122   }
123 
getTypeAsString() const124   std::string getTypeAsString() const override {
125     std::string Inner;
126     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127       if (i != 0)
128         Inner += "|";
129       Inner += Matchers[i].getSupportedKind().asStringRef();
130     }
131     return (Twine("Matcher<") + Inner + ">").str();
132   }
133 
134   llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const135   getTypedMatcher(const MatcherOps &Ops) const override {
136     bool FoundIsExact = false;
137     const DynTypedMatcher *Found = nullptr;
138     int NumFound = 0;
139     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
140       bool IsExactMatch;
141       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
142         if (Found) {
143           if (FoundIsExact) {
144             assert(!IsExactMatch && "We should not have two exact matches.");
145             continue;
146           }
147         }
148         Found = &Matchers[i];
149         FoundIsExact = IsExactMatch;
150         ++NumFound;
151       }
152     }
153     // We only succeed if we found exactly one, or if we found an exact match.
154     if (Found && (FoundIsExact || NumFound == 1))
155       return *Found;
156     return llvm::None;
157   }
158 
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const159   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
160                        unsigned *Specificity) const override {
161     unsigned MaxSpecificity = 0;
162     for (const DynTypedMatcher &Matcher : Matchers) {
163       unsigned ThisSpecificity;
164       if (ArgKind(Matcher.getSupportedKind())
165               .isConvertibleTo(Kind, &ThisSpecificity)) {
166         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
167       }
168     }
169     if (Specificity)
170       *Specificity = MaxSpecificity;
171     return MaxSpecificity > 0;
172   }
173 
174   const std::vector<DynTypedMatcher> Matchers;
175 };
176 
177 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)179   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
180                     std::vector<VariantMatcher> Args)
181       : Op(Op), Args(std::move(Args)) {}
182 
getSingleMatcher() const183   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
184     return llvm::Optional<DynTypedMatcher>();
185   }
186 
getTypeAsString() const187   std::string getTypeAsString() const override {
188     std::string Inner;
189     for (size_t i = 0, e = Args.size(); i != e; ++i) {
190       if (i != 0)
191         Inner += "&";
192       Inner += Args[i].getTypeAsString();
193     }
194     return Inner;
195   }
196 
197   llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const198   getTypedMatcher(const MatcherOps &Ops) const override {
199     return Ops.constructVariadicOperator(Op, Args);
200   }
201 
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const202   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
203                        unsigned *Specificity) const override {
204     for (const VariantMatcher &Matcher : Args) {
205       if (!Matcher.isConvertibleTo(Kind, Specificity))
206         return false;
207     }
208     return true;
209   }
210 
211 private:
212   const DynTypedMatcher::VariadicOperator Op;
213   const std::vector<VariantMatcher> Args;
214 };
215 
VariantMatcher()216 VariantMatcher::VariantMatcher() {}
217 
SingleMatcher(const DynTypedMatcher & Matcher)218 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
219   return VariantMatcher(new SinglePayload(Matcher));
220 }
221 
222 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224   return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
225 }
226 
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)227 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
228     DynTypedMatcher::VariadicOperator Op,
229     std::vector<VariantMatcher> Args) {
230   return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
231 }
232 
getSingleMatcher() const233 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
234   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
235 }
236 
reset()237 void VariantMatcher::reset() { Value.reset(); }
238 
getTypeAsString() const239 std::string VariantMatcher::getTypeAsString() const {
240   if (Value) return Value->getTypeAsString();
241   return "<Nothing>";
242 }
243 
VariantValue(const VariantValue & Other)244 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245   *this = Other;
246 }
247 
VariantValue(unsigned Unsigned)248 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249   setUnsigned(Unsigned);
250 }
251 
VariantValue(StringRef String)252 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
253   setString(String);
254 }
255 
VariantValue(const VariantMatcher & Matcher)256 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257   setMatcher(Matcher);
258 }
259 
~VariantValue()260 VariantValue::~VariantValue() { reset(); }
261 
operator =(const VariantValue & Other)262 VariantValue &VariantValue::operator=(const VariantValue &Other) {
263   if (this == &Other) return *this;
264   reset();
265   switch (Other.Type) {
266   case VT_Unsigned:
267     setUnsigned(Other.getUnsigned());
268     break;
269   case VT_String:
270     setString(Other.getString());
271     break;
272   case VT_Matcher:
273     setMatcher(Other.getMatcher());
274     break;
275   case VT_Nothing:
276     Type = VT_Nothing;
277     break;
278   }
279   return *this;
280 }
281 
reset()282 void VariantValue::reset() {
283   switch (Type) {
284   case VT_String:
285     delete Value.String;
286     break;
287   case VT_Matcher:
288     delete Value.Matcher;
289     break;
290   // Cases that do nothing.
291   case VT_Unsigned:
292   case VT_Nothing:
293     break;
294   }
295   Type = VT_Nothing;
296 }
297 
isUnsigned() const298 bool VariantValue::isUnsigned() const {
299   return Type == VT_Unsigned;
300 }
301 
getUnsigned() const302 unsigned VariantValue::getUnsigned() const {
303   assert(isUnsigned());
304   return Value.Unsigned;
305 }
306 
setUnsigned(unsigned NewValue)307 void VariantValue::setUnsigned(unsigned NewValue) {
308   reset();
309   Type = VT_Unsigned;
310   Value.Unsigned = NewValue;
311 }
312 
isString() const313 bool VariantValue::isString() const {
314   return Type == VT_String;
315 }
316 
getString() const317 const std::string &VariantValue::getString() const {
318   assert(isString());
319   return *Value.String;
320 }
321 
setString(StringRef NewValue)322 void VariantValue::setString(StringRef NewValue) {
323   reset();
324   Type = VT_String;
325   Value.String = new std::string(NewValue);
326 }
327 
isMatcher() const328 bool VariantValue::isMatcher() const {
329   return Type == VT_Matcher;
330 }
331 
getMatcher() const332 const VariantMatcher &VariantValue::getMatcher() const {
333   assert(isMatcher());
334   return *Value.Matcher;
335 }
336 
setMatcher(const VariantMatcher & NewValue)337 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
338   reset();
339   Type = VT_Matcher;
340   Value.Matcher = new VariantMatcher(NewValue);
341 }
342 
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const343 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344   switch (Kind.getArgKind()) {
345   case ArgKind::AK_Unsigned:
346     if (!isUnsigned())
347       return false;
348     *Specificity = 1;
349     return true;
350 
351   case ArgKind::AK_String:
352     if (!isString())
353       return false;
354     *Specificity = 1;
355     return true;
356 
357   case ArgKind::AK_Matcher:
358     if (!isMatcher())
359       return false;
360     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
361   }
362   llvm_unreachable("Invalid Type");
363 }
364 
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const365 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
366                                    unsigned *Specificity) const {
367   unsigned MaxSpecificity = 0;
368   for (const ArgKind& Kind : Kinds) {
369     unsigned ThisSpecificity;
370     if (!isConvertibleTo(Kind, &ThisSpecificity))
371       continue;
372     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
373   }
374   if (Specificity && MaxSpecificity > 0) {
375     *Specificity = MaxSpecificity;
376   }
377   return MaxSpecificity > 0;
378 }
379 
getTypeAsString() const380 std::string VariantValue::getTypeAsString() const {
381   switch (Type) {
382   case VT_String: return "String";
383   case VT_Matcher: return getMatcher().getTypeAsString();
384   case VT_Unsigned: return "Unsigned";
385   case VT_Nothing: return "Nothing";
386   }
387   llvm_unreachable("Invalid Type");
388 }
389 
390 } // end namespace dynamic
391 } // end namespace ast_matchers
392 } // end namespace clang
393