clang  6.0.0svn
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_Boolean:
28  return "boolean";
29  case AK_Double:
30  return "double";
31  case AK_Unsigned:
32  return "unsigned";
33  case AK_String:
34  return "string";
35  }
36  llvm_unreachable("unhandled ArgKind");
37 }
38 
39 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
40  if (K != To.K)
41  return false;
42  if (K != AK_Matcher) {
43  if (Specificity)
44  *Specificity = 1;
45  return true;
46  }
47  unsigned Distance;
48  if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
49  return false;
50 
51  if (Specificity)
52  *Specificity = 100 - Distance;
53  return true;
54 }
55 
56 bool
57 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
58  bool &IsExactMatch) const {
59  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
60  return Matcher.canConvertTo(NodeKind);
61 }
62 
64 VariantMatcher::MatcherOps::constructVariadicOperator(
65  DynTypedMatcher::VariadicOperator Op,
66  ArrayRef<VariantMatcher> InnerMatchers) const {
67  std::vector<DynTypedMatcher> DynMatchers;
68  for (const auto &InnerMatcher : InnerMatchers) {
69  // Abort if any of the inner matchers can't be converted to
70  // Matcher<T>.
71  if (!InnerMatcher.Value)
72  return llvm::None;
74  InnerMatcher.Value->getTypedMatcher(*this);
75  if (!Inner)
76  return llvm::None;
77  DynMatchers.push_back(*Inner);
78  }
79  return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
80 }
81 
82 VariantMatcher::Payload::~Payload() {}
83 
84 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
85 public:
86  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
87 
89  return Matcher;
90  }
91 
92  std::string getTypeAsString() const override {
93  return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
94  .str();
95  }
96 
98  getTypedMatcher(const MatcherOps &Ops) const override {
99  bool Ignore;
100  if (Ops.canConstructFrom(Matcher, Ignore))
101  return Matcher;
102  return llvm::None;
103  }
104 
106  unsigned *Specificity) const override {
107  return ArgKind(Matcher.getSupportedKind())
108  .isConvertibleTo(Kind, Specificity);
109  }
110 
111 private:
112  const DynTypedMatcher Matcher;
113 };
114 
115 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
116 public:
117  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
118  : Matchers(std::move(MatchersIn)) {}
119 
120  ~PolymorphicPayload() override {}
121 
123  if (Matchers.size() != 1)
125  return Matchers[0];
126  }
127 
128  std::string getTypeAsString() const override {
129  std::string Inner;
130  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
131  if (i != 0)
132  Inner += "|";
133  Inner += Matchers[i].getSupportedKind().asStringRef();
134  }
135  return (Twine("Matcher<") + Inner + ">").str();
136  }
137 
139  getTypedMatcher(const MatcherOps &Ops) const override {
140  bool FoundIsExact = false;
141  const DynTypedMatcher *Found = nullptr;
142  int NumFound = 0;
143  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
144  bool IsExactMatch;
145  if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
146  if (Found) {
147  if (FoundIsExact) {
148  assert(!IsExactMatch && "We should not have two exact matches.");
149  continue;
150  }
151  }
152  Found = &Matchers[i];
153  FoundIsExact = IsExactMatch;
154  ++NumFound;
155  }
156  }
157  // We only succeed if we found exactly one, or if we found an exact match.
158  if (Found && (FoundIsExact || NumFound == 1))
159  return *Found;
160  return llvm::None;
161  }
162 
164  unsigned *Specificity) const override {
165  unsigned MaxSpecificity = 0;
166  for (const DynTypedMatcher &Matcher : Matchers) {
167  unsigned ThisSpecificity;
168  if (ArgKind(Matcher.getSupportedKind())
169  .isConvertibleTo(Kind, &ThisSpecificity)) {
170  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
171  }
172  }
173  if (Specificity)
174  *Specificity = MaxSpecificity;
175  return MaxSpecificity > 0;
176  }
177 
178  const std::vector<DynTypedMatcher> Matchers;
179 };
180 
181 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
182 public:
183  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
184  std::vector<VariantMatcher> Args)
185  : Op(Op), Args(std::move(Args)) {}
186 
189  }
190 
191  std::string getTypeAsString() const override {
192  std::string Inner;
193  for (size_t i = 0, e = Args.size(); i != e; ++i) {
194  if (i != 0)
195  Inner += "&";
196  Inner += Args[i].getTypeAsString();
197  }
198  return Inner;
199  }
200 
202  getTypedMatcher(const MatcherOps &Ops) const override {
203  return Ops.constructVariadicOperator(Op, Args);
204  }
205 
207  unsigned *Specificity) const override {
208  for (const VariantMatcher &Matcher : Args) {
209  if (!Matcher.isConvertibleTo(Kind, Specificity))
210  return false;
211  }
212  return true;
213  }
214 
215 private:
216  const DynTypedMatcher::VariadicOperator Op;
217  const std::vector<VariantMatcher> Args;
218 };
219 
221 
222 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
223  return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
224 }
225 
227 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
228  return VariantMatcher(
229  std::make_shared<PolymorphicPayload>(std::move(Matchers)));
230 }
231 
233  DynTypedMatcher::VariadicOperator Op,
234  std::vector<VariantMatcher> Args) {
235  return VariantMatcher(
236  std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
237 }
238 
240  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
241 }
242 
243 void VariantMatcher::reset() { Value.reset(); }
244 
245 std::string VariantMatcher::getTypeAsString() const {
246  if (Value) return Value->getTypeAsString();
247  return "<Nothing>";
248 }
249 
250 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
251  *this = Other;
252 }
253 
254 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
255  setBoolean(Boolean);
256 }
257 
258 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
259  setDouble(Double);
260 }
261 
262 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
263  setUnsigned(Unsigned);
264 }
265 
266 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
267  setString(String);
268 }
269 
270 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
271  setMatcher(Matcher);
272 }
273 
275 
277  if (this == &Other) return *this;
278  reset();
279  switch (Other.Type) {
280  case VT_Boolean:
281  setBoolean(Other.getBoolean());
282  break;
283  case VT_Double:
284  setDouble(Other.getDouble());
285  break;
286  case VT_Unsigned:
287  setUnsigned(Other.getUnsigned());
288  break;
289  case VT_String:
290  setString(Other.getString());
291  break;
292  case VT_Matcher:
293  setMatcher(Other.getMatcher());
294  break;
295  case VT_Nothing:
296  Type = VT_Nothing;
297  break;
298  }
299  return *this;
300 }
301 
302 void VariantValue::reset() {
303  switch (Type) {
304  case VT_String:
305  delete Value.String;
306  break;
307  case VT_Matcher:
308  delete Value.Matcher;
309  break;
310  // Cases that do nothing.
311  case VT_Boolean:
312  case VT_Double:
313  case VT_Unsigned:
314  case VT_Nothing:
315  break;
316  }
317  Type = VT_Nothing;
318 }
319 
321  return Type == VT_Boolean;
322 }
323 
325  assert(isBoolean());
326  return Value.Boolean;
327 }
328 
329 void VariantValue::setBoolean(bool NewValue) {
330  reset();
331  Type = VT_Boolean;
332  Value.Boolean = NewValue;
333 }
334 
336  return Type == VT_Double;
337 }
338 
339 double VariantValue::getDouble() const {
340  assert(isDouble());
341  return Value.Double;
342 }
343 
344 void VariantValue::setDouble(double NewValue) {
345  reset();
346  Type = VT_Double;
347  Value.Double = NewValue;
348 }
349 
351  return Type == VT_Unsigned;
352 }
353 
354 unsigned VariantValue::getUnsigned() const {
355  assert(isUnsigned());
356  return Value.Unsigned;
357 }
358 
359 void VariantValue::setUnsigned(unsigned NewValue) {
360  reset();
361  Type = VT_Unsigned;
362  Value.Unsigned = NewValue;
363 }
364 
366  return Type == VT_String;
367 }
368 
369 const std::string &VariantValue::getString() const {
370  assert(isString());
371  return *Value.String;
372 }
373 
374 void VariantValue::setString(StringRef NewValue) {
375  reset();
376  Type = VT_String;
377  Value.String = new std::string(NewValue);
378 }
379 
381  return Type == VT_Matcher;
382 }
383 
385  assert(isMatcher());
386  return *Value.Matcher;
387 }
388 
390  reset();
391  Type = VT_Matcher;
392  Value.Matcher = new VariantMatcher(NewValue);
393 }
394 
395 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
396  switch (Kind.getArgKind()) {
397  case ArgKind::AK_Boolean:
398  if (!isBoolean())
399  return false;
400  *Specificity = 1;
401  return true;
402 
403  case ArgKind::AK_Double:
404  if (!isDouble())
405  return false;
406  *Specificity = 1;
407  return true;
408 
410  if (!isUnsigned())
411  return false;
412  *Specificity = 1;
413  return true;
414 
415  case ArgKind::AK_String:
416  if (!isString())
417  return false;
418  *Specificity = 1;
419  return true;
420 
421  case ArgKind::AK_Matcher:
422  if (!isMatcher())
423  return false;
424  return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
425  }
426  llvm_unreachable("Invalid Type");
427 }
428 
430  unsigned *Specificity) const {
431  unsigned MaxSpecificity = 0;
432  for (const ArgKind& Kind : Kinds) {
433  unsigned ThisSpecificity;
434  if (!isConvertibleTo(Kind, &ThisSpecificity))
435  continue;
436  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
437  }
438  if (Specificity && MaxSpecificity > 0) {
439  *Specificity = MaxSpecificity;
440  }
441  return MaxSpecificity > 0;
442 }
443 
444 std::string VariantValue::getTypeAsString() const {
445  switch (Type) {
446  case VT_String: return "String";
447  case VT_Matcher: return getMatcher().getTypeAsString();
448  case VT_Boolean: return "Boolean";
449  case VT_Double: return "Double";
450  case VT_Unsigned: return "Unsigned";
451  case VT_Nothing: return "Nothing";
452  }
453  llvm_unreachable("Invalid Type");
454 }
455 
456 } // end namespace dynamic
457 } // end namespace ast_matchers
458 } // end namespace clang
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const override
std::string asString() const
String representation of the type.
StringRef asStringRef() const
String representation of the kind.
The base class of the type hierarchy.
Definition: Type.h:1353
llvm::Optional< DynTypedMatcher > getSingleMatcher() const
Return a single matcher, if there is no ambiguity.
VariantValue & operator=(const VariantValue &Other)
static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher)
Clones the provided matcher.
bool isBoolean() const
Boolean value functions.
bool isUnsigned() const
Unsigned value functions.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
static VariantMatcher VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, std::vector< VariantMatcher > Args)
Creates a &#39;variadic&#39; operator matcher.
Definition: Format.h:1900
PolymorphicPayload(std::vector< DynTypedMatcher > MatchersIn)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
bool isConvertibleTo(ArgKind To, unsigned *Specificity) const
Determines if this type can be converted to To.
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
ArgKind(Kind K)
Constructor for non-matcher types.
Definition: VariantValue.h:44
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, std::vector< VariantMatcher > Args)
std::string getTypeAsString() const
String representation of the type of the value.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
bool isDouble() const
Double value functions.
Kind
std::string getTypeAsString() const
String representation of the type of the value.
const VariantMatcher & getMatcher() const
const std::string & getString() const
bool isBaseOf(ASTNodeKind Other, unsigned *Distance=nullptr) const
Returns true if this is a base kind of (or same as) Other.
Dataflow Directional Tag Classes.
bool isMatcher() const
Matcher value functions.
bool isConvertibleTo(ArgKind Kind, unsigned *Specificity) const
Determines if the contained value can be converted to Kind.
static VariantMatcher PolymorphicMatcher(std::vector< DynTypedMatcher > Matchers)
Clones the provided matchers.
void reset()
Makes the matcher the "null" matcher.
void setMatcher(const VariantMatcher &Matcher)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
llvm::Optional< DynTypedMatcher > getSingleMatcher() const override
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const
Determines if the contained matcher can be converted to Kind.
Definition: VariantValue.h:188
ast_type_traits::ASTNodeKind getMatcherKind() const
Definition: VariantValue.h:51
Polymorphic value type.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
bool isString() const
String value functions.