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