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
asString() const23 std::string ArgKind::asString() const {
24 switch (getArgKind()) {
25 case AK_Matcher:
26 return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
27 case AK_Unsigned:
28 return "unsigned";
29 case AK_String:
30 return "string";
31 }
32 llvm_unreachable("unhandled ArgKind");
33 }
34
isConvertibleTo(ArgKind To,unsigned * Specificity) const35 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
36 if (K != To.K)
37 return false;
38 if (K != AK_Matcher) {
39 if (Specificity)
40 *Specificity = 1;
41 return true;
42 }
43 unsigned Distance;
44 if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
45 return false;
46
47 if (Specificity)
48 *Specificity = 100 - Distance;
49 return true;
50 }
51
52 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const53 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54 bool &IsExactMatch) const {
55 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56 return Matcher.canConvertTo(NodeKind);
57 }
58
59 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const60 VariantMatcher::MatcherOps::constructVariadicOperator(
61 DynTypedMatcher::VariadicOperator Op,
62 ArrayRef<VariantMatcher> InnerMatchers) const {
63 std::vector<DynTypedMatcher> DynMatchers;
64 for (const auto &InnerMatcher : InnerMatchers) {
65 // Abort if any of the inner matchers can't be converted to
66 // Matcher<T>.
67 if (!InnerMatcher.Value)
68 return llvm::None;
69 llvm::Optional<DynTypedMatcher> Inner =
70 InnerMatcher.Value->getTypedMatcher(*this);
71 if (!Inner)
72 return llvm::None;
73 DynMatchers.push_back(*Inner);
74 }
75 return DynTypedMatcher::constructVariadic(Op, DynMatchers);
76 }
77
~Payload()78 VariantMatcher::Payload::~Payload() {}
79
80 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81 public:
SinglePayload(const DynTypedMatcher & Matcher)82 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
83
getSingleMatcher() const84 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
85 return Matcher;
86 }
87
getTypeAsString() const88 std::string getTypeAsString() const override {
89 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
90 .str();
91 }
92
93 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const94 getTypedMatcher(const MatcherOps &Ops) const override {
95 bool Ignore;
96 if (Ops.canConstructFrom(Matcher, Ignore))
97 return Matcher;
98 return llvm::None;
99 }
100
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const101 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
102 unsigned *Specificity) const override {
103 return ArgKind(Matcher.getSupportedKind())
104 .isConvertibleTo(Kind, Specificity);
105 }
106
107 private:
108 const DynTypedMatcher Matcher;
109 };
110
111 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)113 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114 : Matchers(std::move(MatchersIn)) {}
115
~PolymorphicPayload()116 ~PolymorphicPayload() override {}
117
getSingleMatcher() const118 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
119 if (Matchers.size() != 1)
120 return llvm::Optional<DynTypedMatcher>();
121 return Matchers[0];
122 }
123
getTypeAsString() const124 std::string getTypeAsString() const override {
125 std::string Inner;
126 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127 if (i != 0)
128 Inner += "|";
129 Inner += Matchers[i].getSupportedKind().asStringRef();
130 }
131 return (Twine("Matcher<") + Inner + ">").str();
132 }
133
134 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const135 getTypedMatcher(const MatcherOps &Ops) const override {
136 bool FoundIsExact = false;
137 const DynTypedMatcher *Found = nullptr;
138 int NumFound = 0;
139 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
140 bool IsExactMatch;
141 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
142 if (Found) {
143 if (FoundIsExact) {
144 assert(!IsExactMatch && "We should not have two exact matches.");
145 continue;
146 }
147 }
148 Found = &Matchers[i];
149 FoundIsExact = IsExactMatch;
150 ++NumFound;
151 }
152 }
153 // We only succeed if we found exactly one, or if we found an exact match.
154 if (Found && (FoundIsExact || NumFound == 1))
155 return *Found;
156 return llvm::None;
157 }
158
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const159 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
160 unsigned *Specificity) const override {
161 unsigned MaxSpecificity = 0;
162 for (const DynTypedMatcher &Matcher : Matchers) {
163 unsigned ThisSpecificity;
164 if (ArgKind(Matcher.getSupportedKind())
165 .isConvertibleTo(Kind, &ThisSpecificity)) {
166 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
167 }
168 }
169 if (Specificity)
170 *Specificity = MaxSpecificity;
171 return MaxSpecificity > 0;
172 }
173
174 const std::vector<DynTypedMatcher> Matchers;
175 };
176
177 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)179 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
180 std::vector<VariantMatcher> Args)
181 : Op(Op), Args(std::move(Args)) {}
182
getSingleMatcher() const183 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
184 return llvm::Optional<DynTypedMatcher>();
185 }
186
getTypeAsString() const187 std::string getTypeAsString() const override {
188 std::string Inner;
189 for (size_t i = 0, e = Args.size(); i != e; ++i) {
190 if (i != 0)
191 Inner += "&";
192 Inner += Args[i].getTypeAsString();
193 }
194 return Inner;
195 }
196
197 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const198 getTypedMatcher(const MatcherOps &Ops) const override {
199 return Ops.constructVariadicOperator(Op, Args);
200 }
201
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const202 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
203 unsigned *Specificity) const override {
204 for (const VariantMatcher &Matcher : Args) {
205 if (!Matcher.isConvertibleTo(Kind, Specificity))
206 return false;
207 }
208 return true;
209 }
210
211 private:
212 const DynTypedMatcher::VariadicOperator Op;
213 const std::vector<VariantMatcher> Args;
214 };
215
VariantMatcher()216 VariantMatcher::VariantMatcher() {}
217
SingleMatcher(const DynTypedMatcher & Matcher)218 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
219 return VariantMatcher(new SinglePayload(Matcher));
220 }
221
222 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
225 }
226
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)227 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
228 DynTypedMatcher::VariadicOperator Op,
229 std::vector<VariantMatcher> Args) {
230 return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
231 }
232
getSingleMatcher() const233 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
234 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
235 }
236
reset()237 void VariantMatcher::reset() { Value.reset(); }
238
getTypeAsString() const239 std::string VariantMatcher::getTypeAsString() const {
240 if (Value) return Value->getTypeAsString();
241 return "<Nothing>";
242 }
243
VariantValue(const VariantValue & Other)244 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245 *this = Other;
246 }
247
VariantValue(unsigned Unsigned)248 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249 setUnsigned(Unsigned);
250 }
251
VariantValue(const std::string & String)252 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
253 setString(String);
254 }
255
VariantValue(const VariantMatcher & Matcher)256 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257 setMatcher(Matcher);
258 }
259
~VariantValue()260 VariantValue::~VariantValue() { reset(); }
261
operator =(const VariantValue & Other)262 VariantValue &VariantValue::operator=(const VariantValue &Other) {
263 if (this == &Other) return *this;
264 reset();
265 switch (Other.Type) {
266 case VT_Unsigned:
267 setUnsigned(Other.getUnsigned());
268 break;
269 case VT_String:
270 setString(Other.getString());
271 break;
272 case VT_Matcher:
273 setMatcher(Other.getMatcher());
274 break;
275 case VT_Nothing:
276 Type = VT_Nothing;
277 break;
278 }
279 return *this;
280 }
281
reset()282 void VariantValue::reset() {
283 switch (Type) {
284 case VT_String:
285 delete Value.String;
286 break;
287 case VT_Matcher:
288 delete Value.Matcher;
289 break;
290 // Cases that do nothing.
291 case VT_Unsigned:
292 case VT_Nothing:
293 break;
294 }
295 Type = VT_Nothing;
296 }
297
isUnsigned() const298 bool VariantValue::isUnsigned() const {
299 return Type == VT_Unsigned;
300 }
301
getUnsigned() const302 unsigned VariantValue::getUnsigned() const {
303 assert(isUnsigned());
304 return Value.Unsigned;
305 }
306
setUnsigned(unsigned NewValue)307 void VariantValue::setUnsigned(unsigned NewValue) {
308 reset();
309 Type = VT_Unsigned;
310 Value.Unsigned = NewValue;
311 }
312
isString() const313 bool VariantValue::isString() const {
314 return Type == VT_String;
315 }
316
getString() const317 const std::string &VariantValue::getString() const {
318 assert(isString());
319 return *Value.String;
320 }
321
setString(const std::string & NewValue)322 void VariantValue::setString(const std::string &NewValue) {
323 reset();
324 Type = VT_String;
325 Value.String = new std::string(NewValue);
326 }
327
isMatcher() const328 bool VariantValue::isMatcher() const {
329 return Type == VT_Matcher;
330 }
331
getMatcher() const332 const VariantMatcher &VariantValue::getMatcher() const {
333 assert(isMatcher());
334 return *Value.Matcher;
335 }
336
setMatcher(const VariantMatcher & NewValue)337 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
338 reset();
339 Type = VT_Matcher;
340 Value.Matcher = new VariantMatcher(NewValue);
341 }
342
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const343 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344 switch (Kind.getArgKind()) {
345 case ArgKind::AK_Unsigned:
346 if (!isUnsigned())
347 return false;
348 *Specificity = 1;
349 return true;
350
351 case ArgKind::AK_String:
352 if (!isString())
353 return false;
354 *Specificity = 1;
355 return true;
356
357 case ArgKind::AK_Matcher:
358 if (!isMatcher())
359 return false;
360 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
361 }
362 llvm_unreachable("Invalid Type");
363 }
364
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const365 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
366 unsigned *Specificity) const {
367 unsigned MaxSpecificity = 0;
368 for (const ArgKind& Kind : Kinds) {
369 unsigned ThisSpecificity;
370 if (!isConvertibleTo(Kind, &ThisSpecificity))
371 continue;
372 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
373 }
374 if (Specificity && MaxSpecificity > 0) {
375 *Specificity = MaxSpecificity;
376 }
377 return MaxSpecificity > 0;
378 }
379
getTypeAsString() const380 std::string VariantValue::getTypeAsString() const {
381 switch (Type) {
382 case VT_String: return "String";
383 case VT_Matcher: return getMatcher().getTypeAsString();
384 case VT_Unsigned: return "Unsigned";
385 case VT_Nothing: return "Nothing";
386 }
387 llvm_unreachable("Invalid Type");
388 }
389
390 } // end namespace dynamic
391 } // end namespace ast_matchers
392 } // end namespace clang
393