• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 namespace clang {
29 namespace ast_matchers {
30 namespace dynamic {
31 
32 using 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>.
47 class 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 
71 public:
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.
isNull()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>
hasTypedMatcher()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>
getTypedMatcher()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 
137 private:
VariantMatcher(Payload * Value)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 
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch)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 
constructFrom(const DynTypedMatcher & Matcher)156     virtual void constructFrom(const DynTypedMatcher& Matcher) {
157       Out.reset(new MatcherT(Matcher.convertTo<T>()));
158     }
159 
constructVariadicOperator(ast_matchers::internal::VariadicOperatorFunction Func,ArrayRef<VariantMatcher> InnerMatchers)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 
hasMatcher()177     bool hasMatcher() const { return Out.get() != nullptr; }
matcher()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>)
199 class VariantValue {
200 public:
VariantValue()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(); }
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 
234 private:
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