xref: /freebsd/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 #include <optional>
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<") + NodeKind.asStringRef() + ">").str();
27   case AK_Node:
28     return NodeKind.asStringRef().str();
29   case AK_Boolean:
30     return "boolean";
31   case AK_Double:
32     return "double";
33   case AK_Unsigned:
34     return "unsigned";
35   case AK_String:
36     return "string";
37   }
38   llvm_unreachable("unhandled ArgKind");
39 }
40 
isConvertibleTo(ArgKind To,unsigned * Specificity) const41 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
42   if (K != To.K)
43     return false;
44   if (K != AK_Matcher && K != AK_Node) {
45     if (Specificity)
46       *Specificity = 1;
47     return true;
48   }
49   unsigned Distance;
50   if (!NodeKind.isBaseOf(To.NodeKind, &Distance))
51     return false;
52 
53   if (Specificity)
54     *Specificity = 100 - Distance;
55   return true;
56 }
57 
58 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const59 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
60                                              bool &IsExactMatch) const {
61   IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
62   return Matcher.canConvertTo(NodeKind);
63 }
64 
convertMatcher(const DynTypedMatcher & Matcher) const65 DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
66     const DynTypedMatcher &Matcher) const {
67   return Matcher.dynCastTo(NodeKind);
68 }
69 
70 std::optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const71 VariantMatcher::MatcherOps::constructVariadicOperator(
72     DynTypedMatcher::VariadicOperator Op,
73     ArrayRef<VariantMatcher> InnerMatchers) const {
74   std::vector<DynTypedMatcher> DynMatchers;
75   for (const auto &InnerMatcher : InnerMatchers) {
76     // Abort if any of the inner matchers can't be converted to
77     // Matcher<T>.
78     if (!InnerMatcher.Value)
79       return std::nullopt;
80     std::optional<DynTypedMatcher> Inner =
81         InnerMatcher.Value->getTypedMatcher(*this);
82     if (!Inner)
83       return std::nullopt;
84     DynMatchers.push_back(*Inner);
85   }
86   return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
87 }
88 
~Payload()89 VariantMatcher::Payload::~Payload() {}
90 
91 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
92 public:
SinglePayload(const DynTypedMatcher & Matcher)93   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
94 
getSingleMatcher() const95   std::optional<DynTypedMatcher> getSingleMatcher() const override {
96     return Matcher;
97   }
98 
getTypeAsString() const99   std::string getTypeAsString() const override {
100     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
101         .str();
102   }
103 
104   std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const105   getTypedMatcher(const MatcherOps &Ops) const override {
106     bool Ignore;
107     if (Ops.canConstructFrom(Matcher, Ignore))
108       return Matcher;
109     return std::nullopt;
110   }
111 
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const112   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
113     return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
114         .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);
115   }
116 
117 private:
118   const DynTypedMatcher Matcher;
119 };
120 
121 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
122 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)123   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
124       : Matchers(std::move(MatchersIn)) {}
125 
~PolymorphicPayload()126   ~PolymorphicPayload() override {}
127 
getSingleMatcher() const128   std::optional<DynTypedMatcher> getSingleMatcher() const override {
129     if (Matchers.size() != 1)
130       return std::nullopt;
131     return Matchers[0];
132   }
133 
getTypeAsString() const134   std::string getTypeAsString() const override {
135     std::string Inner;
136     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
137       if (i != 0)
138         Inner += "|";
139       Inner += Matchers[i].getSupportedKind().asStringRef();
140     }
141     return (Twine("Matcher<") + Inner + ">").str();
142   }
143 
144   std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const145   getTypedMatcher(const MatcherOps &Ops) const override {
146     bool FoundIsExact = false;
147     const DynTypedMatcher *Found = nullptr;
148     int NumFound = 0;
149     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
150       bool IsExactMatch;
151       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
152         if (Found) {
153           if (FoundIsExact) {
154             assert(!IsExactMatch && "We should not have two exact matches.");
155             continue;
156           }
157         }
158         Found = &Matchers[i];
159         FoundIsExact = IsExactMatch;
160         ++NumFound;
161       }
162     }
163     // We only succeed if we found exactly one, or if we found an exact match.
164     if (Found && (FoundIsExact || NumFound == 1))
165       return *Found;
166     return std::nullopt;
167   }
168 
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const169   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
170     unsigned MaxSpecificity = 0;
171     for (const DynTypedMatcher &Matcher : Matchers) {
172       unsigned ThisSpecificity;
173       if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
174               .isConvertibleTo(ArgKind::MakeMatcherArg(Kind),
175                                &ThisSpecificity)) {
176         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
177       }
178     }
179     if (Specificity)
180       *Specificity = MaxSpecificity;
181     return MaxSpecificity > 0;
182   }
183 
184   const std::vector<DynTypedMatcher> Matchers;
185 };
186 
187 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
188 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)189   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
190                     std::vector<VariantMatcher> Args)
191       : Op(Op), Args(std::move(Args)) {}
192 
getSingleMatcher() const193   std::optional<DynTypedMatcher> getSingleMatcher() const override {
194     return std::nullopt;
195   }
196 
getTypeAsString() const197   std::string getTypeAsString() const override {
198     std::string Inner;
199     for (size_t i = 0, e = Args.size(); i != e; ++i) {
200       if (i != 0)
201         Inner += "&";
202       Inner += Args[i].getTypeAsString();
203     }
204     return Inner;
205   }
206 
207   std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const208   getTypedMatcher(const MatcherOps &Ops) const override {
209     return Ops.constructVariadicOperator(Op, Args);
210   }
211 
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const212   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
213     for (const VariantMatcher &Matcher : Args) {
214       if (!Matcher.isConvertibleTo(Kind, Specificity))
215         return false;
216     }
217     return true;
218   }
219 
220 private:
221   const DynTypedMatcher::VariadicOperator Op;
222   const std::vector<VariantMatcher> Args;
223 };
224 
VariantMatcher()225 VariantMatcher::VariantMatcher() {}
226 
SingleMatcher(const DynTypedMatcher & Matcher)227 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
228   return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
229 }
230 
231 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)232 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
233   return VariantMatcher(
234       std::make_shared<PolymorphicPayload>(std::move(Matchers)));
235 }
236 
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)237 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
238     DynTypedMatcher::VariadicOperator Op,
239     std::vector<VariantMatcher> Args) {
240   return VariantMatcher(
241       std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
242 }
243 
getSingleMatcher() const244 std::optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
245   return Value ? Value->getSingleMatcher() : std::optional<DynTypedMatcher>();
246 }
247 
reset()248 void VariantMatcher::reset() { Value.reset(); }
249 
getTypeAsString() const250 std::string VariantMatcher::getTypeAsString() const {
251   if (Value) return Value->getTypeAsString();
252   return "<Nothing>";
253 }
254 
VariantValue(const VariantValue & Other)255 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
256   *this = Other;
257 }
258 
VariantValue(bool Boolean)259 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
260   setBoolean(Boolean);
261 }
262 
VariantValue(double Double)263 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
264   setDouble(Double);
265 }
266 
VariantValue(unsigned Unsigned)267 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
268   setUnsigned(Unsigned);
269 }
270 
VariantValue(StringRef String)271 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
272   setString(String);
273 }
274 
VariantValue(ASTNodeKind NodeKind)275 VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
276   setNodeKind(NodeKind);
277 }
278 
VariantValue(const VariantMatcher & Matcher)279 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
280   setMatcher(Matcher);
281 }
282 
~VariantValue()283 VariantValue::~VariantValue() { reset(); }
284 
operator =(const VariantValue & Other)285 VariantValue &VariantValue::operator=(const VariantValue &Other) {
286   if (this == &Other) return *this;
287   reset();
288   switch (Other.Type) {
289   case VT_Boolean:
290     setBoolean(Other.getBoolean());
291     break;
292   case VT_Double:
293     setDouble(Other.getDouble());
294     break;
295   case VT_Unsigned:
296     setUnsigned(Other.getUnsigned());
297     break;
298   case VT_String:
299     setString(Other.getString());
300     break;
301   case VT_NodeKind:
302     setNodeKind(Other.getNodeKind());
303     break;
304   case VT_Matcher:
305     setMatcher(Other.getMatcher());
306     break;
307   case VT_Nothing:
308     Type = VT_Nothing;
309     break;
310   }
311   return *this;
312 }
313 
reset()314 void VariantValue::reset() {
315   switch (Type) {
316   case VT_String:
317     delete Value.String;
318     break;
319   case VT_Matcher:
320     delete Value.Matcher;
321     break;
322   case VT_NodeKind:
323     delete Value.NodeKind;
324     break;
325   // Cases that do nothing.
326   case VT_Boolean:
327   case VT_Double:
328   case VT_Unsigned:
329   case VT_Nothing:
330     break;
331   }
332   Type = VT_Nothing;
333 }
334 
isBoolean() const335 bool VariantValue::isBoolean() const {
336   return Type == VT_Boolean;
337 }
338 
getBoolean() const339 bool VariantValue::getBoolean() const {
340   assert(isBoolean());
341   return Value.Boolean;
342 }
343 
setBoolean(bool NewValue)344 void VariantValue::setBoolean(bool NewValue) {
345   reset();
346   Type = VT_Boolean;
347   Value.Boolean = NewValue;
348 }
349 
isDouble() const350 bool VariantValue::isDouble() const {
351   return Type == VT_Double;
352 }
353 
getDouble() const354 double VariantValue::getDouble() const {
355   assert(isDouble());
356   return Value.Double;
357 }
358 
setDouble(double NewValue)359 void VariantValue::setDouble(double NewValue) {
360   reset();
361   Type = VT_Double;
362   Value.Double = NewValue;
363 }
364 
isUnsigned() const365 bool VariantValue::isUnsigned() const {
366   return Type == VT_Unsigned;
367 }
368 
getUnsigned() const369 unsigned VariantValue::getUnsigned() const {
370   assert(isUnsigned());
371   return Value.Unsigned;
372 }
373 
setUnsigned(unsigned NewValue)374 void VariantValue::setUnsigned(unsigned NewValue) {
375   reset();
376   Type = VT_Unsigned;
377   Value.Unsigned = NewValue;
378 }
379 
isString() const380 bool VariantValue::isString() const {
381   return Type == VT_String;
382 }
383 
getString() const384 const std::string &VariantValue::getString() const {
385   assert(isString());
386   return *Value.String;
387 }
388 
setString(StringRef NewValue)389 void VariantValue::setString(StringRef NewValue) {
390   reset();
391   Type = VT_String;
392   Value.String = new std::string(NewValue);
393 }
394 
isNodeKind() const395 bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
396 
getNodeKind() const397 const ASTNodeKind &VariantValue::getNodeKind() const {
398   assert(isNodeKind());
399   return *Value.NodeKind;
400 }
401 
setNodeKind(ASTNodeKind NewValue)402 void VariantValue::setNodeKind(ASTNodeKind NewValue) {
403   reset();
404   Type = VT_NodeKind;
405   Value.NodeKind = new ASTNodeKind(NewValue);
406 }
407 
isMatcher() const408 bool VariantValue::isMatcher() const {
409   return Type == VT_Matcher;
410 }
411 
getMatcher() const412 const VariantMatcher &VariantValue::getMatcher() const {
413   assert(isMatcher());
414   return *Value.Matcher;
415 }
416 
setMatcher(const VariantMatcher & NewValue)417 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
418   reset();
419   Type = VT_Matcher;
420   Value.Matcher = new VariantMatcher(NewValue);
421 }
422 
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const423 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
424   switch (Kind.getArgKind()) {
425   case ArgKind::AK_Boolean:
426     if (!isBoolean())
427       return false;
428     *Specificity = 1;
429     return true;
430 
431   case ArgKind::AK_Double:
432     if (!isDouble())
433       return false;
434     *Specificity = 1;
435     return true;
436 
437   case ArgKind::AK_Unsigned:
438     if (!isUnsigned())
439       return false;
440     *Specificity = 1;
441     return true;
442 
443   case ArgKind::AK_String:
444     if (!isString())
445       return false;
446     *Specificity = 1;
447     return true;
448 
449   case ArgKind::AK_Node:
450     if (!isNodeKind())
451       return false;
452     return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);
453 
454   case ArgKind::AK_Matcher:
455     if (!isMatcher())
456       return false;
457     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
458   }
459   llvm_unreachable("Invalid Type");
460 }
461 
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const462 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
463                                    unsigned *Specificity) const {
464   unsigned MaxSpecificity = 0;
465   for (const ArgKind& Kind : Kinds) {
466     unsigned ThisSpecificity;
467     if (!isConvertibleTo(Kind, &ThisSpecificity))
468       continue;
469     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
470   }
471   if (Specificity && MaxSpecificity > 0) {
472     *Specificity = MaxSpecificity;
473   }
474   return MaxSpecificity > 0;
475 }
476 
getTypeAsString() const477 std::string VariantValue::getTypeAsString() const {
478   switch (Type) {
479   case VT_String: return "String";
480   case VT_Matcher: return getMatcher().getTypeAsString();
481   case VT_Boolean: return "Boolean";
482   case VT_Double: return "Double";
483   case VT_Unsigned: return "Unsigned";
484   case VT_NodeKind:
485     return getNodeKind().asStringRef().str();
486   case VT_Nothing: return "Nothing";
487   }
488   llvm_unreachable("Invalid Type");
489 }
490 
491 } // end namespace dynamic
492 } // end namespace ast_matchers
493 } // end namespace clang
494