]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
Merge ^/head r274961 through r276472.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / ASTMatchers / Dynamic / VariantValue.cpp
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
23 VariantMatcher::MatcherOps::~MatcherOps() {}
24 VariantMatcher::Payload::~Payload() {}
25
26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
27 public:
28   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
29
30   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
31     return Matcher;
32   }
33
34   virtual std::string getTypeAsString() const {
35     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
36         .str();
37   }
38
39   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:
51   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
52       : Matchers(std::move(MatchersIn)) {}
53
54   virtual ~PolymorphicPayload() {}
55
56   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
57     if (Matchers.size() != 1)
58       return llvm::Optional<DynTypedMatcher>();
59     return Matchers[0];
60   }
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 += "|";
67       Inner += Matchers[i].getSupportedKind().asStringRef();
68     }
69     return (Twine("Matcher<") + Inner + ">").str();
70   }
71
72   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:
100   VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
101                     std::vector<VariantMatcher> Args)
102       : Func(Func), Args(std::move(Args)) {}
103
104   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
105     return llvm::Optional<DynTypedMatcher>();
106   }
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);
120   }
121
122 private:
123   const ast_matchers::internal::VariadicOperatorFunction Func;
124   const std::vector<VariantMatcher> Args;
125 };
126
127 VariantMatcher::VariantMatcher() {}
128
129 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
130   return VariantMatcher(new SinglePayload(Matcher));
131 }
132
133 VariantMatcher
134 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
135   return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
136 }
137
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
144 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
145   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
146 }
147
148 void VariantMatcher::reset() { Value.reset(); }
149
150 std::string VariantMatcher::getTypeAsString() const {
151   if (Value) return Value->getTypeAsString();
152   return "<Nothing>";
153 }
154
155 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
156   *this = Other;
157 }
158
159 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
160   setUnsigned(Unsigned);
161 }
162
163 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
164   setString(String);
165 }
166
167 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
168   setMatcher(Matcher);
169 }
170
171 VariantValue::~VariantValue() { reset(); }
172
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
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
209 bool VariantValue::isUnsigned() const {
210   return Type == VT_Unsigned;
211 }
212
213 unsigned VariantValue::getUnsigned() const {
214   assert(isUnsigned());
215   return Value.Unsigned;
216 }
217
218 void VariantValue::setUnsigned(unsigned NewValue) {
219   reset();
220   Type = VT_Unsigned;
221   Value.Unsigned = NewValue;
222 }
223
224 bool VariantValue::isString() const {
225   return Type == VT_String;
226 }
227
228 const std::string &VariantValue::getString() const {
229   assert(isString());
230   return *Value.String;
231 }
232
233 void VariantValue::setString(const std::string &NewValue) {
234   reset();
235   Type = VT_String;
236   Value.String = new std::string(NewValue);
237 }
238
239 bool VariantValue::isMatcher() const {
240   return Type == VT_Matcher;
241 }
242
243 const VariantMatcher &VariantValue::getMatcher() const {
244   assert(isMatcher());
245   return *Value.Matcher;
246 }
247
248 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
249   reset();
250   Type = VT_Matcher;
251   Value.Matcher = new VariantMatcher(NewValue);
252 }
253
254 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