1 //===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Polymorphic value type.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/STLExtras.h"
17
18 namespace clang {
19 namespace ast_matchers {
20 namespace dynamic {
21
asString() const22 std::string ArgKind::asString() const {
23 switch (getArgKind()) {
24 case AK_Matcher:
25 return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
26 case AK_Boolean:
27 return "boolean";
28 case AK_Double:
29 return "double";
30 case AK_Unsigned:
31 return "unsigned";
32 case AK_String:
33 return "string";
34 }
35 llvm_unreachable("unhandled ArgKind");
36 }
37
isConvertibleTo(ArgKind To,unsigned * Specificity) const38 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
39 if (K != To.K)
40 return false;
41 if (K != AK_Matcher) {
42 if (Specificity)
43 *Specificity = 1;
44 return true;
45 }
46 unsigned Distance;
47 if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
48 return false;
49
50 if (Specificity)
51 *Specificity = 100 - Distance;
52 return true;
53 }
54
55 bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const56 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
57 bool &IsExactMatch) const {
58 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
59 return Matcher.canConvertTo(NodeKind);
60 }
61
62 llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const63 VariantMatcher::MatcherOps::constructVariadicOperator(
64 DynTypedMatcher::VariadicOperator Op,
65 ArrayRef<VariantMatcher> InnerMatchers) const {
66 std::vector<DynTypedMatcher> DynMatchers;
67 for (const auto &InnerMatcher : InnerMatchers) {
68 // Abort if any of the inner matchers can't be converted to
69 // Matcher<T>.
70 if (!InnerMatcher.Value)
71 return llvm::None;
72 llvm::Optional<DynTypedMatcher> Inner =
73 InnerMatcher.Value->getTypedMatcher(*this);
74 if (!Inner)
75 return llvm::None;
76 DynMatchers.push_back(*Inner);
77 }
78 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
79 }
80
~Payload()81 VariantMatcher::Payload::~Payload() {}
82
83 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
84 public:
SinglePayload(const DynTypedMatcher & Matcher)85 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
86
getSingleMatcher() const87 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
88 return Matcher;
89 }
90
getTypeAsString() const91 std::string getTypeAsString() const override {
92 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
93 .str();
94 }
95
96 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const97 getTypedMatcher(const MatcherOps &Ops) const override {
98 bool Ignore;
99 if (Ops.canConstructFrom(Matcher, Ignore))
100 return Matcher;
101 return llvm::None;
102 }
103
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const104 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
105 return ArgKind(Matcher.getSupportedKind())
106 .isConvertibleTo(Kind, Specificity);
107 }
108
109 private:
110 const DynTypedMatcher Matcher;
111 };
112
113 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
114 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)115 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
116 : Matchers(std::move(MatchersIn)) {}
117
~PolymorphicPayload()118 ~PolymorphicPayload() override {}
119
getSingleMatcher() const120 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
121 if (Matchers.size() != 1)
122 return llvm::Optional<DynTypedMatcher>();
123 return Matchers[0];
124 }
125
getTypeAsString() const126 std::string getTypeAsString() const override {
127 std::string Inner;
128 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
129 if (i != 0)
130 Inner += "|";
131 Inner += Matchers[i].getSupportedKind().asStringRef();
132 }
133 return (Twine("Matcher<") + Inner + ">").str();
134 }
135
136 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const137 getTypedMatcher(const MatcherOps &Ops) const override {
138 bool FoundIsExact = false;
139 const DynTypedMatcher *Found = nullptr;
140 int NumFound = 0;
141 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
142 bool IsExactMatch;
143 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
144 if (Found) {
145 if (FoundIsExact) {
146 assert(!IsExactMatch && "We should not have two exact matches.");
147 continue;
148 }
149 }
150 Found = &Matchers[i];
151 FoundIsExact = IsExactMatch;
152 ++NumFound;
153 }
154 }
155 // We only succeed if we found exactly one, or if we found an exact match.
156 if (Found && (FoundIsExact || NumFound == 1))
157 return *Found;
158 return llvm::None;
159 }
160
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const161 bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
162 unsigned MaxSpecificity = 0;
163 for (const DynTypedMatcher &Matcher : Matchers) {
164 unsigned ThisSpecificity;
165 if (ArgKind(Matcher.getSupportedKind())
166 .isConvertibleTo(Kind, &ThisSpecificity)) {
167 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
168 }
169 }
170 if (Specificity)
171 *Specificity = MaxSpecificity;
172 return MaxSpecificity > 0;
173 }
174
175 const std::vector<DynTypedMatcher> Matchers;
176 };
177
178 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
179 public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)180 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
181 std::vector<VariantMatcher> Args)
182 : Op(Op), Args(std::move(Args)) {}
183
getSingleMatcher() const184 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
185 return llvm::Optional<DynTypedMatcher>();
186 }
187
getTypeAsString() const188 std::string getTypeAsString() const override {
189 std::string Inner;
190 for (size_t i = 0, e = Args.size(); i != e; ++i) {
191 if (i != 0)
192 Inner += "&";
193 Inner += Args[i].getTypeAsString();
194 }
195 return Inner;
196 }
197
198 llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const199 getTypedMatcher(const MatcherOps &Ops) const override {
200 return Ops.constructVariadicOperator(Op, Args);
201 }
202
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const203 bool isConvertibleTo(ASTNodeKind Kind, 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(std::make_shared<SinglePayload>(Matcher));
220 }
221
222 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224 return VariantMatcher(
225 std::make_shared<PolymorphicPayload>(std::move(Matchers)));
226 }
227
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)228 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
229 DynTypedMatcher::VariadicOperator Op,
230 std::vector<VariantMatcher> Args) {
231 return VariantMatcher(
232 std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
233 }
234
getSingleMatcher() const235 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
236 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
237 }
238
reset()239 void VariantMatcher::reset() { Value.reset(); }
240
getTypeAsString() const241 std::string VariantMatcher::getTypeAsString() const {
242 if (Value) return Value->getTypeAsString();
243 return "<Nothing>";
244 }
245
VariantValue(const VariantValue & Other)246 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
247 *this = Other;
248 }
249
VariantValue(bool Boolean)250 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
251 setBoolean(Boolean);
252 }
253
VariantValue(double Double)254 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
255 setDouble(Double);
256 }
257
VariantValue(unsigned Unsigned)258 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
259 setUnsigned(Unsigned);
260 }
261
VariantValue(StringRef String)262 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
263 setString(String);
264 }
265
VariantValue(const VariantMatcher & Matcher)266 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
267 setMatcher(Matcher);
268 }
269
~VariantValue()270 VariantValue::~VariantValue() { reset(); }
271
operator =(const VariantValue & Other)272 VariantValue &VariantValue::operator=(const VariantValue &Other) {
273 if (this == &Other) return *this;
274 reset();
275 switch (Other.Type) {
276 case VT_Boolean:
277 setBoolean(Other.getBoolean());
278 break;
279 case VT_Double:
280 setDouble(Other.getDouble());
281 break;
282 case VT_Unsigned:
283 setUnsigned(Other.getUnsigned());
284 break;
285 case VT_String:
286 setString(Other.getString());
287 break;
288 case VT_Matcher:
289 setMatcher(Other.getMatcher());
290 break;
291 case VT_Nothing:
292 Type = VT_Nothing;
293 break;
294 }
295 return *this;
296 }
297
reset()298 void VariantValue::reset() {
299 switch (Type) {
300 case VT_String:
301 delete Value.String;
302 break;
303 case VT_Matcher:
304 delete Value.Matcher;
305 break;
306 // Cases that do nothing.
307 case VT_Boolean:
308 case VT_Double:
309 case VT_Unsigned:
310 case VT_Nothing:
311 break;
312 }
313 Type = VT_Nothing;
314 }
315
isBoolean() const316 bool VariantValue::isBoolean() const {
317 return Type == VT_Boolean;
318 }
319
getBoolean() const320 bool VariantValue::getBoolean() const {
321 assert(isBoolean());
322 return Value.Boolean;
323 }
324
setBoolean(bool NewValue)325 void VariantValue::setBoolean(bool NewValue) {
326 reset();
327 Type = VT_Boolean;
328 Value.Boolean = NewValue;
329 }
330
isDouble() const331 bool VariantValue::isDouble() const {
332 return Type == VT_Double;
333 }
334
getDouble() const335 double VariantValue::getDouble() const {
336 assert(isDouble());
337 return Value.Double;
338 }
339
setDouble(double NewValue)340 void VariantValue::setDouble(double NewValue) {
341 reset();
342 Type = VT_Double;
343 Value.Double = NewValue;
344 }
345
isUnsigned() const346 bool VariantValue::isUnsigned() const {
347 return Type == VT_Unsigned;
348 }
349
getUnsigned() const350 unsigned VariantValue::getUnsigned() const {
351 assert(isUnsigned());
352 return Value.Unsigned;
353 }
354
setUnsigned(unsigned NewValue)355 void VariantValue::setUnsigned(unsigned NewValue) {
356 reset();
357 Type = VT_Unsigned;
358 Value.Unsigned = NewValue;
359 }
360
isString() const361 bool VariantValue::isString() const {
362 return Type == VT_String;
363 }
364
getString() const365 const std::string &VariantValue::getString() const {
366 assert(isString());
367 return *Value.String;
368 }
369
setString(StringRef NewValue)370 void VariantValue::setString(StringRef NewValue) {
371 reset();
372 Type = VT_String;
373 Value.String = new std::string(NewValue);
374 }
375
isMatcher() const376 bool VariantValue::isMatcher() const {
377 return Type == VT_Matcher;
378 }
379
getMatcher() const380 const VariantMatcher &VariantValue::getMatcher() const {
381 assert(isMatcher());
382 return *Value.Matcher;
383 }
384
setMatcher(const VariantMatcher & NewValue)385 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
386 reset();
387 Type = VT_Matcher;
388 Value.Matcher = new VariantMatcher(NewValue);
389 }
390
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const391 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
392 switch (Kind.getArgKind()) {
393 case ArgKind::AK_Boolean:
394 if (!isBoolean())
395 return false;
396 *Specificity = 1;
397 return true;
398
399 case ArgKind::AK_Double:
400 if (!isDouble())
401 return false;
402 *Specificity = 1;
403 return true;
404
405 case ArgKind::AK_Unsigned:
406 if (!isUnsigned())
407 return false;
408 *Specificity = 1;
409 return true;
410
411 case ArgKind::AK_String:
412 if (!isString())
413 return false;
414 *Specificity = 1;
415 return true;
416
417 case ArgKind::AK_Matcher:
418 if (!isMatcher())
419 return false;
420 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
421 }
422 llvm_unreachable("Invalid Type");
423 }
424
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const425 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
426 unsigned *Specificity) const {
427 unsigned MaxSpecificity = 0;
428 for (const ArgKind& Kind : Kinds) {
429 unsigned ThisSpecificity;
430 if (!isConvertibleTo(Kind, &ThisSpecificity))
431 continue;
432 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
433 }
434 if (Specificity && MaxSpecificity > 0) {
435 *Specificity = MaxSpecificity;
436 }
437 return MaxSpecificity > 0;
438 }
439
getTypeAsString() const440 std::string VariantValue::getTypeAsString() const {
441 switch (Type) {
442 case VT_String: return "String";
443 case VT_Matcher: return getMatcher().getTypeAsString();
444 case VT_Boolean: return "Boolean";
445 case VT_Double: return "Double";
446 case VT_Unsigned: return "Unsigned";
447 case VT_Nothing: return "Nothing";
448 }
449 llvm_unreachable("Invalid Type");
450 }
451
452 } // end namespace dynamic
453 } // end namespace ast_matchers
454 } // end namespace clang
455