1 //===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// Polymorphic value type.
12 //===----------------------------------------------------------------------===//
14 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/STLExtras.h"
20 namespace ast_matchers
{
23 std::string
ArgKind::asString() const {
24 switch (getArgKind()) {
26 return (Twine("Matcher<") + NodeKind
.asStringRef() + ">").str();
28 return NodeKind
.asStringRef().str();
38 llvm_unreachable("unhandled ArgKind");
41 bool ArgKind::isConvertibleTo(ArgKind To
, unsigned *Specificity
) const {
44 if (K
!= AK_Matcher
&& K
!= AK_Node
) {
50 if (!NodeKind
.isBaseOf(To
.NodeKind
, &Distance
))
54 *Specificity
= 100 - Distance
;
59 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher
&Matcher
,
60 bool &IsExactMatch
) const {
61 IsExactMatch
= Matcher
.getSupportedKind().isSame(NodeKind
);
62 return Matcher
.canConvertTo(NodeKind
);
65 DynTypedMatcher
VariantMatcher::MatcherOps::convertMatcher(
66 const DynTypedMatcher
&Matcher
) const {
67 return Matcher
.dynCastTo(NodeKind
);
70 std::optional
<DynTypedMatcher
>
71 VariantMatcher::MatcherOps::constructVariadicOperator(
72 DynTypedMatcher::VariadicOperator Op
,
73 ArrayRef
<VariantMatcher
> InnerMatchers
) const {
74 std::vector
<DynTypedMatcher
> DynMatchers
;
75 for (const auto &InnerMatcher
: InnerMatchers
) {
76 // Abort if any of the inner matchers can't be converted to
78 if (!InnerMatcher
.Value
)
80 std::optional
<DynTypedMatcher
> Inner
=
81 InnerMatcher
.Value
->getTypedMatcher(*this);
84 DynMatchers
.push_back(*Inner
);
86 return DynTypedMatcher::constructVariadic(Op
, NodeKind
, DynMatchers
);
89 VariantMatcher::Payload::~Payload() {}
91 class VariantMatcher::SinglePayload
: public VariantMatcher::Payload
{
93 SinglePayload(const DynTypedMatcher
&Matcher
) : Matcher(Matcher
) {}
95 std::optional
<DynTypedMatcher
> getSingleMatcher() const override
{
99 std::string
getTypeAsString() const override
{
100 return (Twine("Matcher<") + Matcher
.getSupportedKind().asStringRef() + ">")
104 std::optional
<DynTypedMatcher
>
105 getTypedMatcher(const MatcherOps
&Ops
) const override
{
107 if (Ops
.canConstructFrom(Matcher
, Ignore
))
112 bool isConvertibleTo(ASTNodeKind Kind
, unsigned *Specificity
) const override
{
113 return ArgKind::MakeMatcherArg(Matcher
.getSupportedKind())
114 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind
), Specificity
);
118 const DynTypedMatcher Matcher
;
121 class VariantMatcher::PolymorphicPayload
: public VariantMatcher::Payload
{
123 PolymorphicPayload(std::vector
<DynTypedMatcher
> MatchersIn
)
124 : Matchers(std::move(MatchersIn
)) {}
126 ~PolymorphicPayload() override
{}
128 std::optional
<DynTypedMatcher
> getSingleMatcher() const override
{
129 if (Matchers
.size() != 1)
134 std::string
getTypeAsString() const override
{
136 for (size_t i
= 0, e
= Matchers
.size(); i
!= e
; ++i
) {
139 Inner
+= Matchers
[i
].getSupportedKind().asStringRef();
141 return (Twine("Matcher<") + Inner
+ ">").str();
144 std::optional
<DynTypedMatcher
>
145 getTypedMatcher(const MatcherOps
&Ops
) const override
{
146 bool FoundIsExact
= false;
147 const DynTypedMatcher
*Found
= nullptr;
149 for (size_t i
= 0, e
= Matchers
.size(); i
!= e
; ++i
) {
151 if (Ops
.canConstructFrom(Matchers
[i
], IsExactMatch
)) {
154 assert(!IsExactMatch
&& "We should not have two exact matches.");
158 Found
= &Matchers
[i
];
159 FoundIsExact
= IsExactMatch
;
163 // We only succeed if we found exactly one, or if we found an exact match.
164 if (Found
&& (FoundIsExact
|| NumFound
== 1))
169 bool isConvertibleTo(ASTNodeKind Kind
, unsigned *Specificity
) const override
{
170 unsigned MaxSpecificity
= 0;
171 for (const DynTypedMatcher
&Matcher
: Matchers
) {
172 unsigned ThisSpecificity
;
173 if (ArgKind::MakeMatcherArg(Matcher
.getSupportedKind())
174 .isConvertibleTo(ArgKind::MakeMatcherArg(Kind
),
176 MaxSpecificity
= std::max(MaxSpecificity
, ThisSpecificity
);
180 *Specificity
= MaxSpecificity
;
181 return MaxSpecificity
> 0;
184 const std::vector
<DynTypedMatcher
> Matchers
;
187 class VariantMatcher::VariadicOpPayload
: public VariantMatcher::Payload
{
189 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op
,
190 std::vector
<VariantMatcher
> Args
)
191 : Op(Op
), Args(std::move(Args
)) {}
193 std::optional
<DynTypedMatcher
> getSingleMatcher() const override
{
197 std::string
getTypeAsString() const override
{
199 for (size_t i
= 0, e
= Args
.size(); i
!= e
; ++i
) {
202 Inner
+= Args
[i
].getTypeAsString();
207 std::optional
<DynTypedMatcher
>
208 getTypedMatcher(const MatcherOps
&Ops
) const override
{
209 return Ops
.constructVariadicOperator(Op
, Args
);
212 bool isConvertibleTo(ASTNodeKind Kind
, unsigned *Specificity
) const override
{
213 for (const VariantMatcher
&Matcher
: Args
) {
214 if (!Matcher
.isConvertibleTo(Kind
, Specificity
))
221 const DynTypedMatcher::VariadicOperator Op
;
222 const std::vector
<VariantMatcher
> Args
;
225 VariantMatcher::VariantMatcher() {}
227 VariantMatcher
VariantMatcher::SingleMatcher(const DynTypedMatcher
&Matcher
) {
228 return VariantMatcher(std::make_shared
<SinglePayload
>(Matcher
));
232 VariantMatcher::PolymorphicMatcher(std::vector
<DynTypedMatcher
> Matchers
) {
233 return VariantMatcher(
234 std::make_shared
<PolymorphicPayload
>(std::move(Matchers
)));
237 VariantMatcher
VariantMatcher::VariadicOperatorMatcher(
238 DynTypedMatcher::VariadicOperator Op
,
239 std::vector
<VariantMatcher
> Args
) {
240 return VariantMatcher(
241 std::make_shared
<VariadicOpPayload
>(Op
, std::move(Args
)));
244 std::optional
<DynTypedMatcher
> VariantMatcher::getSingleMatcher() const {
245 return Value
? Value
->getSingleMatcher() : std::optional
<DynTypedMatcher
>();
248 void VariantMatcher::reset() { Value
.reset(); }
250 std::string
VariantMatcher::getTypeAsString() const {
251 if (Value
) return Value
->getTypeAsString();
255 VariantValue::VariantValue(const VariantValue
&Other
) : Type(VT_Nothing
) {
259 VariantValue::VariantValue(bool Boolean
) : Type(VT_Nothing
) {
263 VariantValue::VariantValue(double Double
) : Type(VT_Nothing
) {
267 VariantValue::VariantValue(unsigned Unsigned
) : Type(VT_Nothing
) {
268 setUnsigned(Unsigned
);
271 VariantValue::VariantValue(StringRef String
) : Type(VT_Nothing
) {
275 VariantValue::VariantValue(ASTNodeKind NodeKind
) : Type(VT_Nothing
) {
276 setNodeKind(NodeKind
);
279 VariantValue::VariantValue(const VariantMatcher
&Matcher
) : Type(VT_Nothing
) {
283 VariantValue::~VariantValue() { reset(); }
285 VariantValue
&VariantValue::operator=(const VariantValue
&Other
) {
286 if (this == &Other
) return *this;
288 switch (Other
.Type
) {
290 setBoolean(Other
.getBoolean());
293 setDouble(Other
.getDouble());
296 setUnsigned(Other
.getUnsigned());
299 setString(Other
.getString());
302 setNodeKind(Other
.getNodeKind());
305 setMatcher(Other
.getMatcher());
314 void VariantValue::reset() {
320 delete Value
.Matcher
;
323 delete Value
.NodeKind
;
325 // Cases that do nothing.
335 bool VariantValue::isBoolean() const {
336 return Type
== VT_Boolean
;
339 bool VariantValue::getBoolean() const {
341 return Value
.Boolean
;
344 void VariantValue::setBoolean(bool NewValue
) {
347 Value
.Boolean
= NewValue
;
350 bool VariantValue::isDouble() const {
351 return Type
== VT_Double
;
354 double VariantValue::getDouble() const {
359 void VariantValue::setDouble(double NewValue
) {
362 Value
.Double
= NewValue
;
365 bool VariantValue::isUnsigned() const {
366 return Type
== VT_Unsigned
;
369 unsigned VariantValue::getUnsigned() const {
370 assert(isUnsigned());
371 return Value
.Unsigned
;
374 void VariantValue::setUnsigned(unsigned NewValue
) {
377 Value
.Unsigned
= NewValue
;
380 bool VariantValue::isString() const {
381 return Type
== VT_String
;
384 const std::string
&VariantValue::getString() const {
386 return *Value
.String
;
389 void VariantValue::setString(StringRef NewValue
) {
392 Value
.String
= new std::string(NewValue
);
395 bool VariantValue::isNodeKind() const { return Type
== VT_NodeKind
; }
397 const ASTNodeKind
&VariantValue::getNodeKind() const {
398 assert(isNodeKind());
399 return *Value
.NodeKind
;
402 void VariantValue::setNodeKind(ASTNodeKind NewValue
) {
405 Value
.NodeKind
= new ASTNodeKind(NewValue
);
408 bool VariantValue::isMatcher() const {
409 return Type
== VT_Matcher
;
412 const VariantMatcher
&VariantValue::getMatcher() const {
414 return *Value
.Matcher
;
417 void VariantValue::setMatcher(const VariantMatcher
&NewValue
) {
420 Value
.Matcher
= new VariantMatcher(NewValue
);
423 bool VariantValue::isConvertibleTo(ArgKind Kind
, unsigned *Specificity
) const {
424 switch (Kind
.getArgKind()) {
425 case ArgKind::AK_Boolean
:
431 case ArgKind::AK_Double
:
437 case ArgKind::AK_Unsigned
:
443 case ArgKind::AK_String
:
449 case ArgKind::AK_Node
:
452 return getMatcher().isConvertibleTo(Kind
.getNodeKind(), Specificity
);
454 case ArgKind::AK_Matcher
:
457 return getMatcher().isConvertibleTo(Kind
.getMatcherKind(), Specificity
);
459 llvm_unreachable("Invalid Type");
462 bool VariantValue::isConvertibleTo(ArrayRef
<ArgKind
> Kinds
,
463 unsigned *Specificity
) const {
464 unsigned MaxSpecificity
= 0;
465 for (const ArgKind
& Kind
: Kinds
) {
466 unsigned ThisSpecificity
;
467 if (!isConvertibleTo(Kind
, &ThisSpecificity
))
469 MaxSpecificity
= std::max(MaxSpecificity
, ThisSpecificity
);
471 if (Specificity
&& MaxSpecificity
> 0) {
472 *Specificity
= MaxSpecificity
;
474 return MaxSpecificity
> 0;
477 std::string
VariantValue::getTypeAsString() const {
479 case VT_String
: return "String";
480 case VT_Matcher
: return getMatcher().getTypeAsString();
481 case VT_Boolean
: return "Boolean";
482 case VT_Double
: return "Double";
483 case VT_Unsigned
: return "Unsigned";
485 return getNodeKind().asStringRef().str();
486 case VT_Nothing
: return "Nothing";
488 llvm_unreachable("Invalid Type");
491 } // end namespace dynamic
492 } // end namespace ast_matchers
493 } // end namespace clang