VariantValue.h revision 288943
1259701Sdim//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
2259701Sdim//                     The LLVM Compiler Infrastructure
3259701Sdim//
4259701Sdim// This file is distributed under the University of Illinois Open Source
5259701Sdim// License. See LICENSE.TXT for details.
6259701Sdim//
7259701Sdim//===----------------------------------------------------------------------===//
8259701Sdim///
9259701Sdim/// \file
10259701Sdim/// \brief Polymorphic value type.
11259701Sdim///
12259701Sdim/// Supports all the types required for dynamic Matcher construction.
13259701Sdim///  Used by the registry to construct matchers in a generic way.
14259701Sdim///
15259701Sdim//===----------------------------------------------------------------------===//
16259701Sdim
17280031Sdim#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
18280031Sdim#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
19259701Sdim
20259701Sdim#include "clang/ASTMatchers/ASTMatchers.h"
21259701Sdim#include "clang/ASTMatchers/ASTMatchersInternal.h"
22259701Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h"
23259701Sdim#include "llvm/ADT/Optional.h"
24259701Sdim#include "llvm/ADT/Twine.h"
25276479Sdim#include <memory>
26276479Sdim#include <vector>
27259701Sdim
28259701Sdimnamespace clang {
29259701Sdimnamespace ast_matchers {
30259701Sdimnamespace dynamic {
31259701Sdim
32280031Sdim/// \brief Kind identifier.
33280031Sdim///
34280031Sdim/// It supports all types that VariantValue can contain.
35280031Sdimclass ArgKind {
36280031Sdim public:
37280031Sdim  enum Kind {
38280031Sdim    AK_Matcher,
39280031Sdim    AK_Unsigned,
40280031Sdim    AK_String
41280031Sdim  };
42280031Sdim  /// \brief Constructor for non-matcher types.
43280031Sdim  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
44280031Sdim
45280031Sdim  /// \brief Constructor for matcher types.
46280031Sdim  ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
47280031Sdim      : K(AK_Matcher), MatcherKind(MatcherKind) {}
48280031Sdim
49280031Sdim  Kind getArgKind() const { return K; }
50280031Sdim  ast_type_traits::ASTNodeKind getMatcherKind() const {
51280031Sdim    assert(K == AK_Matcher);
52280031Sdim    return MatcherKind;
53280031Sdim  }
54280031Sdim
55280031Sdim  /// \brief Determines if this type can be converted to \p To.
56280031Sdim  ///
57280031Sdim  /// \param To the requested destination type.
58280031Sdim  ///
59280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
60280031Sdim  ///   convertion.
61280031Sdim  bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
62280031Sdim
63280031Sdim  bool operator<(const ArgKind &Other) const {
64280031Sdim    if (K == AK_Matcher && Other.K == AK_Matcher)
65280031Sdim      return MatcherKind < Other.MatcherKind;
66280031Sdim    return K < Other.K;
67280031Sdim  }
68280031Sdim
69280031Sdim  /// \brief String representation of the type.
70280031Sdim  std::string asString() const;
71280031Sdim
72280031Sdimprivate:
73280031Sdim  Kind K;
74280031Sdim  ast_type_traits::ASTNodeKind MatcherKind;
75280031Sdim};
76280031Sdim
77259701Sdimusing ast_matchers::internal::DynTypedMatcher;
78259701Sdim
79259701Sdim/// \brief A variant matcher object.
80259701Sdim///
81259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers
82259701Sdim/// into a single object type.
83259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible
84259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the
85259701Sdim/// appropriate overload when needed.
86259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do:
87259701Sdim///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
88259701Sdim///    to decide which matcher to return. Eg. it contains only a single
89259701Sdim///    matcher, or a polymorphic one with only one overload.
90259701Sdim///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
91259701Sdim///    the underlying matcher(s) can unambiguously return a Matcher<T>.
92259701Sdimclass VariantMatcher {
93259701Sdim  /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
94259701Sdim  class MatcherOps {
95259701Sdim  public:
96280031Sdim    MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
97280031Sdim
98280031Sdim    bool canConstructFrom(const DynTypedMatcher &Matcher,
99280031Sdim                          bool &IsExactMatch) const;
100280031Sdim
101280031Sdim    /// \brief Convert \p Matcher the destination type and return it as a new
102280031Sdim    /// DynTypedMatcher.
103280031Sdim    virtual DynTypedMatcher
104280031Sdim    convertMatcher(const DynTypedMatcher &Matcher) const = 0;
105280031Sdim
106280031Sdim    /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
107280031Sdim    /// Will try to convert each inner matcher to the destination type and
108280031Sdim    /// return llvm::None if it fails to do so.
109280031Sdim    llvm::Optional<DynTypedMatcher>
110280031Sdim    constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
111280031Sdim                              ArrayRef<VariantMatcher> InnerMatchers) const;
112280031Sdim
113280031Sdim  protected:
114288943Sdim    ~MatcherOps() = default;
115280031Sdim
116280031Sdim  private:
117280031Sdim    ast_type_traits::ASTNodeKind NodeKind;
118259701Sdim  };
119259701Sdim
120259701Sdim  /// \brief Payload interface to be specialized by each matcher type.
121259701Sdim  ///
122259701Sdim  /// It follows a similar interface as VariantMatcher itself.
123259701Sdim  class Payload : public RefCountedBaseVPTR {
124259701Sdim  public:
125288943Sdim    ~Payload() override;
126259701Sdim    virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
127259701Sdim    virtual std::string getTypeAsString() const = 0;
128280031Sdim    virtual llvm::Optional<DynTypedMatcher>
129280031Sdim    getTypedMatcher(const MatcherOps &Ops) const = 0;
130280031Sdim    virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
131280031Sdim                                 unsigned *Specificity) const = 0;
132259701Sdim  };
133259701Sdim
134259701Sdimpublic:
135259701Sdim  /// \brief A null matcher.
136259701Sdim  VariantMatcher();
137259701Sdim
138259701Sdim  /// \brief Clones the provided matcher.
139259701Sdim  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
140259701Sdim
141259701Sdim  /// \brief Clones the provided matchers.
142259701Sdim  ///
143259701Sdim  /// They should be the result of a polymorphic matcher.
144276479Sdim  static VariantMatcher
145276479Sdim  PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
146259701Sdim
147259701Sdim  /// \brief Creates a 'variadic' operator matcher.
148259701Sdim  ///
149259701Sdim  /// It will bind to the appropriate type on getTypedMatcher<T>().
150280031Sdim  static VariantMatcher
151280031Sdim  VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
152280031Sdim                          std::vector<VariantMatcher> Args);
153259701Sdim
154259701Sdim  /// \brief Makes the matcher the "null" matcher.
155259701Sdim  void reset();
156259701Sdim
157259701Sdim  /// \brief Whether the matcher is null.
158259701Sdim  bool isNull() const { return !Value; }
159259701Sdim
160259701Sdim  /// \brief Return a single matcher, if there is no ambiguity.
161259701Sdim  ///
162259701Sdim  /// \returns the matcher, if there is only one matcher. An empty Optional, if
163259701Sdim  /// the underlying matcher is a polymorphic matcher with more than one
164259701Sdim  /// representation.
165259701Sdim  llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
166259701Sdim
167259701Sdim  /// \brief Determines if the contained matcher can be converted to
168259701Sdim  ///   \c Matcher<T>.
169259701Sdim  ///
170259701Sdim  /// For the Single case, it returns true if it can be converted to
171259701Sdim  /// \c Matcher<T>.
172259701Sdim  /// For the Polymorphic case, it returns true if one, and only one, of the
173259701Sdim  /// overloads can be converted to \c Matcher<T>. If there are more than one
174259701Sdim  /// that can, the result would be ambiguous and false is returned.
175259701Sdim  template <class T>
176259701Sdim  bool hasTypedMatcher() const {
177280031Sdim    if (!Value) return false;
178280031Sdim    return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
179259701Sdim  }
180259701Sdim
181280031Sdim  /// \brief Determines if the contained matcher can be converted to \p Kind.
182280031Sdim  ///
183280031Sdim  /// \param Kind the requested destination type.
184280031Sdim  ///
185280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
186280031Sdim  ///   convertion.
187280031Sdim  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
188280031Sdim                       unsigned *Specificity) const {
189280031Sdim    if (Value)
190280031Sdim      return Value->isConvertibleTo(Kind, Specificity);
191280031Sdim    return false;
192280031Sdim  }
193280031Sdim
194259701Sdim  /// \brief Return this matcher as a \c Matcher<T>.
195259701Sdim  ///
196259701Sdim  /// Handles the different types (Single, Polymorphic) accordingly.
197259701Sdim  /// Asserts that \c hasTypedMatcher<T>() is true.
198259701Sdim  template <class T>
199259701Sdim  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
200280031Sdim    assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
201280031Sdim    return Value->getTypedMatcher(TypedMatcherOps<T>())
202280031Sdim        ->template convertTo<T>();
203259701Sdim  }
204259701Sdim
205259701Sdim  /// \brief String representation of the type of the value.
206259701Sdim  ///
207259701Sdim  /// If the underlying matcher is a polymorphic one, the string will show all
208259701Sdim  /// the types.
209259701Sdim  std::string getTypeAsString() const;
210259701Sdim
211259701Sdimprivate:
212259701Sdim  explicit VariantMatcher(Payload *Value) : Value(Value) {}
213259701Sdim
214280031Sdim  template <typename T> struct TypedMatcherOps;
215280031Sdim
216259701Sdim  class SinglePayload;
217259701Sdim  class PolymorphicPayload;
218259701Sdim  class VariadicOpPayload;
219259701Sdim
220280031Sdim  IntrusiveRefCntPtr<const Payload> Value;
221280031Sdim};
222259701Sdim
223280031Sdimtemplate <typename T>
224280031Sdimstruct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
225280031Sdim  TypedMatcherOps()
226280031Sdim      : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
227280031Sdim  typedef ast_matchers::internal::Matcher<T> MatcherT;
228259701Sdim
229280031Sdim  DynTypedMatcher
230280031Sdim  convertMatcher(const DynTypedMatcher &Matcher) const override {
231280031Sdim    return DynTypedMatcher(Matcher.convertTo<T>());
232280031Sdim  }
233259701Sdim};
234259701Sdim
235259701Sdim/// \brief Variant value class.
236259701Sdim///
237259701Sdim/// Basically, a tagged union with value type semantics.
238259701Sdim/// It is used by the registry as the return value and argument type for the
239259701Sdim/// matcher factory methods.
240259701Sdim/// It can be constructed from any of the supported types. It supports
241259701Sdim/// copy/assignment.
242259701Sdim///
243259701Sdim/// Supported types:
244259701Sdim///  - \c unsigned
245288943Sdim///  - \c llvm::StringRef
246259701Sdim///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
247259701Sdimclass VariantValue {
248259701Sdimpublic:
249259701Sdim  VariantValue() : Type(VT_Nothing) {}
250259701Sdim
251259701Sdim  VariantValue(const VariantValue &Other);
252259701Sdim  ~VariantValue();
253259701Sdim  VariantValue &operator=(const VariantValue &Other);
254259701Sdim
255259701Sdim  /// \brief Specific constructors for each supported type.
256259701Sdim  VariantValue(unsigned Unsigned);
257288943Sdim  VariantValue(StringRef String);
258259701Sdim  VariantValue(const VariantMatcher &Matchers);
259259701Sdim
260276479Sdim  /// \brief Returns true iff this is not an empty value.
261288943Sdim  explicit operator bool() const { return hasValue(); }
262276479Sdim  bool hasValue() const { return Type != VT_Nothing; }
263276479Sdim
264259701Sdim  /// \brief Unsigned value functions.
265259701Sdim  bool isUnsigned() const;
266259701Sdim  unsigned getUnsigned() const;
267259701Sdim  void setUnsigned(unsigned Unsigned);
268259701Sdim
269259701Sdim  /// \brief String value functions.
270259701Sdim  bool isString() const;
271259701Sdim  const std::string &getString() const;
272288943Sdim  void setString(StringRef String);
273259701Sdim
274259701Sdim  /// \brief Matcher value functions.
275259701Sdim  bool isMatcher() const;
276259701Sdim  const VariantMatcher &getMatcher() const;
277259701Sdim  void setMatcher(const VariantMatcher &Matcher);
278259701Sdim
279280031Sdim  /// \brief Determines if the contained value can be converted to \p Kind.
280280031Sdim  ///
281280031Sdim  /// \param Kind the requested destination type.
282280031Sdim  ///
283280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
284280031Sdim  ///   convertion.
285280031Sdim  bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
286280031Sdim
287280031Sdim  /// \brief Determines if the contained value can be converted to any kind
288280031Sdim  /// in \p Kinds.
289280031Sdim  ///
290280031Sdim  /// \param Kinds the requested destination types.
291280031Sdim  ///
292280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
293280031Sdim  ///   convertion. It is the maximum specificity of all the possible
294280031Sdim  ///   conversions.
295280031Sdim  bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
296280031Sdim
297259701Sdim  /// \brief String representation of the type of the value.
298259701Sdim  std::string getTypeAsString() const;
299259701Sdim
300259701Sdimprivate:
301259701Sdim  void reset();
302259701Sdim
303259701Sdim  /// \brief All supported value types.
304259701Sdim  enum ValueType {
305259701Sdim    VT_Nothing,
306259701Sdim    VT_Unsigned,
307259701Sdim    VT_String,
308259701Sdim    VT_Matcher
309259701Sdim  };
310259701Sdim
311259701Sdim  /// \brief All supported value types.
312259701Sdim  union AllValues {
313259701Sdim    unsigned Unsigned;
314259701Sdim    std::string *String;
315259701Sdim    VariantMatcher *Matcher;
316259701Sdim  };
317259701Sdim
318259701Sdim  ValueType Type;
319259701Sdim  AllValues Value;
320259701Sdim};
321259701Sdim
322259701Sdim} // end namespace dynamic
323259701Sdim} // end namespace ast_matchers
324259701Sdim} // end namespace clang
325259701Sdim
326259701Sdim#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
327