blob: 18c989432f46c2c476b007d26d6529004aa0c67f [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
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000023VariantMatcher::MatcherOps::~MatcherOps() {}
24VariantMatcher::Payload::~Payload() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000025
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000026class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
27public:
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000028 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000029
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000030 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
31 return Matcher;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000032 }
33
34 virtual std::string getTypeAsString() const {
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000035 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000036 .str();
37 }
38
Samuel Benzaquena7350902013-08-28 18:42:04 +000039 virtual void makeTypedMatcher(MatcherOps &Ops) const {
Stephen Hines651f13c2014-04-23 16:59:28 -070040 bool Ignore;
41 if (Ops.canConstructFrom(Matcher, Ignore))
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000042 Ops.constructFrom(Matcher);
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000043 }
44
45private:
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000046 const DynTypedMatcher Matcher;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000047};
48
49class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
50public:
Stephen Hines651f13c2014-04-23 16:59:28 -070051 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
52 : Matchers(std::move(MatchersIn)) {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000053
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000054 virtual ~PolymorphicPayload() {}
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000055
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000056 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000057 if (Matchers.size() != 1)
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000058 return llvm::Optional<DynTypedMatcher>();
59 return Matchers[0];
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000060 }
61
62 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 += "|";
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000067 Inner += Matchers[i].getSupportedKind().asStringRef();
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000068 }
69 return (Twine("Matcher<") + Inner + ">").str();
70 }
71
Samuel Benzaquena7350902013-08-28 18:42:04 +000072 virtual void makeTypedMatcher(MatcherOps &Ops) const {
Stephen Hines651f13c2014-04-23 16:59:28 -070073 bool FoundIsExact = false;
Stephen Hines6bcf27b2014-05-29 04:14:42 -070074 const DynTypedMatcher *Found = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -070075 int NumFound = 0;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000076 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
Stephen Hines651f13c2014-04-23 16:59:28 -070077 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 }
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000085 Found = &Matchers[i];
Stephen Hines651f13c2014-04-23 16:59:28 -070086 FoundIsExact = IsExactMatch;
87 ++NumFound;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000088 }
89 }
Stephen Hines651f13c2014-04-23 16:59:28 -070090 // We only succeed if we found exactly one, or if we found an exact match.
91 if (Found && (FoundIsExact || NumFound == 1))
Samuel Benzaquena7350902013-08-28 18:42:04 +000092 Ops.constructFrom(*Found);
93 }
94
Samuel Benzaquenb7488d72013-10-29 14:37:15 +000095 const std::vector<DynTypedMatcher> Matchers;
Samuel Benzaquena7350902013-08-28 18:42:04 +000096};
97
98class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
99public:
100 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
Stephen Hines651f13c2014-04-23 16:59:28 -0700101 std::vector<VariantMatcher> Args)
102 : Func(Func), Args(std::move(Args)) {}
Samuel Benzaquena7350902013-08-28 18:42:04 +0000103
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000104 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
105 return llvm::Optional<DynTypedMatcher>();
Samuel Benzaquena7350902013-08-28 18:42:04 +0000106 }
107
108 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
118 virtual void makeTypedMatcher(MatcherOps &Ops) const {
119 Ops.constructVariadicOperator(Func, Args);
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000120 }
121
122private:
Samuel Benzaquena7350902013-08-28 18:42:04 +0000123 const ast_matchers::internal::VariadicOperatorFunction Func;
124 const std::vector<VariantMatcher> Args;
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000125};
126
127VariantMatcher::VariantMatcher() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000128
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000129VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000130 return VariantMatcher(new SinglePayload(Matcher));
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000131}
132
133VariantMatcher
Stephen Hines651f13c2014-04-23 16:59:28 -0700134VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
135 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000136}
137
Samuel Benzaquena7350902013-08-28 18:42:04 +0000138VariantMatcher VariantMatcher::VariadicOperatorMatcher(
139 ast_matchers::internal::VariadicOperatorFunction Func,
Stephen Hines651f13c2014-04-23 16:59:28 -0700140 std::vector<VariantMatcher> Args) {
141 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
Samuel Benzaquena7350902013-08-28 18:42:04 +0000142}
143
Samuel Benzaquenb7488d72013-10-29 14:37:15 +0000144llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
145 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000146}
147
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000148void VariantMatcher::reset() { Value.reset(); }
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000149
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000150std::string VariantMatcher::getTypeAsString() const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000151 if (Value) return Value->getTypeAsString();
152 return "<Nothing>";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000153}
154
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000155VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
156 *this = Other;
157}
158
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000159VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
160 setUnsigned(Unsigned);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000161}
162
163VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
164 setString(String);
165}
166
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000167VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
168 setMatcher(Matcher);
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000169}
170
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000171VariantValue::~VariantValue() { reset(); }
172
173VariantValue &VariantValue::operator=(const VariantValue &Other) {
174 if (this == &Other) return *this;
175 reset();
176 switch (Other.Type) {
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000177 case VT_Unsigned:
178 setUnsigned(Other.getUnsigned());
179 break;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000180 case VT_String:
181 setString(Other.getString());
182 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000183 case VT_Matcher:
184 setMatcher(Other.getMatcher());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000185 break;
186 case VT_Nothing:
187 Type = VT_Nothing;
188 break;
189 }
190 return *this;
191}
192
193void VariantValue::reset() {
194 switch (Type) {
195 case VT_String:
196 delete Value.String;
197 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000198 case VT_Matcher:
199 delete Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000200 break;
201 // Cases that do nothing.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000202 case VT_Unsigned:
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000203 case VT_Nothing:
204 break;
205 }
206 Type = VT_Nothing;
207}
208
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000209bool VariantValue::isUnsigned() const {
210 return Type == VT_Unsigned;
211}
212
213unsigned VariantValue::getUnsigned() const {
214 assert(isUnsigned());
215 return Value.Unsigned;
216}
217
218void VariantValue::setUnsigned(unsigned NewValue) {
219 reset();
220 Type = VT_Unsigned;
221 Value.Unsigned = NewValue;
222}
223
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000224bool VariantValue::isString() const {
225 return Type == VT_String;
226}
227
228const std::string &VariantValue::getString() const {
229 assert(isString());
230 return *Value.String;
231}
232
233void VariantValue::setString(const std::string &NewValue) {
234 reset();
235 Type = VT_String;
236 Value.String = new std::string(NewValue);
237}
238
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000239bool VariantValue::isMatcher() const {
240 return Type == VT_Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000241}
242
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000243const VariantMatcher &VariantValue::getMatcher() const {
244 assert(isMatcher());
245 return *Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000246}
247
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000248void VariantValue::setMatcher(const VariantMatcher &NewValue) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000249 reset();
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000250 Type = VT_Matcher;
251 Value.Matcher = new VariantMatcher(NewValue);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000252}
253
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000254std::string VariantValue::getTypeAsString() const {
255 switch (Type) {
256 case VT_String: return "String";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000257 case VT_Matcher: return getMatcher().getTypeAsString();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000258 case VT_Unsigned: return "Unsigned";
259 case VT_Nothing: return "Nothing";
260 }
261 llvm_unreachable("Invalid Type");
262}
263
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000264} // end namespace dynamic
265} // end namespace ast_matchers
266} // end namespace clang