xref: /freebsd/contrib/llvm-project/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 //===--- VariantValue.h - 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 /// Supports all the types required for dynamic Matcher construction.
13 ///  Used by the registry to construct matchers in a generic way.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
18 #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
19 
20 #include "clang/ASTMatchers/ASTMatchers.h"
21 #include "clang/ASTMatchers/ASTMatchersInternal.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include <memory>
24 #include <optional>
25 #include <vector>
26 
27 namespace clang {
28 namespace ast_matchers {
29 namespace dynamic {
30 
31 /// Kind identifier.
32 ///
33 /// It supports all types that VariantValue can contain.
34 class ArgKind {
35  public:
36   enum Kind {
37     AK_Matcher,
38     AK_Node,
39     AK_Boolean,
40     AK_Double,
41     AK_Unsigned,
42     AK_String
43   };
44   /// Constructor for non-matcher types.
ArgKind(Kind K)45   ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
46 
47   /// Constructor for matcher types.
MakeMatcherArg(ASTNodeKind MatcherKind)48   static ArgKind MakeMatcherArg(ASTNodeKind MatcherKind) {
49     return ArgKind{AK_Matcher, MatcherKind};
50   }
51 
MakeNodeArg(ASTNodeKind MatcherKind)52   static ArgKind MakeNodeArg(ASTNodeKind MatcherKind) {
53     return ArgKind{AK_Node, MatcherKind};
54   }
55 
getArgKind()56   Kind getArgKind() const { return K; }
getMatcherKind()57   ASTNodeKind getMatcherKind() const {
58     assert(K == AK_Matcher);
59     return NodeKind;
60   }
getNodeKind()61   ASTNodeKind getNodeKind() const {
62     assert(K == AK_Node);
63     return NodeKind;
64   }
65 
66   /// Determines if this type can be converted to \p To.
67   ///
68   /// \param To the requested destination type.
69   ///
70   /// \param Specificity value corresponding to the "specificity" of the
71   ///   conversion.
72   bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
73 
74   bool operator<(const ArgKind &Other) const {
75     if ((K == AK_Matcher && Other.K == AK_Matcher) ||
76         (K == AK_Node && Other.K == AK_Node))
77       return NodeKind < Other.NodeKind;
78     return K < Other.K;
79   }
80 
81   /// String representation of the type.
82   std::string asString() const;
83 
84 private:
ArgKind(Kind K,ASTNodeKind NK)85   ArgKind(Kind K, ASTNodeKind NK) : K(K), NodeKind(NK) {}
86   Kind K;
87   ASTNodeKind NodeKind;
88 };
89 
90 using ast_matchers::internal::DynTypedMatcher;
91 
92 /// A variant matcher object.
93 ///
94 /// The purpose of this object is to abstract simple and polymorphic matchers
95 /// into a single object type.
96 /// Polymorphic matchers might be implemented as a list of all the possible
97 /// overloads of the matcher. \c VariantMatcher knows how to select the
98 /// appropriate overload when needed.
99 /// To get a real matcher object out of a \c VariantMatcher you can do:
100 ///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
101 ///    to decide which matcher to return. Eg. it contains only a single
102 ///    matcher, or a polymorphic one with only one overload.
103 ///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
104 ///    the underlying matcher(s) can unambiguously return a Matcher<T>.
105 class VariantMatcher {
106   /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
107   class MatcherOps {
108   public:
MatcherOps(ASTNodeKind NodeKind)109     MatcherOps(ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
110 
111     bool canConstructFrom(const DynTypedMatcher &Matcher,
112                           bool &IsExactMatch) const;
113 
114     /// Convert \p Matcher the destination type and return it as a new
115     /// DynTypedMatcher.
116     DynTypedMatcher convertMatcher(const DynTypedMatcher &Matcher) const;
117 
118     /// Constructs a variadic typed matcher from \p InnerMatchers.
119     /// Will try to convert each inner matcher to the destination type and
120     /// return std::nullopt if it fails to do so.
121     std::optional<DynTypedMatcher>
122     constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
123                               ArrayRef<VariantMatcher> InnerMatchers) const;
124 
125   private:
126     ASTNodeKind NodeKind;
127   };
128 
129   /// Payload interface to be specialized by each matcher type.
130   ///
131   /// It follows a similar interface as VariantMatcher itself.
132   class Payload {
133   public:
134     virtual ~Payload();
135     virtual std::optional<DynTypedMatcher> getSingleMatcher() const = 0;
136     virtual std::string getTypeAsString() const = 0;
137     virtual std::optional<DynTypedMatcher>
138     getTypedMatcher(const MatcherOps &Ops) const = 0;
139     virtual bool isConvertibleTo(ASTNodeKind Kind,
140                                  unsigned *Specificity) const = 0;
141   };
142 
143 public:
144   /// A null matcher.
145   VariantMatcher();
146 
147   /// Clones the provided matcher.
148   static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
149 
150   /// Clones the provided matchers.
151   ///
152   /// They should be the result of a polymorphic matcher.
153   static VariantMatcher
154   PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
155 
156   /// Creates a 'variadic' operator matcher.
157   ///
158   /// It will bind to the appropriate type on getTypedMatcher<T>().
159   static VariantMatcher
160   VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
161                           std::vector<VariantMatcher> Args);
162 
163   /// Makes the matcher the "null" matcher.
164   void reset();
165 
166   /// Whether the matcher is null.
isNull()167   bool isNull() const { return !Value; }
168 
169   /// Return a single matcher, if there is no ambiguity.
170   ///
171   /// \returns the matcher, if there is only one matcher. An empty Optional, if
172   /// the underlying matcher is a polymorphic matcher with more than one
173   /// representation.
174   std::optional<DynTypedMatcher> getSingleMatcher() const;
175 
176   /// Determines if the contained matcher can be converted to
177   ///   \c Matcher<T>.
178   ///
179   /// For the Single case, it returns true if it can be converted to
180   /// \c Matcher<T>.
181   /// For the Polymorphic case, it returns true if one, and only one, of the
182   /// overloads can be converted to \c Matcher<T>. If there are more than one
183   /// that can, the result would be ambiguous and false is returned.
184   template <class T>
hasTypedMatcher()185   bool hasTypedMatcher() const {
186     return hasTypedMatcher(ASTNodeKind::getFromNodeKind<T>());
187   }
188 
hasTypedMatcher(ASTNodeKind NK)189   bool hasTypedMatcher(ASTNodeKind NK) const {
190     if (!Value) return false;
191     return Value->getTypedMatcher(MatcherOps(NK)).has_value();
192   }
193 
194   /// Determines if the contained matcher can be converted to \p Kind.
195   ///
196   /// \param Kind the requested destination type.
197   ///
198   /// \param Specificity value corresponding to the "specificity" of the
199   ///   conversion.
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity)200   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const {
201     if (Value)
202       return Value->isConvertibleTo(Kind, Specificity);
203     return false;
204   }
205 
206   /// Return this matcher as a \c Matcher<T>.
207   ///
208   /// Handles the different types (Single, Polymorphic) accordingly.
209   /// Asserts that \c hasTypedMatcher<T>() is true.
210   template <class T>
getTypedMatcher()211   ast_matchers::internal::Matcher<T> getTypedMatcher() const {
212     assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
213     return Value->getTypedMatcher(MatcherOps(ASTNodeKind::getFromNodeKind<T>()))
214         ->template convertTo<T>();
215   }
216 
getTypedMatcher(ASTNodeKind NK)217   DynTypedMatcher getTypedMatcher(ASTNodeKind NK) const {
218     assert(hasTypedMatcher(NK) && "hasTypedMatcher(NK) == false");
219     return *Value->getTypedMatcher(MatcherOps(NK));
220   }
221 
222   /// String representation of the type of the value.
223   ///
224   /// If the underlying matcher is a polymorphic one, the string will show all
225   /// the types.
226   std::string getTypeAsString() const;
227 
228 private:
VariantMatcher(std::shared_ptr<Payload> Value)229   explicit VariantMatcher(std::shared_ptr<Payload> Value)
230       : Value(std::move(Value)) {}
231 
232 
233   class SinglePayload;
234   class PolymorphicPayload;
235   class VariadicOpPayload;
236 
237   std::shared_ptr<const Payload> Value;
238 };
239 
240 /// Variant value class.
241 ///
242 /// Basically, a tagged union with value type semantics.
243 /// It is used by the registry as the return value and argument type for the
244 /// matcher factory methods.
245 /// It can be constructed from any of the supported types. It supports
246 /// copy/assignment.
247 ///
248 /// Supported types:
249 ///  - \c bool
250 //   - \c double
251 ///  - \c unsigned
252 ///  - \c llvm::StringRef
253 ///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
254 class VariantValue {
255 public:
VariantValue()256   VariantValue() : Type(VT_Nothing) {}
257 
258   VariantValue(const VariantValue &Other);
259   ~VariantValue();
260   VariantValue &operator=(const VariantValue &Other);
261 
262   /// Specific constructors for each supported type.
263   VariantValue(bool Boolean);
264   VariantValue(double Double);
265   VariantValue(unsigned Unsigned);
266   VariantValue(StringRef String);
267   VariantValue(ASTNodeKind NodeKind);
268   VariantValue(const VariantMatcher &Matchers);
269 
270   /// Constructs an \c unsigned value (disambiguation from bool).
VariantValue(int Signed)271   VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
272 
273   /// Returns true iff this is not an empty value.
274   explicit operator bool() const { return hasValue(); }
hasValue()275   bool hasValue() const { return Type != VT_Nothing; }
276 
277   /// Boolean value functions.
278   bool isBoolean() const;
279   bool getBoolean() const;
280   void setBoolean(bool Boolean);
281 
282   /// Double value functions.
283   bool isDouble() const;
284   double getDouble() const;
285   void setDouble(double Double);
286 
287   /// Unsigned value functions.
288   bool isUnsigned() const;
289   unsigned getUnsigned() const;
290   void setUnsigned(unsigned Unsigned);
291 
292   /// String value functions.
293   bool isString() const;
294   const std::string &getString() const;
295   void setString(StringRef String);
296 
297   bool isNodeKind() const;
298   const ASTNodeKind &getNodeKind() const;
299   void setNodeKind(ASTNodeKind NodeKind);
300 
301   /// Matcher value functions.
302   bool isMatcher() const;
303   const VariantMatcher &getMatcher() const;
304   void setMatcher(const VariantMatcher &Matcher);
305 
306   /// Determines if the contained value can be converted to \p Kind.
307   ///
308   /// \param Kind the requested destination type.
309   ///
310   /// \param Specificity value corresponding to the "specificity" of the
311   ///   conversion.
312   bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
313 
314   /// Determines if the contained value can be converted to any kind
315   /// in \p Kinds.
316   ///
317   /// \param Kinds the requested destination types.
318   ///
319   /// \param Specificity value corresponding to the "specificity" of the
320   ///   conversion. It is the maximum specificity of all the possible
321   ///   conversions.
322   bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
323 
324   /// String representation of the type of the value.
325   std::string getTypeAsString() const;
326 
327 private:
328   void reset();
329 
330   /// All supported value types.
331   enum ValueType {
332     VT_Nothing,
333     VT_Boolean,
334     VT_Double,
335     VT_Unsigned,
336     VT_String,
337     VT_Matcher,
338     VT_NodeKind
339   };
340 
341   /// All supported value types.
342   union AllValues {
343     unsigned Unsigned;
344     double Double;
345     bool Boolean;
346     std::string *String;
347     VariantMatcher *Matcher;
348     ASTNodeKind *NodeKind;
349   };
350 
351   ValueType Type;
352   AllValues Value;
353 };
354 
355 } // end namespace dynamic
356 } // end namespace ast_matchers
357 } // end namespace clang
358 
359 #endif // LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
360