VariantValue.h revision 341825
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
27namespace clang {
28namespace ast_matchers {
29namespace dynamic {
30
31/// Kind identifier.
32///
33/// It supports all types that VariantValue can contain.
34class 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.
44  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
45
46  /// Constructor for matcher types.
47  ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
48      : K(AK_Matcher), MatcherKind(MatcherKind) {}
49
50  Kind getArgKind() const { return K; }
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
73private:
74  Kind K;
75  ast_type_traits::ASTNodeKind MatcherKind;
76};
77
78using 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>.
93class VariantMatcher {
94  /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
95  class MatcherOps {
96  public:
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
135public:
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.
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>
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.
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>
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
212private:
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
225template <typename T>
226struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
227  TypedMatcherOps()
228      : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
229  typedef ast_matchers::internal::Matcher<T> MatcherT;
230
231  DynTypedMatcher
232  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>)
251class VariantValue {
252public:
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).
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(); }
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
319private:
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