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