VariantValue.h revision 259701
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
17259701Sdim#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
18259701Sdim#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
19259701Sdim
20259701Sdim#include <vector>
21259701Sdim
22259701Sdim#include "clang/ASTMatchers/ASTMatchers.h"
23259701Sdim#include "clang/ASTMatchers/ASTMatchersInternal.h"
24259701Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h"
25259701Sdim#include "llvm/ADT/Optional.h"
26259701Sdim#include "llvm/ADT/Twine.h"
27259701Sdim#include "llvm/Support/type_traits.h"
28259701Sdim
29259701Sdimnamespace clang {
30259701Sdimnamespace ast_matchers {
31259701Sdimnamespace dynamic {
32259701Sdim
33259701Sdimusing ast_matchers::internal::DynTypedMatcher;
34259701Sdim
35259701Sdim/// \brief A variant matcher object.
36259701Sdim///
37259701Sdim/// The purpose of this object is to abstract simple and polymorphic matchers
38259701Sdim/// into a single object type.
39259701Sdim/// Polymorphic matchers might be implemented as a list of all the possible
40259701Sdim/// overloads of the matcher. \c VariantMatcher knows how to select the
41259701Sdim/// appropriate overload when needed.
42259701Sdim/// To get a real matcher object out of a \c VariantMatcher you can do:
43259701Sdim///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
44259701Sdim///    to decide which matcher to return. Eg. it contains only a single
45259701Sdim///    matcher, or a polymorphic one with only one overload.
46259701Sdim///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
47259701Sdim///    the underlying matcher(s) can unambiguously return a Matcher<T>.
48259701Sdimclass VariantMatcher {
49259701Sdim  /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
50259701Sdim  class MatcherOps {
51259701Sdim  public:
52259701Sdim    virtual ~MatcherOps();
53259701Sdim    virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0;
54259701Sdim    virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
55259701Sdim    virtual void constructVariadicOperator(
56259701Sdim        ast_matchers::internal::VariadicOperatorFunction Func,
57259701Sdim        ArrayRef<VariantMatcher> InnerMatchers) = 0;
58259701Sdim  };
59259701Sdim
60259701Sdim  /// \brief Payload interface to be specialized by each matcher type.
61259701Sdim  ///
62259701Sdim  /// It follows a similar interface as VariantMatcher itself.
63259701Sdim  class Payload : public RefCountedBaseVPTR {
64259701Sdim  public:
65259701Sdim    virtual ~Payload();
66259701Sdim    virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
67259701Sdim    virtual std::string getTypeAsString() const = 0;
68259701Sdim    virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
69259701Sdim  };
70259701Sdim
71259701Sdimpublic:
72259701Sdim  /// \brief A null matcher.
73259701Sdim  VariantMatcher();
74259701Sdim
75259701Sdim  /// \brief Clones the provided matcher.
76259701Sdim  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
77259701Sdim
78259701Sdim  /// \brief Clones the provided matchers.
79259701Sdim  ///
80259701Sdim  /// They should be the result of a polymorphic matcher.
81259701Sdim  static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
82259701Sdim
83259701Sdim  /// \brief Creates a 'variadic' operator matcher.
84259701Sdim  ///
85259701Sdim  /// It will bind to the appropriate type on getTypedMatcher<T>().
86259701Sdim  static VariantMatcher VariadicOperatorMatcher(
87259701Sdim      ast_matchers::internal::VariadicOperatorFunction Func,
88259701Sdim      ArrayRef<VariantMatcher> Args);
89259701Sdim
90259701Sdim  /// \brief Makes the matcher the "null" matcher.
91259701Sdim  void reset();
92259701Sdim
93259701Sdim  /// \brief Whether the matcher is null.
94259701Sdim  bool isNull() const { return !Value; }
95259701Sdim
96259701Sdim  /// \brief Return a single matcher, if there is no ambiguity.
97259701Sdim  ///
98259701Sdim  /// \returns the matcher, if there is only one matcher. An empty Optional, if
99259701Sdim  /// the underlying matcher is a polymorphic matcher with more than one
100259701Sdim  /// representation.
101259701Sdim  llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
102259701Sdim
103259701Sdim  /// \brief Determines if the contained matcher can be converted to
104259701Sdim  ///   \c Matcher<T>.
105259701Sdim  ///
106259701Sdim  /// For the Single case, it returns true if it can be converted to
107259701Sdim  /// \c Matcher<T>.
108259701Sdim  /// For the Polymorphic case, it returns true if one, and only one, of the
109259701Sdim  /// overloads can be converted to \c Matcher<T>. If there are more than one
110259701Sdim  /// that can, the result would be ambiguous and false is returned.
111259701Sdim  template <class T>
112259701Sdim  bool hasTypedMatcher() const {
113259701Sdim    TypedMatcherOps<T> Ops;
114259701Sdim    if (Value) Value->makeTypedMatcher(Ops);
115259701Sdim    return Ops.hasMatcher();
116259701Sdim  }
117259701Sdim
118259701Sdim  /// \brief Return this matcher as a \c Matcher<T>.
119259701Sdim  ///
120259701Sdim  /// Handles the different types (Single, Polymorphic) accordingly.
121259701Sdim  /// Asserts that \c hasTypedMatcher<T>() is true.
122259701Sdim  template <class T>
123259701Sdim  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
124259701Sdim    TypedMatcherOps<T> Ops;
125259701Sdim    Value->makeTypedMatcher(Ops);
126259701Sdim    assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
127259701Sdim    return Ops.matcher();
128259701Sdim  }
129259701Sdim
130259701Sdim  /// \brief String representation of the type of the value.
131259701Sdim  ///
132259701Sdim  /// If the underlying matcher is a polymorphic one, the string will show all
133259701Sdim  /// the types.
134259701Sdim  std::string getTypeAsString() const;
135259701Sdim
136259701Sdimprivate:
137259701Sdim  explicit VariantMatcher(Payload *Value) : Value(Value) {}
138259701Sdim
139259701Sdim  class SinglePayload;
140259701Sdim  class PolymorphicPayload;
141259701Sdim  class VariadicOpPayload;
142259701Sdim
143259701Sdim  template <typename T>
144259701Sdim  class TypedMatcherOps : public MatcherOps {
145259701Sdim  public:
146259701Sdim    typedef ast_matchers::internal::Matcher<T> MatcherT;
147259701Sdim
148259701Sdim    virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const {
149259701Sdim      return Matcher.canConvertTo<T>();
150259701Sdim    }
151259701Sdim
152259701Sdim    virtual void constructFrom(const DynTypedMatcher& Matcher) {
153259701Sdim      Out.reset(new MatcherT(Matcher.convertTo<T>()));
154259701Sdim    }
155259701Sdim
156259701Sdim    virtual void constructVariadicOperator(
157259701Sdim        ast_matchers::internal::VariadicOperatorFunction Func,
158259701Sdim        ArrayRef<VariantMatcher> InnerMatchers) {
159259701Sdim      const size_t NumArgs = InnerMatchers.size();
160259701Sdim      MatcherT **InnerArgs = new MatcherT *[NumArgs]();
161259701Sdim      bool HasError = false;
162259701Sdim      for (size_t i = 0; i != NumArgs; ++i) {
163259701Sdim        // Abort if any of the inner matchers can't be converted to
164259701Sdim        // Matcher<T>.
165259701Sdim        if (!InnerMatchers[i].hasTypedMatcher<T>()) {
166259701Sdim          HasError = true;
167259701Sdim          break;
168259701Sdim        }
169259701Sdim        InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>());
170259701Sdim      }
171259701Sdim      if (!HasError) {
172259701Sdim        Out.reset(new MatcherT(
173259701Sdim            new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
174259701Sdim                Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
175259701Sdim      }
176259701Sdim      for (size_t i = 0; i != NumArgs; ++i) {
177259701Sdim        delete InnerArgs[i];
178259701Sdim      }
179259701Sdim      delete[] InnerArgs;
180259701Sdim    }
181259701Sdim
182259701Sdim    bool hasMatcher() const { return Out.get() != NULL; }
183259701Sdim    const MatcherT &matcher() const { return *Out; }
184259701Sdim
185259701Sdim  private:
186259701Sdim    OwningPtr<MatcherT> Out;
187259701Sdim  };
188259701Sdim
189259701Sdim  IntrusiveRefCntPtr<const Payload> Value;
190259701Sdim};
191259701Sdim
192259701Sdim/// \brief Variant value class.
193259701Sdim///
194259701Sdim/// Basically, a tagged union with value type semantics.
195259701Sdim/// It is used by the registry as the return value and argument type for the
196259701Sdim/// matcher factory methods.
197259701Sdim/// It can be constructed from any of the supported types. It supports
198259701Sdim/// copy/assignment.
199259701Sdim///
200259701Sdim/// Supported types:
201259701Sdim///  - \c unsigned
202259701Sdim///  - \c std::string
203259701Sdim///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
204259701Sdimclass VariantValue {
205259701Sdimpublic:
206259701Sdim  VariantValue() : Type(VT_Nothing) {}
207259701Sdim
208259701Sdim  VariantValue(const VariantValue &Other);
209259701Sdim  ~VariantValue();
210259701Sdim  VariantValue &operator=(const VariantValue &Other);
211259701Sdim
212259701Sdim  /// \brief Specific constructors for each supported type.
213259701Sdim  VariantValue(unsigned Unsigned);
214259701Sdim  VariantValue(const std::string &String);
215259701Sdim  VariantValue(const VariantMatcher &Matchers);
216259701Sdim
217259701Sdim  /// \brief Unsigned value functions.
218259701Sdim  bool isUnsigned() const;
219259701Sdim  unsigned getUnsigned() const;
220259701Sdim  void setUnsigned(unsigned Unsigned);
221259701Sdim
222259701Sdim  /// \brief String value functions.
223259701Sdim  bool isString() const;
224259701Sdim  const std::string &getString() const;
225259701Sdim  void setString(const std::string &String);
226259701Sdim
227259701Sdim  /// \brief Matcher value functions.
228259701Sdim  bool isMatcher() const;
229259701Sdim  const VariantMatcher &getMatcher() const;
230259701Sdim  void setMatcher(const VariantMatcher &Matcher);
231259701Sdim
232259701Sdim  /// \brief String representation of the type of the value.
233259701Sdim  std::string getTypeAsString() const;
234259701Sdim
235259701Sdimprivate:
236259701Sdim  void reset();
237259701Sdim
238259701Sdim  /// \brief All supported value types.
239259701Sdim  enum ValueType {
240259701Sdim    VT_Nothing,
241259701Sdim    VT_Unsigned,
242259701Sdim    VT_String,
243259701Sdim    VT_Matcher
244259701Sdim  };
245259701Sdim
246259701Sdim  /// \brief All supported value types.
247259701Sdim  union AllValues {
248259701Sdim    unsigned Unsigned;
249259701Sdim    std::string *String;
250259701Sdim    VariantMatcher *Matcher;
251259701Sdim  };
252259701Sdim
253259701Sdim  ValueType Type;
254259701Sdim  AllValues Value;
255259701Sdim};
256259701Sdim
257259701Sdim} // end namespace dynamic
258259701Sdim} // end namespace ast_matchers
259259701Sdim} // end namespace clang
260259701Sdim
261259701Sdim#endif  // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
262