1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Polymorphic value type.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/STLExtras.h"
18
19 namespace clang {
20 namespace ast_matchers {
21 namespace dynamic {
22
~MatcherOps()23 VariantMatcher::MatcherOps::~MatcherOps() {}
~Payload()24 VariantMatcher::Payload::~Payload() {}
25
26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
27 public:
SinglePayload(const DynTypedMatcher & Matcher)28 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
29
getSingleMatcher() const30 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
31 return Matcher;
32 }
33
getTypeAsString() const34 virtual std::string getTypeAsString() const {
35 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
36 .str();
37 }
38
makeTypedMatcher(MatcherOps & Ops) const39 virtual void makeTypedMatcher(MatcherOps &Ops) const {
40 bool Ignore;
41 if (Ops.canConstructFrom(Matcher, Ignore))
42 Ops.constructFrom(Matcher);
43 }
44
45 private:
46 const DynTypedMatcher Matcher;
47 };
48
49 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
50 public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)51 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
52 : Matchers(std::move(MatchersIn)) {}
53
~PolymorphicPayload()54 virtual ~PolymorphicPayload() {}
55
getSingleMatcher() const56 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
57 if (Matchers.size() != 1)
58 return llvm::Optional<DynTypedMatcher>();
59 return Matchers[0];
60 }
61
getTypeAsString() const62 virtual std::string getTypeAsString() const {
63 std::string Inner;
64 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
65 if (i != 0)
66 Inner += "|";
67 Inner += Matchers[i].getSupportedKind().asStringRef();
68 }
69 return (Twine("Matcher<") + Inner + ">").str();
70 }
71
makeTypedMatcher(MatcherOps & Ops) const72 virtual void makeTypedMatcher(MatcherOps &Ops) const {
73 bool FoundIsExact = false;
74 const DynTypedMatcher *Found = nullptr;
75 int NumFound = 0;
76 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
77 bool IsExactMatch;
78 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
79 if (Found) {
80 if (FoundIsExact) {
81 assert(!IsExactMatch && "We should not have two exact matches.");
82 continue;
83 }
84 }
85 Found = &Matchers[i];
86 FoundIsExact = IsExactMatch;
87 ++NumFound;
88 }
89 }
90 // We only succeed if we found exactly one, or if we found an exact match.
91 if (Found && (FoundIsExact || NumFound == 1))
92 Ops.constructFrom(*Found);
93 }
94
95 const std::vector<DynTypedMatcher> Matchers;
96 };
97
98 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
99 public:
VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,std::vector<VariantMatcher> Args)100 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
101 std::vector<VariantMatcher> Args)
102 : Func(Func), Args(std::move(Args)) {}
103
getSingleMatcher() const104 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
105 return llvm::Optional<DynTypedMatcher>();
106 }
107
getTypeAsString() const108 virtual std::string getTypeAsString() const {
109 std::string Inner;
110 for (size_t i = 0, e = Args.size(); i != e; ++i) {
111 if (i != 0)
112 Inner += "&";
113 Inner += Args[i].getTypeAsString();
114 }
115 return Inner;
116 }
117
makeTypedMatcher(MatcherOps & Ops) const118 virtual void makeTypedMatcher(MatcherOps &Ops) const {
119 Ops.constructVariadicOperator(Func, Args);
120 }
121
122 private:
123 const ast_matchers::internal::VariadicOperatorFunction Func;
124 const std::vector<VariantMatcher> Args;
125 };
126
VariantMatcher()127 VariantMatcher::VariantMatcher() {}
128
SingleMatcher(const DynTypedMatcher & Matcher)129 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
130 return VariantMatcher(new SinglePayload(Matcher));
131 }
132
133 VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)134 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
135 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
136 }
137
VariadicOperatorMatcher(ast_matchers::internal::VariadicOperatorFunction Func,std::vector<VariantMatcher> Args)138 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
139 ast_matchers::internal::VariadicOperatorFunction Func,
140 std::vector<VariantMatcher> Args) {
141 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
142 }
143
getSingleMatcher() const144 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
145 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
146 }
147
reset()148 void VariantMatcher::reset() { Value.reset(); }
149
getTypeAsString() const150 std::string VariantMatcher::getTypeAsString() const {
151 if (Value) return Value->getTypeAsString();
152 return "<Nothing>";
153 }
154
VariantValue(const VariantValue & Other)155 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
156 *this = Other;
157 }
158
VariantValue(unsigned Unsigned)159 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
160 setUnsigned(Unsigned);
161 }
162
VariantValue(const std::string & String)163 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
164 setString(String);
165 }
166
VariantValue(const VariantMatcher & Matcher)167 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
168 setMatcher(Matcher);
169 }
170
~VariantValue()171 VariantValue::~VariantValue() { reset(); }
172
operator =(const VariantValue & Other)173 VariantValue &VariantValue::operator=(const VariantValue &Other) {
174 if (this == &Other) return *this;
175 reset();
176 switch (Other.Type) {
177 case VT_Unsigned:
178 setUnsigned(Other.getUnsigned());
179 break;
180 case VT_String:
181 setString(Other.getString());
182 break;
183 case VT_Matcher:
184 setMatcher(Other.getMatcher());
185 break;
186 case VT_Nothing:
187 Type = VT_Nothing;
188 break;
189 }
190 return *this;
191 }
192
reset()193 void VariantValue::reset() {
194 switch (Type) {
195 case VT_String:
196 delete Value.String;
197 break;
198 case VT_Matcher:
199 delete Value.Matcher;
200 break;
201 // Cases that do nothing.
202 case VT_Unsigned:
203 case VT_Nothing:
204 break;
205 }
206 Type = VT_Nothing;
207 }
208
isUnsigned() const209 bool VariantValue::isUnsigned() const {
210 return Type == VT_Unsigned;
211 }
212
getUnsigned() const213 unsigned VariantValue::getUnsigned() const {
214 assert(isUnsigned());
215 return Value.Unsigned;
216 }
217
setUnsigned(unsigned NewValue)218 void VariantValue::setUnsigned(unsigned NewValue) {
219 reset();
220 Type = VT_Unsigned;
221 Value.Unsigned = NewValue;
222 }
223
isString() const224 bool VariantValue::isString() const {
225 return Type == VT_String;
226 }
227
getString() const228 const std::string &VariantValue::getString() const {
229 assert(isString());
230 return *Value.String;
231 }
232
setString(const std::string & NewValue)233 void VariantValue::setString(const std::string &NewValue) {
234 reset();
235 Type = VT_String;
236 Value.String = new std::string(NewValue);
237 }
238
isMatcher() const239 bool VariantValue::isMatcher() const {
240 return Type == VT_Matcher;
241 }
242
getMatcher() const243 const VariantMatcher &VariantValue::getMatcher() const {
244 assert(isMatcher());
245 return *Value.Matcher;
246 }
247
setMatcher(const VariantMatcher & NewValue)248 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
249 reset();
250 Type = VT_Matcher;
251 Value.Matcher = new VariantMatcher(NewValue);
252 }
253
getTypeAsString() const254 std::string VariantValue::getTypeAsString() const {
255 switch (Type) {
256 case VT_String: return "String";
257 case VT_Matcher: return getMatcher().getTypeAsString();
258 case VT_Unsigned: return "Unsigned";
259 case VT_Nothing: return "Nothing";
260 }
261 llvm_unreachable("Invalid Type");
262 }
263
264 } // end namespace dynamic
265 } // end namespace ast_matchers
266 } // end namespace clang
267