clang  9.0.0svn
VariantValue.cpp
Go to the documentation of this file.
1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Polymorphic value type.
11 ///
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/STLExtras.h"
17 
18 namespace clang {
19 namespace ast_matchers {
20 namespace dynamic {
21 
22 std::string ArgKind::asString() const {
23  switch (getArgKind()) {
24  case AK_Matcher:
25  return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
26  case AK_Boolean:
27  return "boolean";
28  case AK_Double:
29  return "double";
30  case AK_Unsigned:
31  return "unsigned";
32  case AK_String:
33  return "string";
34  }
35  llvm_unreachable("unhandled ArgKind");
36 }
37 
38 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
39  if (K != To.K)
40  return false;
41  if (K != AK_Matcher) {
42  if (Specificity)
43  *Specificity = 1;
44  return true;
45  }
46  unsigned Distance;
47  if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
48  return false;
49 
50  if (Specificity)
51  *Specificity = 100 - Distance;
52  return true;
53 }
54 
55 bool
56 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
57  bool &IsExactMatch) const {
58  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
59  return Matcher.canConvertTo(NodeKind);
60 }
61 
63 VariantMatcher::MatcherOps::constructVariadicOperator(
64  DynTypedMatcher::VariadicOperator Op,
65  ArrayRef<VariantMatcher> InnerMatchers) const {
66  std::vector<DynTypedMatcher> DynMatchers;
67  for (const auto &InnerMatcher : InnerMatchers) {
68  // Abort if any of the inner matchers can't be converted to
69  // Matcher<T>.
70  if (!InnerMatcher.Value)
71  return llvm::None;
73  InnerMatcher.Value->getTypedMatcher(*this);
74  if (!Inner)
75  return llvm::None;
76  DynMatchers.push_back(*Inner);
77  }
78  return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
79 }
80 
81 VariantMatcher::Payload::~Payload() {}
82 
83 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
84 public:
85  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
86 
88  return Matcher;
89  }
90 
91  std::string getTypeAsString() const override {
92  return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
93  .str();
94  }
95 
97  getTypedMatcher(const MatcherOps &Ops) const override {
98  bool Ignore;
99  if (Ops.canConstructFrom(Matcher, Ignore))
100  return Matcher;
101  return llvm::None;
102  }
103 
105  unsigned *Specificity) const override {
106  return ArgKind(Matcher.getSupportedKind())
107  .isConvertibleTo(Kind, Specificity);
108  }
109 
110 private:
111  const DynTypedMatcher Matcher;
112 };
113 
114 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
115 public:
116  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
117  : Matchers(std::move(MatchersIn)) {}
118 
119  ~PolymorphicPayload() override {}
120 
122  if (Matchers.size() != 1)
124  return Matchers[0];
125  }
126 
127  std::string getTypeAsString() const override {
128  std::string Inner;
129  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
130  if (i != 0)
131  Inner += "|";
132  Inner += Matchers[i].getSupportedKind().asStringRef();
133  }
134  return (Twine("Matcher<") + Inner + ">").str();
135  }
136 
138  getTypedMatcher(const MatcherOps &Ops) const override {
139  bool FoundIsExact = false;
140  const DynTypedMatcher *Found = nullptr;
141  int NumFound = 0;
142  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
143  bool IsExactMatch;
144  if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
145  if (Found) {
146  if (FoundIsExact) {
147  assert(!IsExactMatch && "We should not have two exact matches.");
148  continue;
149  }
150  }
151  Found = &Matchers[i];
152  FoundIsExact = IsExactMatch;
153  ++NumFound;
154  }
155  }
156  // We only succeed if we found exactly one, or if we found an exact match.
157  if (Found && (FoundIsExact || NumFound == 1))
158  return *Found;
159  return llvm::None;
160  }
161 
163  unsigned *Specificity) const override {
164  unsigned MaxSpecificity = 0;
165  for (const DynTypedMatcher &Matcher : Matchers) {
166  unsigned ThisSpecificity;
167  if (ArgKind(Matcher.getSupportedKind())
168  .isConvertibleTo(Kind, &ThisSpecificity)) {
169  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
170  }
171  }
172  if (Specificity)
173  *Specificity = MaxSpecificity;
174  return MaxSpecificity > 0;
175  }
176 
177  const std::vector<DynTypedMatcher> Matchers;
178 };
179 
180 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
181 public:
182  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
183  std::vector<VariantMatcher> Args)
184  : Op(Op), Args(std::move(Args)) {}
185 
188  }
189 
190  std::string getTypeAsString() const override {
191  std::string Inner;
192  for (size_t i = 0, e = Args.size(); i != e; ++i) {
193  if (i != 0)
194  Inner += "&";
195  Inner += Args[i].getTypeAsString();
196  }
197  return Inner;
198  }
199 
201  getTypedMatcher(const MatcherOps &Ops) const override {
202  return Ops.constructVariadicOperator(Op, Args);
203  }
204 
206  unsigned *Specificity) const override {
207  for (const VariantMatcher &Matcher : Args) {
208  if (!Matcher.isConvertibleTo(Kind, Specificity))
209  return false;
210  }
211  return true;
212  }
213 
214 private:
215  const DynTypedMatcher::VariadicOperator Op;
216  const std::vector<VariantMatcher> Args;
217 };
218 
220 
221 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
222  return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
223 }
224 
226 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
227  return VariantMatcher(
228  std::make_shared<PolymorphicPayload>(std::move(Matchers)));
229 }
230 
232  DynTypedMatcher::VariadicOperator Op,
233  std::vector<VariantMatcher> Args) {
234  return VariantMatcher(
235  std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
236 }
237 
239  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
240 }
241 
242 void VariantMatcher::reset() { Value.reset(); }
243 
244 std::string VariantMatcher::getTypeAsString() const {
245  if (Value) return Value->getTypeAsString();
246  return "<Nothing>";
247 }
248 
249 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
250  *this = Other;
251 }
252 
253 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
254  setBoolean(Boolean);
255 }
256 
257 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
258  setDouble(Double);
259 }
260 
261 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
262  setUnsigned(Unsigned);
263 }
264 
265 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
266  setString(String);
267 }
268 
269 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
270  setMatcher(Matcher);
271 }
272 
274 
276  if (this == &Other) return *this;
277  reset();
278  switch (Other.Type) {
279  case VT_Boolean:
280  setBoolean(Other.getBoolean());
281  break;
282  case VT_Double:
283  setDouble(Other.getDouble());
284  break;
285  case VT_Unsigned:
286  setUnsigned(Other.getUnsigned());
287  break;
288  case VT_String:
289  setString(Other.getString());
290  break;
291  case VT_Matcher:
292  setMatcher(Other.getMatcher());
293  break;
294  case VT_Nothing:
295  Type = VT_Nothing;
296  break;
297  }
298  return *this;
299 }
300 
301 void VariantValue::reset() {
302  switch (Type) {
303  case VT_String:
304  delete Value.String;
305  break;
306  case VT_Matcher:
307  delete Value.Matcher;
308  break;
309  // Cases that do nothing.
310  case VT_Boolean:
311  case VT_Double:
312  case VT_Unsigned:
313  case VT_Nothing:
314  break;
315  }
316  Type = VT_Nothing;
317 }
318 
320  return Type == VT_Boolean;
321 }
322 
324  assert(isBoolean());
325  return Value.Boolean;
326 }
327 
328 void VariantValue::setBoolean(bool NewValue) {
329  reset();
330  Type = VT_Boolean;
331  Value.Boolean = NewValue;
332 }
333 
335  return Type == VT_Double;
336 }
337 
338 double VariantValue::getDouble() const {
339  assert(isDouble());
340  return Value.Double;
341 }
342 
343 void VariantValue::setDouble(double NewValue) {
344  reset();
345  Type = VT_Double;
346  Value.Double = NewValue;
347 }
348 
350  return Type == VT_Unsigned;
351 }
352 
353 unsigned VariantValue::getUnsigned() const {
354  assert(isUnsigned());
355  return Value.Unsigned;
356 }
357 
358 void VariantValue::setUnsigned(unsigned NewValue) {
359  reset();
360  Type = VT_Unsigned;
361  Value.Unsigned = NewValue;
362 }
363 
365  return Type == VT_String;
366 }
367 
368 const std::string &VariantValue::getString() const {
369  assert(isString());
370  return *Value.String;
371 }
372 
373 void VariantValue::setString(StringRef NewValue) {
374  reset();
375  Type = VT_String;
376  Value.String = new std::string(NewValue);
377 }
378 
380  return Type == VT_Matcher;
381 }
382 
384  assert(isMatcher());
385  return *Value.Matcher;
386 }
387 
389  reset();
390  Type = VT_Matcher;
391  Value.Matcher = new VariantMatcher(NewValue);
392 }
393 
394 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
395  switch (Kind.getArgKind()) {
396  case ArgKind::AK_Boolean:
397  if (!isBoolean())
398  return false;
399  *Specificity = 1;
400  return true;
401 
402  case ArgKind::AK_Double:
403  if (!isDouble())
404  return false;
405  *Specificity = 1;
406  return true;
407 
409  if (!isUnsigned())
410  return false;
411  *Specificity = 1;
412  return true;
413 
414  case ArgKind::AK_String:
415  if (!isString())
416  return false;
417  *Specificity = 1;
418  return true;
419 
420  case ArgKind::AK_Matcher:
421  if (!isMatcher())
422  return false;
423  return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
424  }
425  llvm_unreachable("Invalid Type");
426 }
427 
429  unsigned *Specificity) const {
430  unsigned MaxSpecificity = 0;
431  for (const ArgKind& Kind : Kinds) {
432  unsigned ThisSpecificity;
433  if (!isConvertibleTo(Kind, &ThisSpecificity))
434  continue;
435  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
436  }
437  if (Specificity && MaxSpecificity > 0) {
438  *Specificity = MaxSpecificity;
439  }
440  return MaxSpecificity > 0;
441 }
442 
443 std::string VariantValue::getTypeAsString() const {
444  switch (Type) {
445  case VT_String: return "String";
446  case VT_Matcher: return getMatcher().getTypeAsString();
447  case VT_Boolean: return "Boolean";
448  case VT_Double: return "Double";
449  case VT_Unsigned: return "Unsigned";
450  case VT_Nothing: return "Nothing";
451  }
452  llvm_unreachable("Invalid Type");
453 }
454 
455 } // end namespace dynamic
456 } // end namespace ast_matchers
457 } // 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:1433
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.
long i
Definition: xmmintrin.h:1456
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:2274
__DEVICE__ int max(int __a, int __b)
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:43
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.
NodeKind
A kind of a syntax node, used for implementing casts.
Definition: Nodes.h:25
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)
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:187
ast_type_traits::ASTNodeKind getMatcherKind() const
Definition: VariantValue.h:50
Polymorphic value type.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
bool isString() const
String value functions.