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