VariantValue.h revision 314564
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"
24276479Sdim#include <memory>
25276479Sdim#include <vector>
26259701Sdim
27259701Sdimnamespace clang {
28259701Sdimnamespace ast_matchers {
29259701Sdimnamespace dynamic {
30259701Sdim
31280031Sdim/// \brief Kind identifier.
32280031Sdim///
33280031Sdim/// It supports all types that VariantValue can contain.
34280031Sdimclass ArgKind {
35280031Sdim public:
36280031Sdim  enum Kind {
37280031Sdim    AK_Matcher,
38280031Sdim    AK_Unsigned,
39280031Sdim    AK_String
40280031Sdim  };
41280031Sdim  /// \brief Constructor for non-matcher types.
42280031Sdim  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
43280031Sdim
44280031Sdim  /// \brief Constructor for matcher types.
45280031Sdim  ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
46280031Sdim      : K(AK_Matcher), MatcherKind(MatcherKind) {}
47280031Sdim
48280031Sdim  Kind getArgKind() const { return K; }
49280031Sdim  ast_type_traits::ASTNodeKind getMatcherKind() const {
50280031Sdim    assert(K == AK_Matcher);
51280031Sdim    return MatcherKind;
52280031Sdim  }
53280031Sdim
54280031Sdim  /// \brief Determines if this type can be converted to \p To.
55280031Sdim  ///
56280031Sdim  /// \param To the requested destination type.
57280031Sdim  ///
58280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
59280031Sdim  ///   convertion.
60280031Sdim  bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
61280031Sdim
62280031Sdim  bool operator<(const ArgKind &Other) const {
63280031Sdim    if (K == AK_Matcher && Other.K == AK_Matcher)
64280031Sdim      return MatcherKind < Other.MatcherKind;
65280031Sdim    return K < Other.K;
66280031Sdim  }
67280031Sdim
68280031Sdim  /// \brief String representation of the type.
69280031Sdim  std::string asString() const;
70280031Sdim
71280031Sdimprivate:
72280031Sdim  Kind K;
73280031Sdim  ast_type_traits::ASTNodeKind MatcherKind;
74280031Sdim};
75280031Sdim
76259701Sdimusing ast_matchers::internal::DynTypedMatcher;
77259701Sdim
78259701Sdim/// \brief A variant matcher object.
79259701Sdim///
80259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers
81259701Sdim/// into a single object type.
82259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible
83259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the
84259701Sdim/// appropriate overload when needed.
85259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do:
86259701Sdim///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
87259701Sdim///    to decide which matcher to return. Eg. it contains only a single
88259701Sdim///    matcher, or a polymorphic one with only one overload.
89259701Sdim///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
90259701Sdim///    the underlying matcher(s) can unambiguously return a Matcher<T>.
91259701Sdimclass VariantMatcher {
92259701Sdim  /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
93259701Sdim  class MatcherOps {
94259701Sdim  public:
95280031Sdim    MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
96280031Sdim
97280031Sdim    bool canConstructFrom(const DynTypedMatcher &Matcher,
98280031Sdim                          bool &IsExactMatch) const;
99280031Sdim
100280031Sdim    /// \brief Convert \p Matcher the destination type and return it as a new
101280031Sdim    /// DynTypedMatcher.
102280031Sdim    virtual DynTypedMatcher
103280031Sdim    convertMatcher(const DynTypedMatcher &Matcher) const = 0;
104280031Sdim
105280031Sdim    /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
106280031Sdim    /// Will try to convert each inner matcher to the destination type and
107280031Sdim    /// return llvm::None if it fails to do so.
108280031Sdim    llvm::Optional<DynTypedMatcher>
109280031Sdim    constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
110280031Sdim                              ArrayRef<VariantMatcher> InnerMatchers) const;
111280031Sdim
112280031Sdim  protected:
113288943Sdim    ~MatcherOps() = default;
114280031Sdim
115280031Sdim  private:
116280031Sdim    ast_type_traits::ASTNodeKind NodeKind;
117259701Sdim  };
118259701Sdim
119259701Sdim  /// \brief Payload interface to be specialized by each matcher type.
120259701Sdim  ///
121259701Sdim  /// It follows a similar interface as VariantMatcher itself.
122314564Sdim  class Payload {
123259701Sdim  public:
124314564Sdim    virtual ~Payload();
125259701Sdim    virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
126259701Sdim    virtual std::string getTypeAsString() const = 0;
127280031Sdim    virtual llvm::Optional<DynTypedMatcher>
128280031Sdim    getTypedMatcher(const MatcherOps &Ops) const = 0;
129280031Sdim    virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
130280031Sdim                                 unsigned *Specificity) const = 0;
131259701Sdim  };
132259701Sdim
133259701Sdimpublic:
134259701Sdim  /// \brief A null matcher.
135259701Sdim  VariantMatcher();
136259701Sdim
137259701Sdim  /// \brief Clones the provided matcher.
138259701Sdim  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
139259701Sdim
140259701Sdim  /// \brief Clones the provided matchers.
141259701Sdim  ///
142259701Sdim  /// They should be the result of a polymorphic matcher.
143276479Sdim  static VariantMatcher
144276479Sdim  PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
145259701Sdim
146259701Sdim  /// \brief Creates a 'variadic' operator matcher.
147259701Sdim  ///
148259701Sdim  /// It will bind to the appropriate type on getTypedMatcher<T>().
149280031Sdim  static VariantMatcher
150280031Sdim  VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
151280031Sdim                          std::vector<VariantMatcher> Args);
152259701Sdim
153259701Sdim  /// \brief Makes the matcher the "null" matcher.
154259701Sdim  void reset();
155259701Sdim
156259701Sdim  /// \brief Whether the matcher is null.
157259701Sdim  bool isNull() const { return !Value; }
158259701Sdim
159259701Sdim  /// \brief Return a single matcher, if there is no ambiguity.
160259701Sdim  ///
161259701Sdim  /// \returns the matcher, if there is only one matcher. An empty Optional, if
162259701Sdim  /// the underlying matcher is a polymorphic matcher with more than one
163259701Sdim  /// representation.
164259701Sdim  llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
165259701Sdim
166259701Sdim  /// \brief Determines if the contained matcher can be converted to
167259701Sdim  ///   \c Matcher<T>.
168259701Sdim  ///
169259701Sdim  /// For the Single case, it returns true if it can be converted to
170259701Sdim  /// \c Matcher<T>.
171259701Sdim  /// For the Polymorphic case, it returns true if one, and only one, of the
172259701Sdim  /// overloads can be converted to \c Matcher<T>. If there are more than one
173259701Sdim  /// that can, the result would be ambiguous and false is returned.
174259701Sdim  template <class T>
175259701Sdim  bool hasTypedMatcher() const {
176280031Sdim    if (!Value) return false;
177280031Sdim    return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
178259701Sdim  }
179259701Sdim
180280031Sdim  /// \brief Determines if the contained matcher can be converted to \p Kind.
181280031Sdim  ///
182280031Sdim  /// \param Kind the requested destination type.
183280031Sdim  ///
184280031Sdim  /// \param Specificity value corresponding to the "specificity" of the
185280031Sdim  ///   convertion.
186280031Sdim  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
187280031Sdim                       unsigned *Specificity) const {
188280031Sdim    if (Value)
189280031Sdim      return Value->isConvertibleTo(Kind, Specificity);
190280031Sdim    return false;
191280031Sdim  }
192280031Sdim
193259701Sdim  /// \brief Return this matcher as a \c Matcher<T>.
194259701Sdim  ///
195259701Sdim  /// Handles the different types (Single, Polymorphic) accordingly.
196259701Sdim  /// Asserts that \c hasTypedMatcher<T>() is true.
197259701Sdim  template <class T>
198259701Sdim  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
199280031Sdim    assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
200280031Sdim    return Value->getTypedMatcher(TypedMatcherOps<T>())
201280031Sdim        ->template convertTo<T>();
202259701Sdim  }
203259701Sdim
204259701Sdim  /// \brief String representation of the type of the value.
205259701Sdim  ///
206259701Sdim  /// If the underlying matcher is a polymorphic one, the string will show all
207259701Sdim  /// the types.
208259701Sdim  std::string getTypeAsString() const;
209259701Sdim
210259701Sdimprivate:
211314564Sdim  explicit VariantMatcher(std::shared_ptr<Payload> Value)
212314564Sdim      : Value(std::move(Value)) {}
213259701Sdim
214280031Sdim  template <typename T> struct TypedMatcherOps;
215280031Sdim
216259701Sdim  class SinglePayload;
217259701Sdim  class PolymorphicPayload;
218259701Sdim  class VariadicOpPayload;
219259701Sdim
220314564Sdim  std::shared_ptr<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