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_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
18#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
19
20#include "clang/ASTMatchers/ASTMatchers.h"
21#include "clang/ASTMatchers/ASTMatchersInternal.h"
22#include "llvm/ADT/IntrusiveRefCntPtr.h"
23#include "llvm/ADT/Optional.h"
24#include "llvm/ADT/Twine.h"
25#include <memory>
26#include <vector>
27
28namespace clang {
29namespace ast_matchers {
30namespace dynamic {
31
32using ast_matchers::internal::DynTypedMatcher;
33
34/// \brief A variant matcher object.
35///
36/// The purpose of this object is to abstract simple and polymorphic matchers
37/// into a single object type.
38/// Polymorphic matchers might be implemented as a list of all the possible
39/// overloads of the matcher. \c VariantMatcher knows how to select the
40/// appropriate overload when needed.
41/// To get a real matcher object out of a \c VariantMatcher you can do:
42///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
43///    to decide which matcher to return. Eg. it contains only a single
44///    matcher, or a polymorphic one with only one overload.
45///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
46///    the underlying matcher(s) can unambiguously return a Matcher<T>.
47class VariantMatcher {
48  /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
49  class MatcherOps {
50  public:
51    virtual ~MatcherOps();
52    virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
53                                  bool &IsExactMatch) const = 0;
54    virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
55    virtual void constructVariadicOperator(
56        ast_matchers::internal::VariadicOperatorFunction Func,
57        ArrayRef<VariantMatcher> InnerMatchers) = 0;
58  };
59
60  /// \brief Payload interface to be specialized by each matcher type.
61  ///
62  /// It follows a similar interface as VariantMatcher itself.
63  class Payload : public RefCountedBaseVPTR {
64  public:
65    virtual ~Payload();
66    virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
67    virtual std::string getTypeAsString() const = 0;
68    virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
69  };
70
71public:
72  /// \brief A null matcher.
73  VariantMatcher();
74
75  /// \brief Clones the provided matcher.
76  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
77
78  /// \brief Clones the provided matchers.
79  ///
80  /// They should be the result of a polymorphic matcher.
81  static VariantMatcher
82  PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
83
84  /// \brief Creates a 'variadic' operator matcher.
85  ///
86  /// It will bind to the appropriate type on getTypedMatcher<T>().
87  static VariantMatcher VariadicOperatorMatcher(
88      ast_matchers::internal::VariadicOperatorFunction Func,
89      std::vector<VariantMatcher> Args);
90
91  /// \brief Makes the matcher the "null" matcher.
92  void reset();
93
94  /// \brief Whether the matcher is null.
95  bool isNull() const { return !Value; }
96
97  /// \brief Return a single matcher, if there is no ambiguity.
98  ///
99  /// \returns the matcher, if there is only one matcher. An empty Optional, if
100  /// the underlying matcher is a polymorphic matcher with more than one
101  /// representation.
102  llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
103
104  /// \brief Determines if the contained matcher can be converted to
105  ///   \c Matcher<T>.
106  ///
107  /// For the Single case, it returns true if it can be converted to
108  /// \c Matcher<T>.
109  /// For the Polymorphic case, it returns true if one, and only one, of the
110  /// overloads can be converted to \c Matcher<T>. If there are more than one
111  /// that can, the result would be ambiguous and false is returned.
112  template <class T>
113  bool hasTypedMatcher() const {
114    TypedMatcherOps<T> Ops;
115    if (Value) Value->makeTypedMatcher(Ops);
116    return Ops.hasMatcher();
117  }
118
119  /// \brief Return this matcher as a \c Matcher<T>.
120  ///
121  /// Handles the different types (Single, Polymorphic) accordingly.
122  /// Asserts that \c hasTypedMatcher<T>() is true.
123  template <class T>
124  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
125    TypedMatcherOps<T> Ops;
126    Value->makeTypedMatcher(Ops);
127    assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
128    return Ops.matcher();
129  }
130
131  /// \brief String representation of the type of the value.
132  ///
133  /// If the underlying matcher is a polymorphic one, the string will show all
134  /// the types.
135  std::string getTypeAsString() const;
136
137private:
138  explicit VariantMatcher(Payload *Value) : Value(Value) {}
139
140  class SinglePayload;
141  class PolymorphicPayload;
142  class VariadicOpPayload;
143
144  template <typename T>
145  class TypedMatcherOps : public MatcherOps {
146  public:
147    typedef ast_matchers::internal::Matcher<T> MatcherT;
148
149    virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
150                                  bool &IsExactMatch) const {
151      IsExactMatch = Matcher.getSupportedKind().isSame(
152          ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
153      return Matcher.canConvertTo<T>();
154    }
155
156    virtual void constructFrom(const DynTypedMatcher& Matcher) {
157      Out.reset(new MatcherT(Matcher.convertTo<T>()));
158    }
159
160    virtual void constructVariadicOperator(
161        ast_matchers::internal::VariadicOperatorFunction Func,
162        ArrayRef<VariantMatcher> InnerMatchers) {
163      std::vector<DynTypedMatcher> DynMatchers;
164      for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
165        // Abort if any of the inner matchers can't be converted to
166        // Matcher<T>.
167        if (!InnerMatchers[i].hasTypedMatcher<T>()) {
168          return;
169        }
170        DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>());
171      }
172      Out.reset(new MatcherT(
173          new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
174              Func, DynMatchers)));
175    }
176
177    bool hasMatcher() const { return Out.get() != nullptr; }
178    const MatcherT &matcher() const { return *Out; }
179
180  private:
181    std::unique_ptr<MatcherT> Out;
182  };
183
184  IntrusiveRefCntPtr<const Payload> Value;
185};
186
187/// \brief Variant value class.
188///
189/// Basically, a tagged union with value type semantics.
190/// It is used by the registry as the return value and argument type for the
191/// matcher factory methods.
192/// It can be constructed from any of the supported types. It supports
193/// copy/assignment.
194///
195/// Supported types:
196///  - \c unsigned
197///  - \c std::string
198///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
199class VariantValue {
200public:
201  VariantValue() : Type(VT_Nothing) {}
202
203  VariantValue(const VariantValue &Other);
204  ~VariantValue();
205  VariantValue &operator=(const VariantValue &Other);
206
207  /// \brief Specific constructors for each supported type.
208  VariantValue(unsigned Unsigned);
209  VariantValue(const std::string &String);
210  VariantValue(const VariantMatcher &Matchers);
211
212  /// \brief Returns true iff this is not an empty value.
213  LLVM_EXPLICIT operator bool() const { return hasValue(); }
214  bool hasValue() const { return Type != VT_Nothing; }
215
216  /// \brief Unsigned value functions.
217  bool isUnsigned() const;
218  unsigned getUnsigned() const;
219  void setUnsigned(unsigned Unsigned);
220
221  /// \brief String value functions.
222  bool isString() const;
223  const std::string &getString() const;
224  void setString(const std::string &String);
225
226  /// \brief Matcher value functions.
227  bool isMatcher() const;
228  const VariantMatcher &getMatcher() const;
229  void setMatcher(const VariantMatcher &Matcher);
230
231  /// \brief String representation of the type of the value.
232  std::string getTypeAsString() const;
233
234private:
235  void reset();
236
237  /// \brief All supported value types.
238  enum ValueType {
239    VT_Nothing,
240    VT_Unsigned,
241    VT_String,
242    VT_Matcher
243  };
244
245  /// \brief All supported value types.
246  union AllValues {
247    unsigned Unsigned;
248    std::string *String;
249    VariantMatcher *Matcher;
250  };
251
252  ValueType Type;
253  AllValues Value;
254};
255
256} // end namespace dynamic
257} // end namespace ast_matchers
258} // end namespace clang
259
260#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
261