blob: a88b707012341372cc4319912fdd7f7e39697866 [file] [log] [blame]
Manuel Klimekf7f295f2013-05-14 09:13:00 +00001//===--- 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"
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000016#include "clang/Basic/LLVM.h"
Samuel Benzaquen9d028072013-08-13 14:54:51 +000017#include "llvm/ADT/STLExtras.h"
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000018
Manuel Klimekf7f295f2013-05-14 09:13:00 +000019namespace clang {
20namespace ast_matchers {
21namespace dynamic {
22
Stephen Hines176edba2014-12-01 14:53:08 -080023std::string ArgKind::asString() const {
24 switch (getArgKind()) {
25 case AK_Matcher:
26 return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
27 case AK_Unsigned:
28 return "unsigned";
29 case AK_String:
30 return "string";
31 }
32 llvm_unreachable("unhandled ArgKind");
33}
34
35bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
36 if (K != To.K)
37 return false;
38 if (K != AK_Matcher) {
39 if (Specificity)
40 *Specificity = 1;
41 return true;
42 }
43 unsigned Distance;
44 if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
45 return false;
46
47 if (Specificity)
48 *Specificity = 100 - Distance;
49 return true;
50}
51
52bool
53VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54 bool &IsExactMatch) const {
55 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56 return Matcher.canConvertTo(NodeKind);
57}
58
59llvm::Optional<DynTypedMatcher>
60VariantMatcher::MatcherOps::constructVariadicOperator(
61 DynTypedMatcher::VariadicOperator Op,
62 ArrayRef<VariantMatcher> InnerMatchers) const {
63 std::vector<DynTypedMatcher> DynMatchers;
64 for (const auto &InnerMatcher : InnerMatchers) {
65 // Abort if any of the inner matchers can't be converted to
66 // Matcher<T>.
67 if (!InnerMatcher.Value)
68 return llvm::None;
69 llvm::Optional<DynTypedMatcher> Inner =
70 InnerMatcher.Value->getTypedMatcher(*this);
71 if (!Inner)
72 return llvm::None;
73 DynMatchers.push_back(*Inner);
74 }
75 return DynTypedMatcher::constructVariadic(Op, DynMatchers);
76}
77
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000078VariantMatcher::Payload::~Payload() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000079
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000080class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81public:
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000082 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000083
Stephen Hines176edba2014-12-01 14:53:08 -080084 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000085 return Matcher;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000086 }
87
Stephen Hines176edba2014-12-01 14:53:08 -080088 std::string getTypeAsString() const override {
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000089 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000090 .str();
91 }
92
Stephen Hines176edba2014-12-01 14:53:08 -080093 llvm::Optional<DynTypedMatcher>
94 getTypedMatcher(const MatcherOps &Ops) const override {
Stephen Hines651f13c2014-04-23 16:59:28 -070095 bool Ignore;
96 if (Ops.canConstructFrom(Matcher, Ignore))
Stephen Hines176edba2014-12-01 14:53:08 -080097 return Matcher;
98 return llvm::None;
99 }
100
101 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
102 unsigned *Specificity) const override {
103 return ArgKind(Matcher.getSupportedKind())
104 .isConvertibleTo(Kind, Specificity);
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000105 }
106
107private:
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000108 const DynTypedMatcher Matcher;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000109};
110
111class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112public:
Stephen Hines651f13c2014-04-23 16:59:28 -0700113 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114 : Matchers(std::move(MatchersIn)) {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000115
Stephen Hines176edba2014-12-01 14:53:08 -0800116 ~PolymorphicPayload() override {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000117
Stephen Hines176edba2014-12-01 14:53:08 -0800118 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000119 if (Matchers.size() != 1)
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000120 return llvm::Optional<DynTypedMatcher>();
121 return Matchers[0];
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000122 }
123
Stephen Hines176edba2014-12-01 14:53:08 -0800124 std::string getTypeAsString() const override {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000125 std::string Inner;
126 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127 if (i != 0)
128 Inner += "|";
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000129 Inner += Matchers[i].getSupportedKind().asStringRef();
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000130 }
131 return (Twine("Matcher<") + Inner + ">").str();
132 }
133
Stephen Hines176edba2014-12-01 14:53:08 -0800134 llvm::Optional<DynTypedMatcher>
135 getTypedMatcher(const MatcherOps &Ops) const override {
Stephen Hines651f13c2014-04-23 16:59:28 -0700136 bool FoundIsExact = false;
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700137 const DynTypedMatcher *Found = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -0700138 int NumFound = 0;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000139 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700140 bool IsExactMatch;
141 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
142 if (Found) {
143 if (FoundIsExact) {
144 assert(!IsExactMatch && "We should not have two exact matches.");
145 continue;
146 }
147 }
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000148 Found = &Matchers[i];
Stephen Hines651f13c2014-04-23 16:59:28 -0700149 FoundIsExact = IsExactMatch;
150 ++NumFound;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000151 }
152 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700153 // We only succeed if we found exactly one, or if we found an exact match.
154 if (Found && (FoundIsExact || NumFound == 1))
Stephen Hines176edba2014-12-01 14:53:08 -0800155 return *Found;
156 return llvm::None;
157 }
158
159 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
160 unsigned *Specificity) const override {
161 unsigned MaxSpecificity = 0;
162 for (const DynTypedMatcher &Matcher : Matchers) {
163 unsigned ThisSpecificity;
164 if (ArgKind(Matcher.getSupportedKind())
165 .isConvertibleTo(Kind, &ThisSpecificity)) {
166 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
167 }
168 }
169 if (Specificity)
170 *Specificity = MaxSpecificity;
171 return MaxSpecificity > 0;
Samuel Benzaquena7350902013-08-28 18:42:04 +0000172 }
173
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000174 const std::vector<DynTypedMatcher> Matchers;
Samuel Benzaquena7350902013-08-28 18:42:04 +0000175};
176
177class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178public:
Stephen Hines176edba2014-12-01 14:53:08 -0800179 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
Stephen Hines651f13c2014-04-23 16:59:28 -0700180 std::vector<VariantMatcher> Args)
Stephen Hines176edba2014-12-01 14:53:08 -0800181 : Op(Op), Args(std::move(Args)) {}
Samuel Benzaquena7350902013-08-28 18:42:04 +0000182
Stephen Hines176edba2014-12-01 14:53:08 -0800183 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000184 return llvm::Optional<DynTypedMatcher>();
Samuel Benzaquena7350902013-08-28 18:42:04 +0000185 }
186
Stephen Hines176edba2014-12-01 14:53:08 -0800187 std::string getTypeAsString() const override {
Samuel Benzaquena7350902013-08-28 18:42:04 +0000188 std::string Inner;
189 for (size_t i = 0, e = Args.size(); i != e; ++i) {
190 if (i != 0)
191 Inner += "&";
192 Inner += Args[i].getTypeAsString();
193 }
194 return Inner;
195 }
196
Stephen Hines176edba2014-12-01 14:53:08 -0800197 llvm::Optional<DynTypedMatcher>
198 getTypedMatcher(const MatcherOps &Ops) const override {
199 return Ops.constructVariadicOperator(Op, Args);
200 }
201
202 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
203 unsigned *Specificity) const override {
204 for (const VariantMatcher &Matcher : Args) {
205 if (!Matcher.isConvertibleTo(Kind, Specificity))
206 return false;
207 }
208 return true;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000209 }
210
211private:
Stephen Hines176edba2014-12-01 14:53:08 -0800212 const DynTypedMatcher::VariadicOperator Op;
Samuel Benzaquena7350902013-08-28 18:42:04 +0000213 const std::vector<VariantMatcher> Args;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000214};
215
216VariantMatcher::VariantMatcher() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000217
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000218VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000219 return VariantMatcher(new SinglePayload(Matcher));
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000220}
221
222VariantMatcher
Stephen Hines651f13c2014-04-23 16:59:28 -0700223VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000225}
226
Samuel Benzaquena7350902013-08-28 18:42:04 +0000227VariantMatcher VariantMatcher::VariadicOperatorMatcher(
Stephen Hines176edba2014-12-01 14:53:08 -0800228 DynTypedMatcher::VariadicOperator Op,
Stephen Hines651f13c2014-04-23 16:59:28 -0700229 std::vector<VariantMatcher> Args) {
Stephen Hines176edba2014-12-01 14:53:08 -0800230 return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
Samuel Benzaquena7350902013-08-28 18:42:04 +0000231}
232
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000233llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
234 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000235}
236
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000237void VariantMatcher::reset() { Value.reset(); }
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000238
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000239std::string VariantMatcher::getTypeAsString() const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000240 if (Value) return Value->getTypeAsString();
241 return "<Nothing>";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000242}
243
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000244VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245 *this = Other;
246}
247
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000248VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249 setUnsigned(Unsigned);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000250}
251
252VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
253 setString(String);
254}
255
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000256VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257 setMatcher(Matcher);
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000258}
259
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000260VariantValue::~VariantValue() { reset(); }
261
262VariantValue &VariantValue::operator=(const VariantValue &Other) {
263 if (this == &Other) return *this;
264 reset();
265 switch (Other.Type) {
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000266 case VT_Unsigned:
267 setUnsigned(Other.getUnsigned());
268 break;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000269 case VT_String:
270 setString(Other.getString());
271 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000272 case VT_Matcher:
273 setMatcher(Other.getMatcher());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000274 break;
275 case VT_Nothing:
276 Type = VT_Nothing;
277 break;
278 }
279 return *this;
280}
281
282void VariantValue::reset() {
283 switch (Type) {
284 case VT_String:
285 delete Value.String;
286 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000287 case VT_Matcher:
288 delete Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000289 break;
290 // Cases that do nothing.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000291 case VT_Unsigned:
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000292 case VT_Nothing:
293 break;
294 }
295 Type = VT_Nothing;
296}
297
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000298bool VariantValue::isUnsigned() const {
299 return Type == VT_Unsigned;
300}
301
302unsigned VariantValue::getUnsigned() const {
303 assert(isUnsigned());
304 return Value.Unsigned;
305}
306
307void VariantValue::setUnsigned(unsigned NewValue) {
308 reset();
309 Type = VT_Unsigned;
310 Value.Unsigned = NewValue;
311}
312
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000313bool VariantValue::isString() const {
314 return Type == VT_String;
315}
316
317const std::string &VariantValue::getString() const {
318 assert(isString());
319 return *Value.String;
320}
321
322void VariantValue::setString(const std::string &NewValue) {
323 reset();
324 Type = VT_String;
325 Value.String = new std::string(NewValue);
326}
327
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000328bool VariantValue::isMatcher() const {
329 return Type == VT_Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000330}
331
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000332const VariantMatcher &VariantValue::getMatcher() const {
333 assert(isMatcher());
334 return *Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000335}
336
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000337void VariantValue::setMatcher(const VariantMatcher &NewValue) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000338 reset();
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000339 Type = VT_Matcher;
340 Value.Matcher = new VariantMatcher(NewValue);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000341}
342
Stephen Hines176edba2014-12-01 14:53:08 -0800343bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344 switch (Kind.getArgKind()) {
345 case ArgKind::AK_Unsigned:
346 if (!isUnsigned())
347 return false;
348 *Specificity = 1;
349 return true;
350
351 case ArgKind::AK_String:
352 if (!isString())
353 return false;
354 *Specificity = 1;
355 return true;
356
357 case ArgKind::AK_Matcher:
358 if (!isMatcher())
359 return false;
360 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
361 }
362 llvm_unreachable("Invalid Type");
363}
364
365bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
366 unsigned *Specificity) const {
367 unsigned MaxSpecificity = 0;
368 for (const ArgKind& Kind : Kinds) {
369 unsigned ThisSpecificity;
370 if (!isConvertibleTo(Kind, &ThisSpecificity))
371 continue;
372 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
373 }
374 if (Specificity && MaxSpecificity > 0) {
375 *Specificity = MaxSpecificity;
376 }
377 return MaxSpecificity > 0;
378}
379
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000380std::string VariantValue::getTypeAsString() const {
381 switch (Type) {
382 case VT_String: return "String";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000383 case VT_Matcher: return getMatcher().getTypeAsString();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000384 case VT_Unsigned: return "Unsigned";
385 case VT_Nothing: return "Nothing";
386 }
387 llvm_unreachable("Invalid Type");
388}
389
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000390} // end namespace dynamic
391} // end namespace ast_matchers
392} // end namespace clang