blob: 87aca7da8533dafe1eb8c00de15f3da07a199fbf [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"
16
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000017#include "clang/Basic/LLVM.h"
Samuel Benzaquen9d028072013-08-13 14:54:51 +000018#include "llvm/ADT/STLExtras.h"
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000019
Manuel Klimekf7f295f2013-05-14 09:13:00 +000020namespace clang {
21namespace ast_matchers {
22namespace dynamic {
23
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000024VariantMatcher::MatcherOps::~MatcherOps() {}
25VariantMatcher::Payload::~Payload() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000026
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +000027class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
28public:
29 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher.clone()) {}
30
31 virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
32 Out = Matcher.get();
33 return true;
34 }
35
36 virtual std::string getTypeAsString() const {
37 return (Twine("Matcher<") + Matcher->getSupportedKind().asStringRef() + ">")
38 .str();
39 }
40
41 virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
42 return Ops.canConstructFrom(*Matcher);
43 }
44
45 virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
46 assert(hasTypedMatcher(Ops));
47 return Matcher.get();
48 }
49
50private:
51 OwningPtr<const DynTypedMatcher> Matcher;
52};
53
54class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
55public:
56 PolymorphicPayload(ArrayRef<const DynTypedMatcher *> MatchersIn) {
57 for (size_t i = 0, e = MatchersIn.size(); i != e; ++i) {
58 Matchers.push_back(MatchersIn[i]->clone());
59 }
60 }
61
62 virtual ~PolymorphicPayload() {
63 llvm::DeleteContainerPointers(Matchers);
64 }
65
66 virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
67 if (Matchers.size() != 1)
68 return false;
69 Out = Matchers[0];
70 return true;
71 }
72
73 virtual std::string getTypeAsString() const {
74 std::string Inner;
75 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
76 if (i != 0)
77 Inner += "|";
78 Inner += Matchers[i]->getSupportedKind().asStringRef();
79 }
80 return (Twine("Matcher<") + Inner + ">").str();
81 }
82
83 virtual bool hasTypedMatcher(const MatcherOps &Ops) const {
84 return getTypedMatcher(Ops) != NULL;
85 }
86
87 virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const {
88 const DynTypedMatcher* Found = NULL;
89 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
90 if (Ops.canConstructFrom(*Matchers[i])) {
91 if (Found) return NULL;
92 Found = Matchers[i];
93 }
94 }
95 return Found;
96 }
97
98private:
99 std::vector<const DynTypedMatcher *> Matchers;
100};
101
102VariantMatcher::VariantMatcher() {}
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000103
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000104VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000105 return VariantMatcher(new SinglePayload(Matcher));
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000106}
107
108VariantMatcher
109VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000110 return VariantMatcher(new PolymorphicPayload(Matchers));
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000111}
112
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000113bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000114 if (Value) return Value->getSingleMatcher(Out);
115 return false;
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000116}
117
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000118void VariantMatcher::reset() { Value.reset(); }
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000119
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000120std::string VariantMatcher::getTypeAsString() const {
Samuel Benzaquen544ae5b2013-08-22 16:38:33 +0000121 if (Value) return Value->getTypeAsString();
122 return "<Nothing>";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000123}
124
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000125VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
126 *this = Other;
127}
128
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000129VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
130 setUnsigned(Unsigned);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000131}
132
133VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
134 setString(String);
135}
136
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000137VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
138 setMatcher(Matcher);
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000139}
140
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000141VariantValue::~VariantValue() { reset(); }
142
143VariantValue &VariantValue::operator=(const VariantValue &Other) {
144 if (this == &Other) return *this;
145 reset();
146 switch (Other.Type) {
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000147 case VT_Unsigned:
148 setUnsigned(Other.getUnsigned());
149 break;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000150 case VT_String:
151 setString(Other.getString());
152 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000153 case VT_Matcher:
154 setMatcher(Other.getMatcher());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000155 break;
156 case VT_Nothing:
157 Type = VT_Nothing;
158 break;
159 }
160 return *this;
161}
162
163void VariantValue::reset() {
164 switch (Type) {
165 case VT_String:
166 delete Value.String;
167 break;
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000168 case VT_Matcher:
169 delete Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000170 break;
171 // Cases that do nothing.
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000172 case VT_Unsigned:
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000173 case VT_Nothing:
174 break;
175 }
176 Type = VT_Nothing;
177}
178
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000179bool VariantValue::isUnsigned() const {
180 return Type == VT_Unsigned;
181}
182
183unsigned VariantValue::getUnsigned() const {
184 assert(isUnsigned());
185 return Value.Unsigned;
186}
187
188void VariantValue::setUnsigned(unsigned NewValue) {
189 reset();
190 Type = VT_Unsigned;
191 Value.Unsigned = NewValue;
192}
193
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000194bool VariantValue::isString() const {
195 return Type == VT_String;
196}
197
198const std::string &VariantValue::getString() const {
199 assert(isString());
200 return *Value.String;
201}
202
203void VariantValue::setString(const std::string &NewValue) {
204 reset();
205 Type = VT_String;
206 Value.String = new std::string(NewValue);
207}
208
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000209bool VariantValue::isMatcher() const {
210 return Type == VT_Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000211}
212
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000213const VariantMatcher &VariantValue::getMatcher() const {
214 assert(isMatcher());
215 return *Value.Matcher;
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000216}
217
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000218void VariantValue::setMatcher(const VariantMatcher &NewValue) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000219 reset();
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000220 Type = VT_Matcher;
221 Value.Matcher = new VariantMatcher(NewValue);
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000222}
223
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000224std::string VariantValue::getTypeAsString() const {
225 switch (Type) {
226 case VT_String: return "String";
Samuel Benzaquen9d028072013-08-13 14:54:51 +0000227 case VT_Matcher: return getMatcher().getTypeAsString();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000228 case VT_Unsigned: return "Unsigned";
229 case VT_Nothing: return "Nothing";
230 }
231 llvm_unreachable("Invalid Type");
232}
233
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000234} // end namespace dynamic
235} // end namespace ast_matchers
236} // end namespace clang