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 
23 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 
35 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 VariantMatcher::MatcherOps::~MatcherOps() {}
53 VariantMatcher::Payload::~Payload() {}
54 
55 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
56 public:
57   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
58 
59   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
60     return Matcher;
61   }
62 
63   std::string getTypeAsString() const override {
64     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
65         .str();
66   }
67 
68   void makeTypedMatcher(MatcherOps &Ops) const override {
69     bool Ignore;
70     if (Ops.canConstructFrom(Matcher, Ignore))
71       Ops.constructFrom(Matcher);
72   }
73 
74   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
75                        unsigned *Specificity) const override {
76     return ArgKind(Matcher.getSupportedKind())
77         .isConvertibleTo(Kind, Specificity);
78   }
79 
80 private:
81   const DynTypedMatcher Matcher;
82 };
83 
84 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
85 public:
86   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
87       : Matchers(std::move(MatchersIn)) {}
88 
89   ~PolymorphicPayload() override {}
90 
91   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
92     if (Matchers.size() != 1)
93       return llvm::Optional<DynTypedMatcher>();
94     return Matchers[0];
95   }
96 
97   std::string getTypeAsString() const override {
98     std::string Inner;
99     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
100       if (i != 0)
101         Inner += "|";
102       Inner += Matchers[i].getSupportedKind().asStringRef();
103     }
104     return (Twine("Matcher<") + Inner + ">").str();
105   }
106 
107   void makeTypedMatcher(MatcherOps &Ops) const override {
108     bool FoundIsExact = false;
109     const DynTypedMatcher *Found = nullptr;
110     int NumFound = 0;
111     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
112       bool IsExactMatch;
113       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
114         if (Found) {
115           if (FoundIsExact) {
116             assert(!IsExactMatch && "We should not have two exact matches.");
117             continue;
118           }
119         }
120         Found = &Matchers[i];
121         FoundIsExact = IsExactMatch;
122         ++NumFound;
123       }
124     }
125     // We only succeed if we found exactly one, or if we found an exact match.
126     if (Found && (FoundIsExact || NumFound == 1))
127       Ops.constructFrom(*Found);
128   }
129 
130   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
131                        unsigned *Specificity) const override {
132     unsigned MaxSpecificity = 0;
133     for (const DynTypedMatcher &Matcher : Matchers) {
134       unsigned ThisSpecificity;
135       if (ArgKind(Matcher.getSupportedKind())
136               .isConvertibleTo(Kind, &ThisSpecificity)) {
137         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
138       }
139     }
140     if (Specificity)
141       *Specificity = MaxSpecificity;
142     return MaxSpecificity > 0;
143   }
144 
145   const std::vector<DynTypedMatcher> Matchers;
146 };
147 
148 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
149 public:
150   VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
151                     std::vector<VariantMatcher> Args)
152       : Func(Func), Args(std::move(Args)) {}
153 
154   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
155     return llvm::Optional<DynTypedMatcher>();
156   }
157 
158   std::string getTypeAsString() const override {
159     std::string Inner;
160     for (size_t i = 0, e = Args.size(); i != e; ++i) {
161       if (i != 0)
162         Inner += "&";
163       Inner += Args[i].getTypeAsString();
164     }
165     return Inner;
166   }
167 
168   void makeTypedMatcher(MatcherOps &Ops) const override {
169     Ops.constructVariadicOperator(Func, Args);
170   }
171 
172   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
173                        unsigned *Specificity) const override {
174     for (const VariantMatcher &Matcher : Args) {
175       if (!Matcher.isConvertibleTo(Kind, Specificity))
176         return false;
177     }
178     return true;
179   }
180 
181 private:
182   const ast_matchers::internal::VariadicOperatorFunction Func;
183   const std::vector<VariantMatcher> Args;
184 };
185 
186 VariantMatcher::VariantMatcher() {}
187 
188 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
189   return VariantMatcher(new SinglePayload(Matcher));
190 }
191 
192 VariantMatcher
193 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
194   return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
195 }
196 
197 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
198     ast_matchers::internal::VariadicOperatorFunction Func,
199     std::vector<VariantMatcher> Args) {
200   return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
201 }
202 
203 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
204   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
205 }
206 
207 void VariantMatcher::reset() { Value.reset(); }
208 
209 std::string VariantMatcher::getTypeAsString() const {
210   if (Value) return Value->getTypeAsString();
211   return "<Nothing>";
212 }
213 
214 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
215   *this = Other;
216 }
217 
218 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
219   setUnsigned(Unsigned);
220 }
221 
222 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
223   setString(String);
224 }
225 
226 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
227   setMatcher(Matcher);
228 }
229 
230 VariantValue::~VariantValue() { reset(); }
231 
232 VariantValue &VariantValue::operator=(const VariantValue &Other) {
233   if (this == &Other) return *this;
234   reset();
235   switch (Other.Type) {
236   case VT_Unsigned:
237     setUnsigned(Other.getUnsigned());
238     break;
239   case VT_String:
240     setString(Other.getString());
241     break;
242   case VT_Matcher:
243     setMatcher(Other.getMatcher());
244     break;
245   case VT_Nothing:
246     Type = VT_Nothing;
247     break;
248   }
249   return *this;
250 }
251 
252 void VariantValue::reset() {
253   switch (Type) {
254   case VT_String:
255     delete Value.String;
256     break;
257   case VT_Matcher:
258     delete Value.Matcher;
259     break;
260   // Cases that do nothing.
261   case VT_Unsigned:
262   case VT_Nothing:
263     break;
264   }
265   Type = VT_Nothing;
266 }
267 
268 bool VariantValue::isUnsigned() const {
269   return Type == VT_Unsigned;
270 }
271 
272 unsigned VariantValue::getUnsigned() const {
273   assert(isUnsigned());
274   return Value.Unsigned;
275 }
276 
277 void VariantValue::setUnsigned(unsigned NewValue) {
278   reset();
279   Type = VT_Unsigned;
280   Value.Unsigned = NewValue;
281 }
282 
283 bool VariantValue::isString() const {
284   return Type == VT_String;
285 }
286 
287 const std::string &VariantValue::getString() const {
288   assert(isString());
289   return *Value.String;
290 }
291 
292 void VariantValue::setString(const std::string &NewValue) {
293   reset();
294   Type = VT_String;
295   Value.String = new std::string(NewValue);
296 }
297 
298 bool VariantValue::isMatcher() const {
299   return Type == VT_Matcher;
300 }
301 
302 const VariantMatcher &VariantValue::getMatcher() const {
303   assert(isMatcher());
304   return *Value.Matcher;
305 }
306 
307 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
308   reset();
309   Type = VT_Matcher;
310   Value.Matcher = new VariantMatcher(NewValue);
311 }
312 
313 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
314   switch (Kind.getArgKind()) {
315   case ArgKind::AK_Unsigned:
316     if (!isUnsigned())
317       return false;
318     *Specificity = 1;
319     return true;
320 
321   case ArgKind::AK_String:
322     if (!isString())
323       return false;
324     *Specificity = 1;
325     return true;
326 
327   case ArgKind::AK_Matcher:
328     if (!isMatcher())
329       return false;
330     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
331   }
332   llvm_unreachable("Invalid Type");
333 }
334 
335 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
336                                    unsigned *Specificity) const {
337   unsigned MaxSpecificity = 0;
338   for (const ArgKind& Kind : Kinds) {
339     unsigned ThisSpecificity;
340     if (!isConvertibleTo(Kind, &ThisSpecificity))
341       continue;
342     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
343   }
344   if (Specificity && MaxSpecificity > 0) {
345     *Specificity = MaxSpecificity;
346   }
347   return MaxSpecificity > 0;
348 }
349 
350 std::string VariantValue::getTypeAsString() const {
351   switch (Type) {
352   case VT_String: return "String";
353   case VT_Matcher: return getMatcher().getTypeAsString();
354   case VT_Unsigned: return "Unsigned";
355   case VT_Nothing: return "Nothing";
356   }
357   llvm_unreachable("Invalid Type");
358 }
359 
360 } // end namespace dynamic
361 } // end namespace ast_matchers
362 } // end namespace clang
363