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