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