blob: 57c7b80d3619cec7272e97f17c808206d90d0972 [file] [log] [blame]
Manuel Klimek24db0f02013-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 Benzaquen81ef9292013-06-20 14:28:32 +000016#include "clang/Basic/LLVM.h"
Samuel Benzaquen0239b692013-08-13 14:54:51 +000017#include "llvm/ADT/STLExtras.h"
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000018
Manuel Klimek24db0f02013-05-14 09:13:00 +000019namespace clang {
20namespace ast_matchers {
21namespace dynamic {
22
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000023std::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
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000052VariantMatcher::MatcherOps::~MatcherOps() {}
53VariantMatcher::Payload::~Payload() {}
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +000054
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000055class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
56public:
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000057 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000058
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000059 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000060 return Matcher;
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000061 }
62
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000063 std::string getTypeAsString() const override {
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000064 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000065 .str();
66 }
67
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000068 void makeTypedMatcher(MatcherOps &Ops) const override {
Samuel Benzaquena0839352014-03-10 15:40:23 +000069 bool Ignore;
70 if (Ops.canConstructFrom(Matcher, Ignore))
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000071 Ops.constructFrom(Matcher);
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000072 }
73
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000074 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
75 unsigned *Specificity) const override {
76 return ArgKind(Matcher.getSupportedKind())
77 .isConvertibleTo(Kind, Specificity);
78 }
79
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000080private:
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000081 const DynTypedMatcher Matcher;
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000082};
83
84class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
85public:
Benjamin Kramer3f755aa2014-03-10 17:55:02 +000086 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
87 : Matchers(std::move(MatchersIn)) {}
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000088
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000089 ~PolymorphicPayload() override {}
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000090
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000091 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000092 if (Matchers.size() != 1)
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +000093 return llvm::Optional<DynTypedMatcher>();
94 return Matchers[0];
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000095 }
96
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000097 std::string getTypeAsString() const override {
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +000098 std::string Inner;
99 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
100 if (i != 0)
101 Inner += "|";
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000102 Inner += Matchers[i].getSupportedKind().asStringRef();
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000103 }
104 return (Twine("Matcher<") + Inner + ">").str();
105 }
106
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000107 void makeTypedMatcher(MatcherOps &Ops) const override {
Samuel Benzaquena0839352014-03-10 15:40:23 +0000108 bool FoundIsExact = false;
Craig Topper210e1ad2014-05-17 18:49:24 +0000109 const DynTypedMatcher *Found = nullptr;
Samuel Benzaquena0839352014-03-10 15:40:23 +0000110 int NumFound = 0;
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000111 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
Samuel Benzaquena0839352014-03-10 15:40:23 +0000112 bool IsExactMatch;
113 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
114 if (Found) {
115 if (FoundIsExact) {
116 assert(!IsExactMatch && "We should not have two exact matches.");
117 continue;
118 }
119 }
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000120 Found = &Matchers[i];
Samuel Benzaquena0839352014-03-10 15:40:23 +0000121 FoundIsExact = IsExactMatch;
122 ++NumFound;
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000123 }
124 }
Samuel Benzaquena0839352014-03-10 15:40:23 +0000125 // We only succeed if we found exactly one, or if we found an exact match.
126 if (Found && (FoundIsExact || NumFound == 1))
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000127 Ops.constructFrom(*Found);
128 }
129
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000130 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
131 unsigned *Specificity) const override {
132 unsigned MaxSpecificity = 0;
133 for (const DynTypedMatcher &Matcher : Matchers) {
134 unsigned ThisSpecificity;
135 if (ArgKind(Matcher.getSupportedKind())
136 .isConvertibleTo(Kind, &ThisSpecificity)) {
137 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
138 }
139 }
140 if (Specificity)
141 *Specificity = MaxSpecificity;
142 return MaxSpecificity > 0;
143 }
144
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000145 const std::vector<DynTypedMatcher> Matchers;
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000146};
147
148class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
149public:
150 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
Benjamin Kramer3f755aa2014-03-10 17:55:02 +0000151 std::vector<VariantMatcher> Args)
152 : Func(Func), Args(std::move(Args)) {}
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000153
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000154 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000155 return llvm::Optional<DynTypedMatcher>();
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000156 }
157
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000158 std::string getTypeAsString() const override {
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000159 std::string Inner;
160 for (size_t i = 0, e = Args.size(); i != e; ++i) {
161 if (i != 0)
162 Inner += "&";
163 Inner += Args[i].getTypeAsString();
164 }
165 return Inner;
166 }
167
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000168 void makeTypedMatcher(MatcherOps &Ops) const override {
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000169 Ops.constructVariadicOperator(Func, Args);
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000170 }
171
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000172 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
173 unsigned *Specificity) const override {
174 for (const VariantMatcher &Matcher : Args) {
175 if (!Matcher.isConvertibleTo(Kind, Specificity))
176 return false;
177 }
178 return true;
179 }
180
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000181private:
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000182 const ast_matchers::internal::VariadicOperatorFunction Func;
183 const std::vector<VariantMatcher> Args;
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000184};
185
186VariantMatcher::VariantMatcher() {}
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000187
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000188VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000189 return VariantMatcher(new SinglePayload(Matcher));
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000190}
191
192VariantMatcher
Benjamin Kramer3f755aa2014-03-10 17:55:02 +0000193VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
194 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000195}
196
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000197VariantMatcher VariantMatcher::VariadicOperatorMatcher(
198 ast_matchers::internal::VariadicOperatorFunction Func,
Benjamin Kramer3f755aa2014-03-10 17:55:02 +0000199 std::vector<VariantMatcher> Args) {
200 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000201}
202
Samuel Benzaquenf34ac3e2013-10-29 14:37:15 +0000203llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
204 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000205}
206
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000207void VariantMatcher::reset() { Value.reset(); }
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000208
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000209std::string VariantMatcher::getTypeAsString() const {
Samuel Benzaquen8c9f6332013-08-22 16:38:33 +0000210 if (Value) return Value->getTypeAsString();
211 return "<Nothing>";
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000212}
213
Manuel Klimek24db0f02013-05-14 09:13:00 +0000214VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
215 *this = Other;
216}
217
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000218VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
219 setUnsigned(Unsigned);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000220}
221
222VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
223 setString(String);
224}
225
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000226VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
227 setMatcher(Matcher);
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000228}
229
Manuel Klimek24db0f02013-05-14 09:13:00 +0000230VariantValue::~VariantValue() { reset(); }
231
232VariantValue &VariantValue::operator=(const VariantValue &Other) {
233 if (this == &Other) return *this;
234 reset();
235 switch (Other.Type) {
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000236 case VT_Unsigned:
237 setUnsigned(Other.getUnsigned());
238 break;
Manuel Klimek24db0f02013-05-14 09:13:00 +0000239 case VT_String:
240 setString(Other.getString());
241 break;
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000242 case VT_Matcher:
243 setMatcher(Other.getMatcher());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000244 break;
245 case VT_Nothing:
246 Type = VT_Nothing;
247 break;
248 }
249 return *this;
250}
251
252void VariantValue::reset() {
253 switch (Type) {
254 case VT_String:
255 delete Value.String;
256 break;
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000257 case VT_Matcher:
258 delete Value.Matcher;
Manuel Klimek24db0f02013-05-14 09:13:00 +0000259 break;
260 // Cases that do nothing.
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000261 case VT_Unsigned:
Manuel Klimek24db0f02013-05-14 09:13:00 +0000262 case VT_Nothing:
263 break;
264 }
265 Type = VT_Nothing;
266}
267
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000268bool VariantValue::isUnsigned() const {
269 return Type == VT_Unsigned;
270}
271
272unsigned VariantValue::getUnsigned() const {
273 assert(isUnsigned());
274 return Value.Unsigned;
275}
276
277void VariantValue::setUnsigned(unsigned NewValue) {
278 reset();
279 Type = VT_Unsigned;
280 Value.Unsigned = NewValue;
281}
282
Manuel Klimek24db0f02013-05-14 09:13:00 +0000283bool VariantValue::isString() const {
284 return Type == VT_String;
285}
286
287const std::string &VariantValue::getString() const {
288 assert(isString());
289 return *Value.String;
290}
291
292void VariantValue::setString(const std::string &NewValue) {
293 reset();
294 Type = VT_String;
295 Value.String = new std::string(NewValue);
296}
297
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000298bool VariantValue::isMatcher() const {
299 return Type == VT_Matcher;
Manuel Klimek24db0f02013-05-14 09:13:00 +0000300}
301
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000302const VariantMatcher &VariantValue::getMatcher() const {
303 assert(isMatcher());
304 return *Value.Matcher;
Manuel Klimek24db0f02013-05-14 09:13:00 +0000305}
306
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000307void VariantValue::setMatcher(const VariantMatcher &NewValue) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000308 reset();
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000309 Type = VT_Matcher;
310 Value.Matcher = new VariantMatcher(NewValue);
Manuel Klimek24db0f02013-05-14 09:13:00 +0000311}
312
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000313bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
314 switch (Kind.getArgKind()) {
315 case ArgKind::AK_Unsigned:
316 if (!isUnsigned())
317 return false;
318 *Specificity = 1;
319 return true;
320
321 case ArgKind::AK_String:
322 if (!isString())
323 return false;
324 *Specificity = 1;
325 return true;
326
327 case ArgKind::AK_Matcher:
328 if (!isMatcher())
329 return false;
330 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
331 }
332 llvm_unreachable("Invalid Type");
333}
334
335bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
336 unsigned *Specificity) const {
337 unsigned MaxSpecificity = 0;
338 for (const ArgKind& Kind : Kinds) {
339 unsigned ThisSpecificity;
340 if (!isConvertibleTo(Kind, &ThisSpecificity))
341 continue;
342 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
343 }
344 if (Specificity && MaxSpecificity > 0) {
345 *Specificity = MaxSpecificity;
346 }
347 return MaxSpecificity > 0;
348}
349
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000350std::string VariantValue::getTypeAsString() const {
351 switch (Type) {
352 case VT_String: return "String";
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000353 case VT_Matcher: return getMatcher().getTypeAsString();
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000354 case VT_Unsigned: return "Unsigned";
355 case VT_Nothing: return "Nothing";
356 }
357 llvm_unreachable("Invalid Type");
358}
359
Manuel Klimek24db0f02013-05-14 09:13:00 +0000360} // end namespace dynamic
361} // end namespace ast_matchers
362} // end namespace clang