clang  12.0.0git
VariantValue.h
Go to the documentation of this file.
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 
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 {
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(ASTNodeKind MatcherKind) : K(AK_Matcher), MatcherKind(MatcherKind) {}
48 
49  Kind getArgKind() const { return K; }
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>.
93  /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
94  class MatcherOps {
95  public:
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.
110  constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
111  ArrayRef<VariantMatcher> InnerMatchers) const;
112 
113  protected:
114  ~MatcherOps() = default;
115 
116  private:
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;
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.
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(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>
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:
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 {
225  TypedMatcherOps() : MatcherOps(ASTNodeKind::getFromNodeKind<T>()) {}
226  typedef ast_matchers::internal::Matcher<T> MatcherT;
227 
228  DynTypedMatcher
229  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>)
249 public:
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).
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(); }
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
bool hasTypedMatcher() const
Determines if the contained matcher can be converted to Matcher<T>.
Definition: VariantValue.h:176
std::string asString() const
String representation of the type.
The base class of the type hierarchy.
Definition: Type.h:1472
bool operator<(const ArgKind &Other) const
Definition: VariantValue.h:63
ast_matchers::internal::Matcher< T > getTypedMatcher() const
Return this matcher as a Matcher<T>.
Definition: VariantValue.h:198
ArgKind(ASTNodeKind MatcherKind)
Constructor for matcher types.
Definition: VariantValue.h:47
bool isConvertibleTo(ArgKind To, unsigned *Specificity) const
Determines if this type can be converted to To.
VariantValue(int Signed)
Constructs an unsigned value (disambiguation from bool).
Definition: VariantValue.h:264
ArgKind(Kind K)
Constructor for non-matcher types.
Definition: VariantValue.h:44
#define bool
Definition: stdbool.h:15
NodeKind
A kind of a syntax node, used for implementing casts.
Definition: Nodes.h:37
Kind
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const
Determines if the contained matcher can be converted to Kind.
Definition: VariantValue.h:187
Dataflow Directional Tag Classes.
Kind identifier.
Definition: ASTTypeTraits.h:56
bool isNull() const
Whether the matcher is null.
Definition: VariantValue.h:158