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