clang  3.7.0
VariantValue.cpp
Go to the documentation of this file.
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 
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 std::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 
35 bool 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 
52 bool
53 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
54  bool &IsExactMatch) const {
55  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
56  return Matcher.canConvertTo(NodeKind);
57 }
58 
60 VariantMatcher::MatcherOps::constructVariadicOperator(
61  DynTypedMatcher::VariadicOperator Op,
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;
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 
78 VariantMatcher::Payload::~Payload() {}
79 
80 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
81 public:
82  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
83 
85  return Matcher;
86  }
87 
88  std::string getTypeAsString() const override {
89  return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
90  .str();
91  }
92 
94  getTypedMatcher(const MatcherOps &Ops) const override {
95  bool Ignore;
96  if (Ops.canConstructFrom(Matcher, Ignore))
97  return Matcher;
98  return llvm::None;
99  }
100 
102  unsigned *Specificity) const override {
103  return ArgKind(Matcher.getSupportedKind())
104  .isConvertibleTo(Kind, Specificity);
105  }
106 
107 private:
108  const DynTypedMatcher Matcher;
109 };
110 
111 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
112 public:
113  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
114  : Matchers(std::move(MatchersIn)) {}
115 
116  ~PolymorphicPayload() override {}
117 
119  if (Matchers.size() != 1)
121  return Matchers[0];
122  }
123 
124  std::string getTypeAsString() const override {
125  std::string Inner;
126  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
127  if (i != 0)
128  Inner += "|";
129  Inner += Matchers[i].getSupportedKind().asStringRef();
130  }
131  return (Twine("Matcher<") + Inner + ">").str();
132  }
133 
135  getTypedMatcher(const MatcherOps &Ops) const override {
136  bool FoundIsExact = false;
137  const DynTypedMatcher *Found = nullptr;
138  int NumFound = 0;
139  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
140  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  }
148  Found = &Matchers[i];
149  FoundIsExact = IsExactMatch;
150  ++NumFound;
151  }
152  }
153  // We only succeed if we found exactly one, or if we found an exact match.
154  if (Found && (FoundIsExact || NumFound == 1))
155  return *Found;
156  return llvm::None;
157  }
158 
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;
172  }
173 
174  const std::vector<DynTypedMatcher> Matchers;
175 };
176 
177 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
178 public:
179  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
180  std::vector<VariantMatcher> Args)
181  : Op(Op), Args(std::move(Args)) {}
182 
185  }
186 
187  std::string getTypeAsString() const override {
188  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 
198  getTypedMatcher(const MatcherOps &Ops) const override {
199  return Ops.constructVariadicOperator(Op, Args);
200  }
201 
203  unsigned *Specificity) const override {
204  for (const VariantMatcher &Matcher : Args) {
205  if (!Matcher.isConvertibleTo(Kind, Specificity))
206  return false;
207  }
208  return true;
209  }
210 
211 private:
212  const DynTypedMatcher::VariadicOperator Op;
213  const std::vector<VariantMatcher> Args;
214 };
215 
217 
218 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
219  return VariantMatcher(new SinglePayload(Matcher));
220 }
221 
223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224  return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
225 }
226 
228  DynTypedMatcher::VariadicOperator Op,
229  std::vector<VariantMatcher> Args) {
230  return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
231 }
232 
234  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
235 }
236 
237 void VariantMatcher::reset() { Value.reset(); }
238 
239 std::string VariantMatcher::getTypeAsString() const {
240  if (Value) return Value->getTypeAsString();
241  return "<Nothing>";
242 }
243 
244 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
245  *this = Other;
246 }
247 
248 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
249  setUnsigned(Unsigned);
250 }
251 
252 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
253  setString(String);
254 }
255 
256 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
257  setMatcher(Matcher);
258 }
259 
261 
263  if (this == &Other) return *this;
264  reset();
265  switch (Other.Type) {
266  case VT_Unsigned:
267  setUnsigned(Other.getUnsigned());
268  break;
269  case VT_String:
270  setString(Other.getString());
271  break;
272  case VT_Matcher:
273  setMatcher(Other.getMatcher());
274  break;
275  case VT_Nothing:
276  Type = VT_Nothing;
277  break;
278  }
279  return *this;
280 }
281 
282 void VariantValue::reset() {
283  switch (Type) {
284  case VT_String:
285  delete Value.String;
286  break;
287  case VT_Matcher:
288  delete Value.Matcher;
289  break;
290  // Cases that do nothing.
291  case VT_Unsigned:
292  case VT_Nothing:
293  break;
294  }
295  Type = VT_Nothing;
296 }
297 
299  return Type == VT_Unsigned;
300 }
301 
302 unsigned VariantValue::getUnsigned() const {
303  assert(isUnsigned());
304  return Value.Unsigned;
305 }
306 
307 void VariantValue::setUnsigned(unsigned NewValue) {
308  reset();
309  Type = VT_Unsigned;
310  Value.Unsigned = NewValue;
311 }
312 
314  return Type == VT_String;
315 }
316 
317 const std::string &VariantValue::getString() const {
318  assert(isString());
319  return *Value.String;
320 }
321 
322 void VariantValue::setString(StringRef NewValue) {
323  reset();
324  Type = VT_String;
325  Value.String = new std::string(NewValue);
326 }
327 
329  return Type == VT_Matcher;
330 }
331 
333  assert(isMatcher());
334  return *Value.Matcher;
335 }
336 
338  reset();
339  Type = VT_Matcher;
340  Value.Matcher = new VariantMatcher(NewValue);
341 }
342 
343 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
344  switch (Kind.getArgKind()) {
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 
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 
380 std::string VariantValue::getTypeAsString() const {
381  switch (Type) {
382  case VT_String: return "String";
383  case VT_Matcher: return getMatcher().getTypeAsString();
384  case VT_Unsigned: return "Unsigned";
385  case VT_Nothing: return "Nothing";
386  }
387  llvm_unreachable("Invalid Type");
388 }
389 
390 } // end namespace dynamic
391 } // end namespace ast_matchers
392 } // end namespace clang
const MatchFinder::MatchersByType * Matchers
bool isMatcher() const
Matcher value functions.
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const override
std::string getTypeAsString() const
String representation of the type of the value.
const DynTypedMatcher *const Matcher
VariantValue & operator=(const VariantValue &Other)
static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher)
Clones the provided matcher.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
static VariantMatcher VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, std::vector< VariantMatcher > Args)
Creates a 'variadic' operator matcher.
bool isUnsigned() const
Unsigned value functions.
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const
Determines if the contained matcher can be converted to Kind.
Definition: VariantValue.h:187
bool isBaseOf(ASTNodeKind Other, unsigned *Distance=nullptr) const
Returns true if this is a base kind of (or same as) Other.
std::vector< DynTypedMatcher > InnerMatchers
PolymorphicPayload(std::vector< DynTypedMatcher > MatchersIn)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const IntrusiveRefCntPtr< DynMatcherInterface > InnerMatcher
ast_type_traits::ASTNodeKind getMatcherKind() const
Definition: VariantValue.h:50
llvm::Optional< DynTypedMatcher > getSingleMatcher() const override
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const override
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const override
llvm::Optional< DynTypedMatcher > getSingleMatcher() const override
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, std::vector< VariantMatcher > Args)
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
std::string asString() const
String representation of the type.
Kind
bool isConvertibleTo(ArgKind To, unsigned *Specificity) const
Determines if this type can be converted to To.
StringRef asStringRef() const
String representation of the kind.
std::string getTypeAsString() const
String representation of the type of the value.
static VariantMatcher PolymorphicMatcher(std::vector< DynTypedMatcher > Matchers)
Clones the provided matchers.
void reset()
Makes the matcher the "null" matcher.
void setMatcher(const VariantMatcher &Matcher)
bool isString() const
String value functions.
llvm::Optional< DynTypedMatcher > getSingleMatcher() const override
bool isConvertibleTo(ArgKind Kind, unsigned *Specificity) const
Determines if the contained value can be converted to Kind.
const std::string & getString() const
Polymorphic value type.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
const VariantMatcher & getMatcher() const
llvm::Optional< DynTypedMatcher > getSingleMatcher() const
Return a single matcher, if there is no ambiguity.