1//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7///
8/// \file
9/// Polymorphic value type.
10///
11/// Supports all the types required for dynamic Matcher construction.
12///  Used by the registry to construct matchers in a generic way.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
17#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
18
19#include "clang/ASTMatchers/ASTMatchers.h"
20#include "clang/ASTMatchers/ASTMatchersInternal.h"
21#include "llvm/ADT/IntrusiveRefCntPtr.h"
22#include "llvm/ADT/Optional.h"
23#include <memory>
24#include <vector>
25
26namespace clang {
27namespace ast_matchers {
28namespace dynamic {
29
30/// Kind identifier.
31///
32/// It supports all types that VariantValue can contain.
33class ArgKind {
34 public:
35  enum Kind {
36    AK_Matcher,
37    AK_Boolean,
38    AK_Double,
39    AK_Unsigned,
40    AK_String
41  };
42  /// Constructor for non-matcher types.
43  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
44
45  /// Constructor for matcher types.
46  ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
47      : K(AK_Matcher), MatcherKind(MatcherKind) {}
48
49  Kind getArgKind() const { return K; }
50  ast_type_traits::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
72private:
73  Kind K;
74  ast_type_traits::ASTNodeKind MatcherKind;
75};
76
77using 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>.
92class VariantMatcher {
93  /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
94  class MatcherOps {
95  public:
96    MatcherOps(ast_type_traits::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    ast_type_traits::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(ast_type_traits::ASTNodeKind Kind,
131                                 unsigned *Specificity) const = 0;
132  };
133
134public:
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.
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>
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.
187  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
188                       unsigned *Specificity) const {
189    if (Value)
190      return Value->isConvertibleTo(Kind, Specificity);
191    return false;
192  }
193
194  /// Return this matcher as a \c Matcher<T>.
195  ///
196  /// Handles the different types (Single, Polymorphic) accordingly.
197  /// Asserts that \c hasTypedMatcher<T>() is true.
198  template <class T>
199  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
200    assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
201    return Value->getTypedMatcher(TypedMatcherOps<T>())
202        ->template convertTo<T>();
203  }
204
205  /// String representation of the type of the value.
206  ///
207  /// If the underlying matcher is a polymorphic one, the string will show all
208  /// the types.
209  std::string getTypeAsString() const;
210
211private:
212  explicit VariantMatcher(std::shared_ptr<Payload> Value)
213      : Value(std::move(Value)) {}
214
215  template <typename T> struct TypedMatcherOps;
216
217  class SinglePayload;
218  class PolymorphicPayload;
219  class VariadicOpPayload;
220
221  std::shared_ptr<const Payload> Value;
222};
223
224template <typename T>
225struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
226  TypedMatcherOps()
227      : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
228  typedef ast_matchers::internal::Matcher<T> MatcherT;
229
230  DynTypedMatcher
231  convertMatcher(const DynTypedMatcher &Matcher) const override {
232    return DynTypedMatcher(Matcher.convertTo<T>());
233  }
234};
235
236/// Variant value class.
237///
238/// Basically, a tagged union with value type semantics.
239/// It is used by the registry as the return value and argument type for the
240/// matcher factory methods.
241/// It can be constructed from any of the supported types. It supports
242/// copy/assignment.
243///
244/// Supported types:
245///  - \c bool
246//   - \c double
247///  - \c unsigned
248///  - \c llvm::StringRef
249///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
250class VariantValue {
251public:
252  VariantValue() : Type(VT_Nothing) {}
253
254  VariantValue(const VariantValue &Other);
255  ~VariantValue();
256  VariantValue &operator=(const VariantValue &Other);
257
258  /// Specific constructors for each supported type.
259  VariantValue(bool Boolean);
260  VariantValue(double Double);
261  VariantValue(unsigned Unsigned);
262  VariantValue(StringRef String);
263  VariantValue(const VariantMatcher &Matchers);
264
265  /// Constructs an \c unsigned value (disambiguation from bool).
266  VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
267
268  /// Returns true iff this is not an empty value.
269  explicit operator bool() const { return hasValue(); }
270  bool hasValue() const { return Type != VT_Nothing; }
271
272  /// Boolean value functions.
273  bool isBoolean() const;
274  bool getBoolean() const;
275  void setBoolean(bool Boolean);
276
277  /// Double value functions.
278  bool isDouble() const;
279  double getDouble() const;
280  void setDouble(double Double);
281
282  /// Unsigned value functions.
283  bool isUnsigned() const;
284  unsigned getUnsigned() const;
285  void setUnsigned(unsigned Unsigned);
286
287  /// String value functions.
288  bool isString() const;
289  const std::string &getString() const;
290  void setString(StringRef String);
291
292  /// Matcher value functions.
293  bool isMatcher() const;
294  const VariantMatcher &getMatcher() const;
295  void setMatcher(const VariantMatcher &Matcher);
296
297  /// Determines if the contained value can be converted to \p Kind.
298  ///
299  /// \param Kind the requested destination type.
300  ///
301  /// \param Specificity value corresponding to the "specificity" of the
302  ///   conversion.
303  bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
304
305  /// Determines if the contained value can be converted to any kind
306  /// in \p Kinds.
307  ///
308  /// \param Kinds the requested destination types.
309  ///
310  /// \param Specificity value corresponding to the "specificity" of the
311  ///   conversion. It is the maximum specificity of all the possible
312  ///   conversions.
313  bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
314
315  /// String representation of the type of the value.
316  std::string getTypeAsString() const;
317
318private:
319  void reset();
320
321  /// All supported value types.
322  enum ValueType {
323    VT_Nothing,
324    VT_Boolean,
325    VT_Double,
326    VT_Unsigned,
327    VT_String,
328    VT_Matcher
329  };
330
331  /// All supported value types.
332  union AllValues {
333    unsigned Unsigned;
334    double Double;
335    bool Boolean;
336    std::string *String;
337    VariantMatcher *Matcher;
338  };
339
340  ValueType Type;
341  AllValues Value;
342};
343
344} // end namespace dynamic
345} // end namespace ast_matchers
346} // end namespace clang
347
348#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
349