1f4a2713aSLionel Sambuc //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief Polymorphic value type.
12f4a2713aSLionel Sambuc ///
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/VariantValue.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/LLVM.h"
17f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
18f4a2713aSLionel Sambuc
19f4a2713aSLionel Sambuc namespace clang {
20f4a2713aSLionel Sambuc namespace ast_matchers {
21f4a2713aSLionel Sambuc namespace dynamic {
22f4a2713aSLionel Sambuc
asString() const23*0a6a1f1dSLionel Sambuc std::string ArgKind::asString() const {
24*0a6a1f1dSLionel Sambuc switch (getArgKind()) {
25*0a6a1f1dSLionel Sambuc case AK_Matcher:
26*0a6a1f1dSLionel Sambuc return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
27*0a6a1f1dSLionel Sambuc case AK_Unsigned:
28*0a6a1f1dSLionel Sambuc return "unsigned";
29*0a6a1f1dSLionel Sambuc case AK_String:
30*0a6a1f1dSLionel Sambuc return "string";
31*0a6a1f1dSLionel Sambuc }
32*0a6a1f1dSLionel Sambuc llvm_unreachable("unhandled ArgKind");
33*0a6a1f1dSLionel Sambuc }
34*0a6a1f1dSLionel Sambuc
isConvertibleTo(ArgKind To,unsigned * Specificity) const35*0a6a1f1dSLionel Sambuc bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
36*0a6a1f1dSLionel Sambuc if (K != To.K)
37*0a6a1f1dSLionel Sambuc return false;
38*0a6a1f1dSLionel Sambuc if (K != AK_Matcher) {
39*0a6a1f1dSLionel Sambuc if (Specificity)
40*0a6a1f1dSLionel Sambuc *Specificity = 1;
41*0a6a1f1dSLionel Sambuc return true;
42*0a6a1f1dSLionel Sambuc }
43*0a6a1f1dSLionel Sambuc unsigned Distance;
44*0a6a1f1dSLionel Sambuc if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
45*0a6a1f1dSLionel Sambuc return false;
46*0a6a1f1dSLionel Sambuc
47*0a6a1f1dSLionel Sambuc if (Specificity)
48*0a6a1f1dSLionel Sambuc *Specificity = 100 - Distance;
49*0a6a1f1dSLionel Sambuc return true;
50*0a6a1f1dSLionel Sambuc }
51*0a6a1f1dSLionel Sambuc
52*0a6a1f1dSLionel Sambuc bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const53*0a6a1f1dSLionel Sambuc VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54*0a6a1f1dSLionel Sambuc bool &IsExactMatch) const {
55*0a6a1f1dSLionel Sambuc IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56*0a6a1f1dSLionel Sambuc return Matcher.canConvertTo(NodeKind);
57*0a6a1f1dSLionel Sambuc }
58*0a6a1f1dSLionel Sambuc
59*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const60*0a6a1f1dSLionel Sambuc VariantMatcher::MatcherOps::constructVariadicOperator(
61*0a6a1f1dSLionel Sambuc DynTypedMatcher::VariadicOperator Op,
62*0a6a1f1dSLionel Sambuc ArrayRef<VariantMatcher> InnerMatchers) const {
63*0a6a1f1dSLionel Sambuc std::vector<DynTypedMatcher> DynMatchers;
64*0a6a1f1dSLionel Sambuc for (const auto &InnerMatcher : InnerMatchers) {
65*0a6a1f1dSLionel Sambuc // Abort if any of the inner matchers can't be converted to
66*0a6a1f1dSLionel Sambuc // Matcher<T>.
67*0a6a1f1dSLionel Sambuc if (!InnerMatcher.Value)
68*0a6a1f1dSLionel Sambuc return llvm::None;
69*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher> Inner =
70*0a6a1f1dSLionel Sambuc InnerMatcher.Value->getTypedMatcher(*this);
71*0a6a1f1dSLionel Sambuc if (!Inner)
72*0a6a1f1dSLionel Sambuc return llvm::None;
73*0a6a1f1dSLionel Sambuc DynMatchers.push_back(*Inner);
74*0a6a1f1dSLionel Sambuc }
75*0a6a1f1dSLionel Sambuc return DynTypedMatcher::constructVariadic(Op, DynMatchers);
76*0a6a1f1dSLionel Sambuc }
77*0a6a1f1dSLionel Sambuc
~Payload()78f4a2713aSLionel Sambuc VariantMatcher::Payload::~Payload() {}
79f4a2713aSLionel Sambuc
80f4a2713aSLionel Sambuc class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81f4a2713aSLionel Sambuc public:
SinglePayload(const DynTypedMatcher & Matcher)82f4a2713aSLionel Sambuc SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
83f4a2713aSLionel Sambuc
getSingleMatcher() const84*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
85f4a2713aSLionel Sambuc return Matcher;
86f4a2713aSLionel Sambuc }
87f4a2713aSLionel Sambuc
getTypeAsString() const88*0a6a1f1dSLionel Sambuc std::string getTypeAsString() const override {
89f4a2713aSLionel Sambuc return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
90f4a2713aSLionel Sambuc .str();
91f4a2713aSLionel Sambuc }
92f4a2713aSLionel Sambuc
93*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const94*0a6a1f1dSLionel Sambuc getTypedMatcher(const MatcherOps &Ops) const override {
95*0a6a1f1dSLionel Sambuc bool Ignore;
96*0a6a1f1dSLionel Sambuc if (Ops.canConstructFrom(Matcher, Ignore))
97*0a6a1f1dSLionel Sambuc return Matcher;
98*0a6a1f1dSLionel Sambuc return llvm::None;
99*0a6a1f1dSLionel Sambuc }
100*0a6a1f1dSLionel Sambuc
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const101*0a6a1f1dSLionel Sambuc bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
102*0a6a1f1dSLionel Sambuc unsigned *Specificity) const override {
103*0a6a1f1dSLionel Sambuc return ArgKind(Matcher.getSupportedKind())
104*0a6a1f1dSLionel Sambuc .isConvertibleTo(Kind, Specificity);
105f4a2713aSLionel Sambuc }
106f4a2713aSLionel Sambuc
107f4a2713aSLionel Sambuc private:
108f4a2713aSLionel Sambuc const DynTypedMatcher Matcher;
109f4a2713aSLionel Sambuc };
110f4a2713aSLionel Sambuc
111f4a2713aSLionel Sambuc class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112f4a2713aSLionel Sambuc public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)113*0a6a1f1dSLionel Sambuc PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114*0a6a1f1dSLionel Sambuc : Matchers(std::move(MatchersIn)) {}
115f4a2713aSLionel Sambuc
~PolymorphicPayload()116*0a6a1f1dSLionel Sambuc ~PolymorphicPayload() override {}
117f4a2713aSLionel Sambuc
getSingleMatcher() const118*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
119f4a2713aSLionel Sambuc if (Matchers.size() != 1)
120f4a2713aSLionel Sambuc return llvm::Optional<DynTypedMatcher>();
121f4a2713aSLionel Sambuc return Matchers[0];
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc
getTypeAsString() const124*0a6a1f1dSLionel Sambuc std::string getTypeAsString() const override {
125f4a2713aSLionel Sambuc std::string Inner;
126f4a2713aSLionel Sambuc for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127f4a2713aSLionel Sambuc if (i != 0)
128f4a2713aSLionel Sambuc Inner += "|";
129f4a2713aSLionel Sambuc Inner += Matchers[i].getSupportedKind().asStringRef();
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc return (Twine("Matcher<") + Inner + ">").str();
132f4a2713aSLionel Sambuc }
133f4a2713aSLionel Sambuc
134*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const135*0a6a1f1dSLionel Sambuc getTypedMatcher(const MatcherOps &Ops) const override {
136*0a6a1f1dSLionel Sambuc bool FoundIsExact = false;
137*0a6a1f1dSLionel Sambuc const DynTypedMatcher *Found = nullptr;
138*0a6a1f1dSLionel Sambuc int NumFound = 0;
139f4a2713aSLionel Sambuc for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
140*0a6a1f1dSLionel Sambuc bool IsExactMatch;
141*0a6a1f1dSLionel Sambuc if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
142*0a6a1f1dSLionel Sambuc if (Found) {
143*0a6a1f1dSLionel Sambuc if (FoundIsExact) {
144*0a6a1f1dSLionel Sambuc assert(!IsExactMatch && "We should not have two exact matches.");
145*0a6a1f1dSLionel Sambuc continue;
146*0a6a1f1dSLionel Sambuc }
147*0a6a1f1dSLionel Sambuc }
148f4a2713aSLionel Sambuc Found = &Matchers[i];
149*0a6a1f1dSLionel Sambuc FoundIsExact = IsExactMatch;
150*0a6a1f1dSLionel Sambuc ++NumFound;
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc }
153*0a6a1f1dSLionel Sambuc // We only succeed if we found exactly one, or if we found an exact match.
154*0a6a1f1dSLionel Sambuc if (Found && (FoundIsExact || NumFound == 1))
155*0a6a1f1dSLionel Sambuc return *Found;
156*0a6a1f1dSLionel Sambuc return llvm::None;
157*0a6a1f1dSLionel Sambuc }
158*0a6a1f1dSLionel Sambuc
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const159*0a6a1f1dSLionel Sambuc bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
160*0a6a1f1dSLionel Sambuc unsigned *Specificity) const override {
161*0a6a1f1dSLionel Sambuc unsigned MaxSpecificity = 0;
162*0a6a1f1dSLionel Sambuc for (const DynTypedMatcher &Matcher : Matchers) {
163*0a6a1f1dSLionel Sambuc unsigned ThisSpecificity;
164*0a6a1f1dSLionel Sambuc if (ArgKind(Matcher.getSupportedKind())
165*0a6a1f1dSLionel Sambuc .isConvertibleTo(Kind, &ThisSpecificity)) {
166*0a6a1f1dSLionel Sambuc MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
167*0a6a1f1dSLionel Sambuc }
168*0a6a1f1dSLionel Sambuc }
169*0a6a1f1dSLionel Sambuc if (Specificity)
170*0a6a1f1dSLionel Sambuc *Specificity = MaxSpecificity;
171*0a6a1f1dSLionel Sambuc return MaxSpecificity > 0;
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc
174f4a2713aSLionel Sambuc const std::vector<DynTypedMatcher> Matchers;
175f4a2713aSLionel Sambuc };
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178f4a2713aSLionel Sambuc public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)179*0a6a1f1dSLionel Sambuc VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
180*0a6a1f1dSLionel Sambuc std::vector<VariantMatcher> Args)
181*0a6a1f1dSLionel Sambuc : Op(Op), Args(std::move(Args)) {}
182f4a2713aSLionel Sambuc
getSingleMatcher() const183*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
184f4a2713aSLionel Sambuc return llvm::Optional<DynTypedMatcher>();
185f4a2713aSLionel Sambuc }
186f4a2713aSLionel Sambuc
getTypeAsString() const187*0a6a1f1dSLionel Sambuc std::string getTypeAsString() const override {
188f4a2713aSLionel Sambuc std::string Inner;
189f4a2713aSLionel Sambuc for (size_t i = 0, e = Args.size(); i != e; ++i) {
190f4a2713aSLionel Sambuc if (i != 0)
191f4a2713aSLionel Sambuc Inner += "&";
192f4a2713aSLionel Sambuc Inner += Args[i].getTypeAsString();
193f4a2713aSLionel Sambuc }
194f4a2713aSLionel Sambuc return Inner;
195f4a2713aSLionel Sambuc }
196f4a2713aSLionel Sambuc
197*0a6a1f1dSLionel Sambuc llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const198*0a6a1f1dSLionel Sambuc getTypedMatcher(const MatcherOps &Ops) const override {
199*0a6a1f1dSLionel Sambuc return Ops.constructVariadicOperator(Op, Args);
200*0a6a1f1dSLionel Sambuc }
201*0a6a1f1dSLionel Sambuc
isConvertibleTo(ast_type_traits::ASTNodeKind Kind,unsigned * Specificity) const202*0a6a1f1dSLionel Sambuc bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
203*0a6a1f1dSLionel Sambuc unsigned *Specificity) const override {
204*0a6a1f1dSLionel Sambuc for (const VariantMatcher &Matcher : Args) {
205*0a6a1f1dSLionel Sambuc if (!Matcher.isConvertibleTo(Kind, Specificity))
206*0a6a1f1dSLionel Sambuc return false;
207*0a6a1f1dSLionel Sambuc }
208*0a6a1f1dSLionel Sambuc return true;
209f4a2713aSLionel Sambuc }
210f4a2713aSLionel Sambuc
211f4a2713aSLionel Sambuc private:
212*0a6a1f1dSLionel Sambuc const DynTypedMatcher::VariadicOperator Op;
213f4a2713aSLionel Sambuc const std::vector<VariantMatcher> Args;
214f4a2713aSLionel Sambuc };
215f4a2713aSLionel Sambuc
VariantMatcher()216f4a2713aSLionel Sambuc VariantMatcher::VariantMatcher() {}
217f4a2713aSLionel Sambuc
SingleMatcher(const DynTypedMatcher & Matcher)218f4a2713aSLionel Sambuc VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
219f4a2713aSLionel Sambuc return VariantMatcher(new SinglePayload(Matcher));
220f4a2713aSLionel Sambuc }
221f4a2713aSLionel Sambuc
222f4a2713aSLionel Sambuc VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)223*0a6a1f1dSLionel Sambuc VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224*0a6a1f1dSLionel Sambuc return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
225f4a2713aSLionel Sambuc }
226f4a2713aSLionel Sambuc
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)227f4a2713aSLionel Sambuc VariantMatcher VariantMatcher::VariadicOperatorMatcher(
228*0a6a1f1dSLionel Sambuc DynTypedMatcher::VariadicOperator Op,
229*0a6a1f1dSLionel Sambuc std::vector<VariantMatcher> Args) {
230*0a6a1f1dSLionel Sambuc return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
231f4a2713aSLionel Sambuc }
232f4a2713aSLionel Sambuc
getSingleMatcher() const233f4a2713aSLionel Sambuc llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
234f4a2713aSLionel Sambuc return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
235f4a2713aSLionel Sambuc }
236f4a2713aSLionel Sambuc
reset()237f4a2713aSLionel Sambuc void VariantMatcher::reset() { Value.reset(); }
238f4a2713aSLionel Sambuc
getTypeAsString() const239f4a2713aSLionel Sambuc std::string VariantMatcher::getTypeAsString() const {
240f4a2713aSLionel Sambuc if (Value) return Value->getTypeAsString();
241f4a2713aSLionel Sambuc return "<Nothing>";
242f4a2713aSLionel Sambuc }
243f4a2713aSLionel Sambuc
VariantValue(const VariantValue & Other)244f4a2713aSLionel Sambuc VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245f4a2713aSLionel Sambuc *this = Other;
246f4a2713aSLionel Sambuc }
247f4a2713aSLionel Sambuc
VariantValue(unsigned Unsigned)248f4a2713aSLionel Sambuc VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249f4a2713aSLionel Sambuc setUnsigned(Unsigned);
250f4a2713aSLionel Sambuc }
251f4a2713aSLionel Sambuc
VariantValue(const std::string & String)252f4a2713aSLionel Sambuc VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
253f4a2713aSLionel Sambuc setString(String);
254f4a2713aSLionel Sambuc }
255f4a2713aSLionel Sambuc
VariantValue(const VariantMatcher & Matcher)256f4a2713aSLionel Sambuc VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257f4a2713aSLionel Sambuc setMatcher(Matcher);
258f4a2713aSLionel Sambuc }
259f4a2713aSLionel Sambuc
~VariantValue()260f4a2713aSLionel Sambuc VariantValue::~VariantValue() { reset(); }
261f4a2713aSLionel Sambuc
operator =(const VariantValue & Other)262f4a2713aSLionel Sambuc VariantValue &VariantValue::operator=(const VariantValue &Other) {
263f4a2713aSLionel Sambuc if (this == &Other) return *this;
264f4a2713aSLionel Sambuc reset();
265f4a2713aSLionel Sambuc switch (Other.Type) {
266f4a2713aSLionel Sambuc case VT_Unsigned:
267f4a2713aSLionel Sambuc setUnsigned(Other.getUnsigned());
268f4a2713aSLionel Sambuc break;
269f4a2713aSLionel Sambuc case VT_String:
270f4a2713aSLionel Sambuc setString(Other.getString());
271f4a2713aSLionel Sambuc break;
272f4a2713aSLionel Sambuc case VT_Matcher:
273f4a2713aSLionel Sambuc setMatcher(Other.getMatcher());
274f4a2713aSLionel Sambuc break;
275f4a2713aSLionel Sambuc case VT_Nothing:
276f4a2713aSLionel Sambuc Type = VT_Nothing;
277f4a2713aSLionel Sambuc break;
278f4a2713aSLionel Sambuc }
279f4a2713aSLionel Sambuc return *this;
280f4a2713aSLionel Sambuc }
281f4a2713aSLionel Sambuc
reset()282f4a2713aSLionel Sambuc void VariantValue::reset() {
283f4a2713aSLionel Sambuc switch (Type) {
284f4a2713aSLionel Sambuc case VT_String:
285f4a2713aSLionel Sambuc delete Value.String;
286f4a2713aSLionel Sambuc break;
287f4a2713aSLionel Sambuc case VT_Matcher:
288f4a2713aSLionel Sambuc delete Value.Matcher;
289f4a2713aSLionel Sambuc break;
290f4a2713aSLionel Sambuc // Cases that do nothing.
291f4a2713aSLionel Sambuc case VT_Unsigned:
292f4a2713aSLionel Sambuc case VT_Nothing:
293f4a2713aSLionel Sambuc break;
294f4a2713aSLionel Sambuc }
295f4a2713aSLionel Sambuc Type = VT_Nothing;
296f4a2713aSLionel Sambuc }
297f4a2713aSLionel Sambuc
isUnsigned() const298f4a2713aSLionel Sambuc bool VariantValue::isUnsigned() const {
299f4a2713aSLionel Sambuc return Type == VT_Unsigned;
300f4a2713aSLionel Sambuc }
301f4a2713aSLionel Sambuc
getUnsigned() const302f4a2713aSLionel Sambuc unsigned VariantValue::getUnsigned() const {
303f4a2713aSLionel Sambuc assert(isUnsigned());
304f4a2713aSLionel Sambuc return Value.Unsigned;
305f4a2713aSLionel Sambuc }
306f4a2713aSLionel Sambuc
setUnsigned(unsigned NewValue)307f4a2713aSLionel Sambuc void VariantValue::setUnsigned(unsigned NewValue) {
308f4a2713aSLionel Sambuc reset();
309f4a2713aSLionel Sambuc Type = VT_Unsigned;
310f4a2713aSLionel Sambuc Value.Unsigned = NewValue;
311f4a2713aSLionel Sambuc }
312f4a2713aSLionel Sambuc
isString() const313f4a2713aSLionel Sambuc bool VariantValue::isString() const {
314f4a2713aSLionel Sambuc return Type == VT_String;
315f4a2713aSLionel Sambuc }
316f4a2713aSLionel Sambuc
getString() const317f4a2713aSLionel Sambuc const std::string &VariantValue::getString() const {
318f4a2713aSLionel Sambuc assert(isString());
319f4a2713aSLionel Sambuc return *Value.String;
320f4a2713aSLionel Sambuc }
321f4a2713aSLionel Sambuc
setString(const std::string & NewValue)322f4a2713aSLionel Sambuc void VariantValue::setString(const std::string &NewValue) {
323f4a2713aSLionel Sambuc reset();
324f4a2713aSLionel Sambuc Type = VT_String;
325f4a2713aSLionel Sambuc Value.String = new std::string(NewValue);
326f4a2713aSLionel Sambuc }
327f4a2713aSLionel Sambuc
isMatcher() const328f4a2713aSLionel Sambuc bool VariantValue::isMatcher() const {
329f4a2713aSLionel Sambuc return Type == VT_Matcher;
330f4a2713aSLionel Sambuc }
331f4a2713aSLionel Sambuc
getMatcher() const332f4a2713aSLionel Sambuc const VariantMatcher &VariantValue::getMatcher() const {
333f4a2713aSLionel Sambuc assert(isMatcher());
334f4a2713aSLionel Sambuc return *Value.Matcher;
335f4a2713aSLionel Sambuc }
336f4a2713aSLionel Sambuc
setMatcher(const VariantMatcher & NewValue)337f4a2713aSLionel Sambuc void VariantValue::setMatcher(const VariantMatcher &NewValue) {
338f4a2713aSLionel Sambuc reset();
339f4a2713aSLionel Sambuc Type = VT_Matcher;
340f4a2713aSLionel Sambuc Value.Matcher = new VariantMatcher(NewValue);
341f4a2713aSLionel Sambuc }
342f4a2713aSLionel Sambuc
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const343*0a6a1f1dSLionel Sambuc bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344*0a6a1f1dSLionel Sambuc switch (Kind.getArgKind()) {
345*0a6a1f1dSLionel Sambuc case ArgKind::AK_Unsigned:
346*0a6a1f1dSLionel Sambuc if (!isUnsigned())
347*0a6a1f1dSLionel Sambuc return false;
348*0a6a1f1dSLionel Sambuc *Specificity = 1;
349*0a6a1f1dSLionel Sambuc return true;
350*0a6a1f1dSLionel Sambuc
351*0a6a1f1dSLionel Sambuc case ArgKind::AK_String:
352*0a6a1f1dSLionel Sambuc if (!isString())
353*0a6a1f1dSLionel Sambuc return false;
354*0a6a1f1dSLionel Sambuc *Specificity = 1;
355*0a6a1f1dSLionel Sambuc return true;
356*0a6a1f1dSLionel Sambuc
357*0a6a1f1dSLionel Sambuc case ArgKind::AK_Matcher:
358*0a6a1f1dSLionel Sambuc if (!isMatcher())
359*0a6a1f1dSLionel Sambuc return false;
360*0a6a1f1dSLionel Sambuc return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
361*0a6a1f1dSLionel Sambuc }
362*0a6a1f1dSLionel Sambuc llvm_unreachable("Invalid Type");
363*0a6a1f1dSLionel Sambuc }
364*0a6a1f1dSLionel Sambuc
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const365*0a6a1f1dSLionel Sambuc bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
366*0a6a1f1dSLionel Sambuc unsigned *Specificity) const {
367*0a6a1f1dSLionel Sambuc unsigned MaxSpecificity = 0;
368*0a6a1f1dSLionel Sambuc for (const ArgKind& Kind : Kinds) {
369*0a6a1f1dSLionel Sambuc unsigned ThisSpecificity;
370*0a6a1f1dSLionel Sambuc if (!isConvertibleTo(Kind, &ThisSpecificity))
371*0a6a1f1dSLionel Sambuc continue;
372*0a6a1f1dSLionel Sambuc MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
373*0a6a1f1dSLionel Sambuc }
374*0a6a1f1dSLionel Sambuc if (Specificity && MaxSpecificity > 0) {
375*0a6a1f1dSLionel Sambuc *Specificity = MaxSpecificity;
376*0a6a1f1dSLionel Sambuc }
377*0a6a1f1dSLionel Sambuc return MaxSpecificity > 0;
378*0a6a1f1dSLionel Sambuc }
379*0a6a1f1dSLionel Sambuc
getTypeAsString() const380f4a2713aSLionel Sambuc std::string VariantValue::getTypeAsString() const {
381f4a2713aSLionel Sambuc switch (Type) {
382f4a2713aSLionel Sambuc case VT_String: return "String";
383f4a2713aSLionel Sambuc case VT_Matcher: return getMatcher().getTypeAsString();
384f4a2713aSLionel Sambuc case VT_Unsigned: return "Unsigned";
385f4a2713aSLionel Sambuc case VT_Nothing: return "Nothing";
386f4a2713aSLionel Sambuc }
387f4a2713aSLionel Sambuc llvm_unreachable("Invalid Type");
388f4a2713aSLionel Sambuc }
389f4a2713aSLionel Sambuc
390f4a2713aSLionel Sambuc } // end namespace dynamic
391f4a2713aSLionel Sambuc } // end namespace ast_matchers
392f4a2713aSLionel Sambuc } // end namespace clang
393