/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
22 | 129 | std::string ArgKind::asString() const { |
23 | 129 | switch (getArgKind()) { |
24 | 7 | case AK_Matcher: |
25 | 7 | return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str(); |
26 | 27 | case AK_Node: |
27 | 27 | return NodeKind.asStringRef().str(); |
28 | 4 | case AK_Boolean: |
29 | 4 | return "boolean"; |
30 | 4 | case AK_Double: |
31 | 4 | return "double"; |
32 | 10 | case AK_Unsigned: |
33 | 10 | return "unsigned"; |
34 | 77 | case AK_String: |
35 | 77 | return "string"; |
36 | 129 | } |
37 | 0 | llvm_unreachable("unhandled ArgKind"); |
38 | 0 | } |
39 | | |
40 | 27.4k | bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const { |
41 | 27.4k | if (K != To.K) |
42 | 0 | return false; |
43 | 27.4k | if (K != AK_Matcher && K != AK_Node0 ) { |
44 | 0 | if (Specificity) |
45 | 0 | *Specificity = 1; |
46 | 0 | return true; |
47 | 0 | } |
48 | 27.4k | unsigned Distance; |
49 | 27.4k | if (!NodeKind.isBaseOf(To.NodeKind, &Distance)) |
50 | 24.2k | return false; |
51 | | |
52 | 3.16k | if (Specificity) |
53 | 1.81k | *Specificity = 100 - Distance; |
54 | 3.16k | return true; |
55 | 27.4k | } |
56 | | |
57 | | bool |
58 | | VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher, |
59 | 621 | bool &IsExactMatch) const { |
60 | 621 | IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind); |
61 | 621 | return Matcher.canConvertTo(NodeKind); |
62 | 621 | } |
63 | | |
64 | | DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher( |
65 | 0 | const DynTypedMatcher &Matcher) const { |
66 | 0 | return Matcher.dynCastTo(NodeKind); |
67 | 0 | } |
68 | | |
69 | | llvm::Optional<DynTypedMatcher> |
70 | | VariantMatcher::MatcherOps::constructVariadicOperator( |
71 | | DynTypedMatcher::VariadicOperator Op, |
72 | 13 | ArrayRef<VariantMatcher> InnerMatchers) const { |
73 | 13 | std::vector<DynTypedMatcher> DynMatchers; |
74 | 21 | for (const auto &InnerMatcher : InnerMatchers) { |
75 | | // Abort if any of the inner matchers can't be converted to |
76 | | // Matcher<T>. |
77 | 21 | if (!InnerMatcher.Value) |
78 | 0 | return llvm::None; |
79 | 21 | llvm::Optional<DynTypedMatcher> Inner = |
80 | 21 | InnerMatcher.Value->getTypedMatcher(*this); |
81 | 21 | if (!Inner) |
82 | 1 | return llvm::None; |
83 | 20 | DynMatchers.push_back(*Inner); |
84 | 20 | } |
85 | 12 | return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers); |
86 | 13 | } |
87 | | |
88 | 169 | VariantMatcher::Payload::~Payload() {} |
89 | | |
90 | | class VariantMatcher::SinglePayload : public VariantMatcher::Payload { |
91 | | public: |
92 | 136 | SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} |
93 | | |
94 | 23 | llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { |
95 | 23 | return Matcher; |
96 | 23 | } |
97 | | |
98 | 6 | std::string getTypeAsString() const override { |
99 | 6 | return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") |
100 | 6 | .str(); |
101 | 6 | } |
102 | | |
103 | | llvm::Optional<DynTypedMatcher> |
104 | 304 | getTypedMatcher(const MatcherOps &Ops) const override { |
105 | 304 | bool Ignore; |
106 | 304 | if (Ops.canConstructFrom(Matcher, Ignore)) |
107 | 273 | return Matcher; |
108 | 31 | return llvm::None; |
109 | 304 | } |
110 | | |
111 | 2 | bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { |
112 | 2 | return ArgKind::MakeMatcherArg(Matcher.getSupportedKind()) |
113 | 2 | .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity); |
114 | 2 | } |
115 | | |
116 | | private: |
117 | | const DynTypedMatcher Matcher; |
118 | | }; |
119 | | |
120 | | class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { |
121 | | public: |
122 | | PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) |
123 | 27 | : Matchers(std::move(MatchersIn)) {} |
124 | | |
125 | 27 | ~PolymorphicPayload() override {} |
126 | | |
127 | 2 | llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { |
128 | 2 | if (Matchers.size() != 1) |
129 | 2 | return llvm::Optional<DynTypedMatcher>(); |
130 | 0 | return Matchers[0]; |
131 | 2 | } |
132 | | |
133 | 4 | std::string getTypeAsString() const override { |
134 | 4 | std::string Inner; |
135 | 16 | for (size_t i = 0, e = Matchers.size(); i != e; ++i12 ) { |
136 | 12 | if (i != 0) |
137 | 8 | Inner += "|"; |
138 | 12 | Inner += Matchers[i].getSupportedKind().asStringRef(); |
139 | 12 | } |
140 | 4 | return (Twine("Matcher<") + Inner + ">").str(); |
141 | 4 | } |
142 | | |
143 | | llvm::Optional<DynTypedMatcher> |
144 | 72 | getTypedMatcher(const MatcherOps &Ops) const override { |
145 | 72 | bool FoundIsExact = false; |
146 | 72 | const DynTypedMatcher *Found = nullptr; |
147 | 72 | int NumFound = 0; |
148 | 389 | for (size_t i = 0, e = Matchers.size(); i != e; ++i317 ) { |
149 | 317 | bool IsExactMatch; |
150 | 317 | if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { |
151 | 70 | if (Found) { |
152 | 0 | if (FoundIsExact) { |
153 | 0 | assert(!IsExactMatch && "We should not have two exact matches."); |
154 | 0 | continue; |
155 | 0 | } |
156 | 0 | } |
157 | 70 | Found = &Matchers[i]; |
158 | 70 | FoundIsExact = IsExactMatch; |
159 | 70 | ++NumFound; |
160 | 70 | } |
161 | 317 | } |
162 | | // We only succeed if we found exactly one, or if we found an exact match. |
163 | 72 | if (Found && (70 FoundIsExact70 || NumFound == 112 )) |
164 | 70 | return *Found; |
165 | 2 | return llvm::None; |
166 | 72 | } |
167 | | |
168 | 0 | bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { |
169 | 0 | unsigned MaxSpecificity = 0; |
170 | 0 | for (const DynTypedMatcher &Matcher : Matchers) { |
171 | 0 | unsigned ThisSpecificity; |
172 | 0 | if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind()) |
173 | 0 | .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), |
174 | 0 | &ThisSpecificity)) { |
175 | 0 | MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); |
176 | 0 | } |
177 | 0 | } |
178 | 0 | if (Specificity) |
179 | 0 | *Specificity = MaxSpecificity; |
180 | 0 | return MaxSpecificity > 0; |
181 | 0 | } |
182 | | |
183 | | const std::vector<DynTypedMatcher> Matchers; |
184 | | }; |
185 | | |
186 | | class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { |
187 | | public: |
188 | | VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, |
189 | | std::vector<VariantMatcher> Args) |
190 | 6 | : Op(Op), Args(std::move(Args)) {} |
191 | | |
192 | 0 | llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { |
193 | 0 | return llvm::Optional<DynTypedMatcher>(); |
194 | 0 | } |
195 | | |
196 | 1 | std::string getTypeAsString() const override { |
197 | 1 | std::string Inner; |
198 | 3 | for (size_t i = 0, e = Args.size(); i != e; ++i2 ) { |
199 | 2 | if (i != 0) |
200 | 1 | Inner += "&"; |
201 | 2 | Inner += Args[i].getTypeAsString(); |
202 | 2 | } |
203 | 1 | return Inner; |
204 | 1 | } |
205 | | |
206 | | llvm::Optional<DynTypedMatcher> |
207 | 13 | getTypedMatcher(const MatcherOps &Ops) const override { |
208 | 13 | return Ops.constructVariadicOperator(Op, Args); |
209 | 13 | } |
210 | | |
211 | 0 | bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { |
212 | 0 | for (const VariantMatcher &Matcher : Args) { |
213 | 0 | if (!Matcher.isConvertibleTo(Kind, Specificity)) |
214 | 0 | return false; |
215 | 0 | } |
216 | 0 | return true; |
217 | 0 | } |
218 | | |
219 | | private: |
220 | | const DynTypedMatcher::VariadicOperator Op; |
221 | | const std::vector<VariantMatcher> Args; |
222 | | }; |
223 | | |
224 | 164 | VariantMatcher::VariantMatcher() {} |
225 | | |
226 | 136 | VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { |
227 | 136 | return VariantMatcher(std::make_shared<SinglePayload>(Matcher)); |
228 | 136 | } |
229 | | |
230 | | VariantMatcher |
231 | 27 | VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { |
232 | 27 | return VariantMatcher( |
233 | 27 | std::make_shared<PolymorphicPayload>(std::move(Matchers))); |
234 | 27 | } |
235 | | |
236 | | VariantMatcher VariantMatcher::VariadicOperatorMatcher( |
237 | | DynTypedMatcher::VariadicOperator Op, |
238 | 6 | std::vector<VariantMatcher> Args) { |
239 | 6 | return VariantMatcher( |
240 | 6 | std::make_shared<VariadicOpPayload>(Op, std::move(Args))); |
241 | 6 | } |
242 | | |
243 | 25 | llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { |
244 | 25 | return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>()0 ; |
245 | 25 | } |
246 | | |
247 | 0 | void VariantMatcher::reset() { Value.reset(); } |
248 | | |
249 | 11 | std::string VariantMatcher::getTypeAsString() const { |
250 | 11 | if (Value) return Value->getTypeAsString(); |
251 | 0 | return "<Nothing>"; |
252 | 11 | } |
253 | | |
254 | 1.32k | VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { |
255 | 1.32k | *this = Other; |
256 | 1.32k | } |
257 | | |
258 | 4 | VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { |
259 | 4 | setBoolean(Boolean); |
260 | 4 | } |
261 | | |
262 | 5 | VariantValue::VariantValue(double Double) : Type(VT_Nothing) { |
263 | 5 | setDouble(Double); |
264 | 5 | } |
265 | | |
266 | 18 | VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { |
267 | 18 | setUnsigned(Unsigned); |
268 | 18 | } |
269 | | |
270 | 68 | VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) { |
271 | 68 | setString(String); |
272 | 68 | } |
273 | | |
274 | 9 | VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) { |
275 | 9 | setNodeKind(NodeKind); |
276 | 9 | } |
277 | | |
278 | 131 | VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { |
279 | 131 | setMatcher(Matcher); |
280 | 131 | } |
281 | | |
282 | 2.45k | VariantValue::~VariantValue() { reset(); } |
283 | | |
284 | 2.11k | VariantValue &VariantValue::operator=(const VariantValue &Other) { |
285 | 2.11k | if (this == &Other) return *this0 ; |
286 | 2.11k | reset(); |
287 | 2.11k | switch (Other.Type) { |
288 | 15 | case VT_Boolean: |
289 | 15 | setBoolean(Other.getBoolean()); |
290 | 15 | break; |
291 | 25 | case VT_Double: |
292 | 25 | setDouble(Other.getDouble()); |
293 | 25 | break; |
294 | 77 | case VT_Unsigned: |
295 | 77 | setUnsigned(Other.getUnsigned()); |
296 | 77 | break; |
297 | 297 | case VT_String: |
298 | 297 | setString(Other.getString()); |
299 | 297 | break; |
300 | 18 | case VT_NodeKind: |
301 | 18 | setNodeKind(Other.getNodeKind()); |
302 | 18 | break; |
303 | 171 | case VT_Matcher: |
304 | 171 | setMatcher(Other.getMatcher()); |
305 | 171 | break; |
306 | 1.51k | case VT_Nothing: |
307 | 1.51k | Type = VT_Nothing; |
308 | 1.51k | break; |
309 | 2.11k | } |
310 | 2.11k | return *this; |
311 | 2.11k | } |
312 | | |
313 | 5.41k | void VariantValue::reset() { |
314 | 5.41k | switch (Type) { |
315 | 365 | case VT_String: |
316 | 365 | delete Value.String; |
317 | 365 | break; |
318 | 302 | case VT_Matcher: |
319 | 302 | delete Value.Matcher; |
320 | 302 | break; |
321 | 28 | case VT_NodeKind: |
322 | 28 | delete Value.NodeKind; |
323 | 28 | break; |
324 | | // Cases that do nothing. |
325 | 19 | case VT_Boolean: |
326 | 49 | case VT_Double: |
327 | 144 | case VT_Unsigned: |
328 | 4.71k | case VT_Nothing: |
329 | 4.71k | break; |
330 | 5.41k | } |
331 | 5.41k | Type = VT_Nothing; |
332 | 5.41k | } |
333 | | |
334 | 30 | bool VariantValue::isBoolean() const { |
335 | 30 | return Type == VT_Boolean; |
336 | 30 | } |
337 | | |
338 | 19 | bool VariantValue::getBoolean() const { |
339 | 19 | assert(isBoolean()); |
340 | 0 | return Value.Boolean; |
341 | 19 | } |
342 | | |
343 | 19 | void VariantValue::setBoolean(bool NewValue) { |
344 | 19 | reset(); |
345 | 19 | Type = VT_Boolean; |
346 | 19 | Value.Boolean = NewValue; |
347 | 19 | } |
348 | | |
349 | 41 | bool VariantValue::isDouble() const { |
350 | 41 | return Type == VT_Double; |
351 | 41 | } |
352 | | |
353 | 30 | double VariantValue::getDouble() const { |
354 | 30 | assert(isDouble()); |
355 | 0 | return Value.Double; |
356 | 30 | } |
357 | | |
358 | 30 | void VariantValue::setDouble(double NewValue) { |
359 | 30 | reset(); |
360 | 30 | Type = VT_Double; |
361 | 30 | Value.Double = NewValue; |
362 | 30 | } |
363 | | |
364 | 110 | bool VariantValue::isUnsigned() const { |
365 | 110 | return Type == VT_Unsigned; |
366 | 110 | } |
367 | | |
368 | 91 | unsigned VariantValue::getUnsigned() const { |
369 | 91 | assert(isUnsigned()); |
370 | 0 | return Value.Unsigned; |
371 | 91 | } |
372 | | |
373 | 95 | void VariantValue::setUnsigned(unsigned NewValue) { |
374 | 95 | reset(); |
375 | 95 | Type = VT_Unsigned; |
376 | 95 | Value.Unsigned = NewValue; |
377 | 95 | } |
378 | | |
379 | 452 | bool VariantValue::isString() const { |
380 | 452 | return Type == VT_String; |
381 | 452 | } |
382 | | |
383 | 361 | const std::string &VariantValue::getString() const { |
384 | 361 | assert(isString()); |
385 | 0 | return *Value.String; |
386 | 361 | } |
387 | | |
388 | 365 | void VariantValue::setString(StringRef NewValue) { |
389 | 365 | reset(); |
390 | 365 | Type = VT_String; |
391 | 365 | Value.String = new std::string(NewValue); |
392 | 365 | } |
393 | | |
394 | 39 | bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; } |
395 | | |
396 | 28 | const ASTNodeKind &VariantValue::getNodeKind() const { |
397 | 28 | assert(isNodeKind()); |
398 | 0 | return *Value.NodeKind; |
399 | 28 | } |
400 | | |
401 | 28 | void VariantValue::setNodeKind(ASTNodeKind NewValue) { |
402 | 28 | reset(); |
403 | 28 | Type = VT_NodeKind; |
404 | 28 | Value.NodeKind = new ASTNodeKind(NewValue); |
405 | 28 | } |
406 | | |
407 | 580 | bool VariantValue::isMatcher() const { |
408 | 580 | return Type == VT_Matcher; |
409 | 580 | } |
410 | | |
411 | 421 | const VariantMatcher &VariantValue::getMatcher() const { |
412 | 421 | assert(isMatcher()); |
413 | 0 | return *Value.Matcher; |
414 | 421 | } |
415 | | |
416 | 302 | void VariantValue::setMatcher(const VariantMatcher &NewValue) { |
417 | 302 | reset(); |
418 | 302 | Type = VT_Matcher; |
419 | 302 | Value.Matcher = new VariantMatcher(NewValue); |
420 | 302 | } |
421 | | |
422 | 6 | bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { |
423 | 6 | switch (Kind.getArgKind()) { |
424 | 0 | case ArgKind::AK_Boolean: |
425 | 0 | if (!isBoolean()) |
426 | 0 | return false; |
427 | 0 | *Specificity = 1; |
428 | 0 | return true; |
429 | | |
430 | 0 | case ArgKind::AK_Double: |
431 | 0 | if (!isDouble()) |
432 | 0 | return false; |
433 | 0 | *Specificity = 1; |
434 | 0 | return true; |
435 | | |
436 | 0 | case ArgKind::AK_Unsigned: |
437 | 0 | if (!isUnsigned()) |
438 | 0 | return false; |
439 | 0 | *Specificity = 1; |
440 | 0 | return true; |
441 | | |
442 | 2 | case ArgKind::AK_String: |
443 | 2 | if (!isString()) |
444 | 1 | return false; |
445 | 1 | *Specificity = 1; |
446 | 1 | return true; |
447 | | |
448 | 0 | case ArgKind::AK_Node: |
449 | 0 | if (!isNodeKind()) |
450 | 0 | return false; |
451 | 0 | return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity); |
452 | | |
453 | 4 | case ArgKind::AK_Matcher: |
454 | 4 | if (!isMatcher()) |
455 | 2 | return false; |
456 | 2 | return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity); |
457 | 6 | } |
458 | 0 | llvm_unreachable("Invalid Type"); |
459 | 0 | } |
460 | | |
461 | | bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds, |
462 | 6 | unsigned *Specificity) const { |
463 | 6 | unsigned MaxSpecificity = 0; |
464 | 6 | for (const ArgKind& Kind : Kinds) { |
465 | 6 | unsigned ThisSpecificity; |
466 | 6 | if (!isConvertibleTo(Kind, &ThisSpecificity)) |
467 | 3 | continue; |
468 | 3 | MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); |
469 | 3 | } |
470 | 6 | if (Specificity && MaxSpecificity > 0) { |
471 | 3 | *Specificity = MaxSpecificity; |
472 | 3 | } |
473 | 6 | return MaxSpecificity > 0; |
474 | 6 | } |
475 | | |
476 | 29 | std::string VariantValue::getTypeAsString() const { |
477 | 29 | switch (Type) { |
478 | 9 | case VT_String: return "String"; |
479 | 9 | case VT_Matcher: return getMatcher().getTypeAsString(); |
480 | 2 | case VT_Boolean: return "Boolean"; |
481 | 2 | case VT_Double: return "Double"; |
482 | 6 | case VT_Unsigned: return "Unsigned"; |
483 | 0 | case VT_NodeKind: |
484 | 0 | return getNodeKind().asStringRef().str(); |
485 | 1 | case VT_Nothing: return "Nothing"; |
486 | 29 | } |
487 | 0 | llvm_unreachable("Invalid Type"); |
488 | 0 | } |
489 | | |
490 | | } // end namespace dynamic |
491 | | } // end namespace ast_matchers |
492 | | } // end namespace clang |