1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Polymorphic value type.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/STLExtras.h"
18 
19 namespace clang {
20 namespace ast_matchers {
21 namespace dynamic {
22 
23 VariantMatcher::MatcherOps::~MatcherOps() {}
24 VariantMatcher::Payload::~Payload() {}
25 
26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
27 public:
28   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
29 
30   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
31     return Matcher;
32   }
33 
34   virtual std::string getTypeAsString() const {
35     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
36         .str();
37   }
38 
39   virtual void makeTypedMatcher(MatcherOps &Ops) const {
40     if (Ops.canConstructFrom(Matcher))
41       Ops.constructFrom(Matcher);
42   }
43 
44 private:
45   const DynTypedMatcher Matcher;
46 };
47 
48 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
49 public:
50   PolymorphicPayload(ArrayRef<DynTypedMatcher> MatchersIn)
51       : Matchers(MatchersIn) {}
52 
53   virtual ~PolymorphicPayload() {}
54 
55   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
56     if (Matchers.size() != 1)
57       return llvm::Optional<DynTypedMatcher>();
58     return Matchers[0];
59   }
60 
61   virtual std::string getTypeAsString() const {
62     std::string Inner;
63     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
64       if (i != 0)
65         Inner += "|";
66       Inner += Matchers[i].getSupportedKind().asStringRef();
67     }
68     return (Twine("Matcher<") + Inner + ">").str();
69   }
70 
71   virtual void makeTypedMatcher(MatcherOps &Ops) const {
72     const DynTypedMatcher *Found = NULL;
73     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
74       if (Ops.canConstructFrom(Matchers[i])) {
75         if (Found)
76           return;
77         Found = &Matchers[i];
78       }
79     }
80     if (Found)
81       Ops.constructFrom(*Found);
82   }
83 
84   const std::vector<DynTypedMatcher> Matchers;
85 };
86 
87 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
88 public:
89   VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
90                     ArrayRef<VariantMatcher> Args)
91       : Func(Func), Args(Args) {}
92 
93   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
94     return llvm::Optional<DynTypedMatcher>();
95   }
96 
97   virtual std::string getTypeAsString() const {
98     std::string Inner;
99     for (size_t i = 0, e = Args.size(); i != e; ++i) {
100       if (i != 0)
101         Inner += "&";
102       Inner += Args[i].getTypeAsString();
103     }
104     return Inner;
105   }
106 
107   virtual void makeTypedMatcher(MatcherOps &Ops) const {
108     Ops.constructVariadicOperator(Func, Args);
109   }
110 
111 private:
112   const ast_matchers::internal::VariadicOperatorFunction Func;
113   const std::vector<VariantMatcher> Args;
114 };
115 
116 VariantMatcher::VariantMatcher() {}
117 
118 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
119   return VariantMatcher(new SinglePayload(Matcher));
120 }
121 
122 VariantMatcher
123 VariantMatcher::PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers) {
124   return VariantMatcher(new PolymorphicPayload(Matchers));
125 }
126 
127 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
128     ast_matchers::internal::VariadicOperatorFunction Func,
129     ArrayRef<VariantMatcher> Args) {
130   return VariantMatcher(new VariadicOpPayload(Func, Args));
131 }
132 
133 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
134   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
135 }
136 
137 void VariantMatcher::reset() { Value.reset(); }
138 
139 std::string VariantMatcher::getTypeAsString() const {
140   if (Value) return Value->getTypeAsString();
141   return "<Nothing>";
142 }
143 
144 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
145   *this = Other;
146 }
147 
148 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
149   setUnsigned(Unsigned);
150 }
151 
152 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
153   setString(String);
154 }
155 
156 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
157   setMatcher(Matcher);
158 }
159 
160 VariantValue::~VariantValue() { reset(); }
161 
162 VariantValue &VariantValue::operator=(const VariantValue &Other) {
163   if (this == &Other) return *this;
164   reset();
165   switch (Other.Type) {
166   case VT_Unsigned:
167     setUnsigned(Other.getUnsigned());
168     break;
169   case VT_String:
170     setString(Other.getString());
171     break;
172   case VT_Matcher:
173     setMatcher(Other.getMatcher());
174     break;
175   case VT_Nothing:
176     Type = VT_Nothing;
177     break;
178   }
179   return *this;
180 }
181 
182 void VariantValue::reset() {
183   switch (Type) {
184   case VT_String:
185     delete Value.String;
186     break;
187   case VT_Matcher:
188     delete Value.Matcher;
189     break;
190   // Cases that do nothing.
191   case VT_Unsigned:
192   case VT_Nothing:
193     break;
194   }
195   Type = VT_Nothing;
196 }
197 
198 bool VariantValue::isUnsigned() const {
199   return Type == VT_Unsigned;
200 }
201 
202 unsigned VariantValue::getUnsigned() const {
203   assert(isUnsigned());
204   return Value.Unsigned;
205 }
206 
207 void VariantValue::setUnsigned(unsigned NewValue) {
208   reset();
209   Type = VT_Unsigned;
210   Value.Unsigned = NewValue;
211 }
212 
213 bool VariantValue::isString() const {
214   return Type == VT_String;
215 }
216 
217 const std::string &VariantValue::getString() const {
218   assert(isString());
219   return *Value.String;
220 }
221 
222 void VariantValue::setString(const std::string &NewValue) {
223   reset();
224   Type = VT_String;
225   Value.String = new std::string(NewValue);
226 }
227 
228 bool VariantValue::isMatcher() const {
229   return Type == VT_Matcher;
230 }
231 
232 const VariantMatcher &VariantValue::getMatcher() const {
233   assert(isMatcher());
234   return *Value.Matcher;
235 }
236 
237 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
238   reset();
239   Type = VT_Matcher;
240   Value.Matcher = new VariantMatcher(NewValue);
241 }
242 
243 std::string VariantValue::getTypeAsString() const {
244   switch (Type) {
245   case VT_String: return "String";
246   case VT_Matcher: return getMatcher().getTypeAsString();
247   case VT_Unsigned: return "Unsigned";
248   case VT_Nothing: return "Nothing";
249   }
250   llvm_unreachable("Invalid Type");
251 }
252 
253 } // end namespace dynamic
254 } // end namespace ast_matchers
255 } // end namespace clang
256