clang  6.0.0svn
VariantValue.h
Go to the documentation of this file.
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 /// \brief 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 /// \brief Kind identifier.
32 ///
33 /// It supports all types that VariantValue can contain.
34 class ArgKind {
35  public:
36  enum Kind {
42  };
43  /// \brief Constructor for non-matcher types.
44  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
45 
46  /// \brief Constructor for matcher types.
48  : K(AK_Matcher), MatcherKind(MatcherKind) {}
49 
50  Kind getArgKind() const { return K; }
52  assert(K == AK_Matcher);
53  return MatcherKind;
54  }
55 
56  /// \brief 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  /// \brief 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 /// \brief 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>.
94  /// \brief 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  /// \brief 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  /// \brief 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.
111  constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
112  ArrayRef<VariantMatcher> InnerMatchers) const;
113 
114  protected:
115  ~MatcherOps() = default;
116 
117  private:
119  };
120 
121  /// \brief 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;
130  getTypedMatcher(const MatcherOps &Ops) const = 0;
132  unsigned *Specificity) const = 0;
133  };
134 
135 public:
136  /// \brief A null matcher.
137  VariantMatcher();
138 
139  /// \brief Clones the provided matcher.
140  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
141 
142  /// \brief 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  /// \brief 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  /// \brief Makes the matcher the "null" matcher.
156  void reset();
157 
158  /// \brief Whether the matcher is null.
159  bool isNull() const { return !Value; }
160 
161  /// \brief 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  /// \brief 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  /// \brief 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.
189  unsigned *Specificity) const {
190  if (Value)
191  return Value->isConvertibleTo(Kind, Specificity);
192  return false;
193  }
194 
195  /// \brief 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  /// \brief 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:
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 {
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 /// \brief 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>)
252 public:
253  VariantValue() : Type(VT_Nothing) {}
254 
255  VariantValue(const VariantValue &Other);
256  ~VariantValue();
257  VariantValue &operator=(const VariantValue &Other);
258 
259  /// \brief 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  /// \brief Constructs an \c unsigned value (disambiguation from bool).
267  VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
268 
269  /// \brief 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  /// \brief Boolean value functions.
274  bool isBoolean() const;
275  bool getBoolean() const;
276  void setBoolean(bool Boolean);
277 
278  /// \brief Double value functions.
279  bool isDouble() const;
280  double getDouble() const;
281  void setDouble(double Double);
282 
283  /// \brief Unsigned value functions.
284  bool isUnsigned() const;
285  unsigned getUnsigned() const;
286  void setUnsigned(unsigned Unsigned);
287 
288  /// \brief String value functions.
289  bool isString() const;
290  const std::string &getString() const;
291  void setString(StringRef String);
292 
293  /// \brief Matcher value functions.
294  bool isMatcher() const;
295  const VariantMatcher &getMatcher() const;
296  void setMatcher(const VariantMatcher &Matcher);
297 
298  /// \brief 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  /// \brief 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  /// \brief String representation of the type of the value.
317  std::string getTypeAsString() const;
318 
319 private:
320  void reset();
321 
322  /// \brief 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  /// \brief 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
bool hasTypedMatcher() const
Determines if the contained matcher can be converted to Matcher<T>.
Definition: VariantValue.h:177
std::string asString() const
String representation of the type.
The base class of the type hierarchy.
Definition: Type.h:1360
bool operator<(const ArgKind &Other) const
Definition: VariantValue.h:64
ast_matchers::internal::Matcher< T > getTypedMatcher() const
Return this matcher as a Matcher<T>.
Definition: VariantValue.h:200
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:267
ArgKind(Kind K)
Constructor for non-matcher types.
Definition: VariantValue.h:44
const FunctionProtoType * T
#define bool
Definition: stdbool.h:31
Kind
Dataflow Directional Tag Classes.
ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
Constructor for matcher types.
Definition: VariantValue.h:47
bool isNull() const
Whether the matcher is null.
Definition: VariantValue.h:159
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const
Determines if the contained matcher can be converted to Kind.
Definition: VariantValue.h:188
ast_type_traits::ASTNodeKind getMatcherKind() const
Definition: VariantValue.h:51