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