clang  12.0.0git
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 
104  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
105  return ArgKind(Matcher.getSupportedKind())
106  .isConvertibleTo(Kind, Specificity);
107  }
108 
109 private:
110  const DynTypedMatcher Matcher;
111 };
112 
113 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
114 public:
115  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
116  : Matchers(std::move(MatchersIn)) {}
117 
118  ~PolymorphicPayload() override {}
119 
121  if (Matchers.size() != 1)
123  return Matchers[0];
124  }
125 
126  std::string getTypeAsString() const override {
127  std::string Inner;
128  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
129  if (i != 0)
130  Inner += "|";
131  Inner += Matchers[i].getSupportedKind().asStringRef();
132  }
133  return (Twine("Matcher<") + Inner + ">").str();
134  }
135 
137  getTypedMatcher(const MatcherOps &Ops) const override {
138  bool FoundIsExact = false;
139  const DynTypedMatcher *Found = nullptr;
140  int NumFound = 0;
141  for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
142  bool IsExactMatch;
143  if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
144  if (Found) {
145  if (FoundIsExact) {
146  assert(!IsExactMatch && "We should not have two exact matches.");
147  continue;
148  }
149  }
150  Found = &Matchers[i];
151  FoundIsExact = IsExactMatch;
152  ++NumFound;
153  }
154  }
155  // We only succeed if we found exactly one, or if we found an exact match.
156  if (Found && (FoundIsExact || NumFound == 1))
157  return *Found;
158  return llvm::None;
159  }
160 
161  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
162  unsigned MaxSpecificity = 0;
163  for (const DynTypedMatcher &Matcher : Matchers) {
164  unsigned ThisSpecificity;
165  if (ArgKind(Matcher.getSupportedKind())
166  .isConvertibleTo(Kind, &ThisSpecificity)) {
167  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
168  }
169  }
170  if (Specificity)
171  *Specificity = MaxSpecificity;
172  return MaxSpecificity > 0;
173  }
174 
175  const std::vector<DynTypedMatcher> Matchers;
176 };
177 
178 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
179 public:
180  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
181  std::vector<VariantMatcher> Args)
182  : Op(Op), Args(std::move(Args)) {}
183 
186  }
187 
188  std::string getTypeAsString() const override {
189  std::string Inner;
190  for (size_t i = 0, e = Args.size(); i != e; ++i) {
191  if (i != 0)
192  Inner += "&";
193  Inner += Args[i].getTypeAsString();
194  }
195  return Inner;
196  }
197 
199  getTypedMatcher(const MatcherOps &Ops) const override {
200  return Ops.constructVariadicOperator(Op, Args);
201  }
202 
203  bool isConvertibleTo(ASTNodeKind Kind, 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(std::make_shared<SinglePayload>(Matcher));
220 }
221 
223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
224  return VariantMatcher(
225  std::make_shared<PolymorphicPayload>(std::move(Matchers)));
226 }
227 
229  DynTypedMatcher::VariadicOperator Op,
230  std::vector<VariantMatcher> Args) {
231  return VariantMatcher(
232  std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
233 }
234 
236  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
237 }
238 
239 void VariantMatcher::reset() { Value.reset(); }
240 
241 std::string VariantMatcher::getTypeAsString() const {
242  if (Value) return Value->getTypeAsString();
243  return "<Nothing>";
244 }
245 
246 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
247  *this = Other;
248 }
249 
250 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
251  setBoolean(Boolean);
252 }
253 
254 VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
255  setDouble(Double);
256 }
257 
258 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
259  setUnsigned(Unsigned);
260 }
261 
262 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
263  setString(String);
264 }
265 
266 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
267  setMatcher(Matcher);
268 }
269 
271 
273  if (this == &Other) return *this;
274  reset();
275  switch (Other.Type) {
276  case VT_Boolean:
277  setBoolean(Other.getBoolean());
278  break;
279  case VT_Double:
280  setDouble(Other.getDouble());
281  break;
282  case VT_Unsigned:
283  setUnsigned(Other.getUnsigned());
284  break;
285  case VT_String:
286  setString(Other.getString());
287  break;
288  case VT_Matcher:
289  setMatcher(Other.getMatcher());
290  break;
291  case VT_Nothing:
292  Type = VT_Nothing;
293  break;
294  }
295  return *this;
296 }
297 
298 void VariantValue::reset() {
299  switch (Type) {
300  case VT_String:
301  delete Value.String;
302  break;
303  case VT_Matcher:
304  delete Value.Matcher;
305  break;
306  // Cases that do nothing.
307  case VT_Boolean:
308  case VT_Double:
309  case VT_Unsigned:
310  case VT_Nothing:
311  break;
312  }
313  Type = VT_Nothing;
314 }
315 
317  return Type == VT_Boolean;
318 }
319 
321  assert(isBoolean());
322  return Value.Boolean;
323 }
324 
325 void VariantValue::setBoolean(bool NewValue) {
326  reset();
327  Type = VT_Boolean;
328  Value.Boolean = NewValue;
329 }
330 
332  return Type == VT_Double;
333 }
334 
335 double VariantValue::getDouble() const {
336  assert(isDouble());
337  return Value.Double;
338 }
339 
340 void VariantValue::setDouble(double NewValue) {
341  reset();
342  Type = VT_Double;
343  Value.Double = NewValue;
344 }
345 
347  return Type == VT_Unsigned;
348 }
349 
350 unsigned VariantValue::getUnsigned() const {
351  assert(isUnsigned());
352  return Value.Unsigned;
353 }
354 
355 void VariantValue::setUnsigned(unsigned NewValue) {
356  reset();
357  Type = VT_Unsigned;
358  Value.Unsigned = NewValue;
359 }
360 
362  return Type == VT_String;
363 }
364 
365 const std::string &VariantValue::getString() const {
366  assert(isString());
367  return *Value.String;
368 }
369 
370 void VariantValue::setString(StringRef NewValue) {
371  reset();
372  Type = VT_String;
373  Value.String = new std::string(NewValue);
374 }
375 
377  return Type == VT_Matcher;
378 }
379 
381  assert(isMatcher());
382  return *Value.Matcher;
383 }
384 
386  reset();
387  Type = VT_Matcher;
388  Value.Matcher = new VariantMatcher(NewValue);
389 }
390 
391 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
392  switch (Kind.getArgKind()) {
393  case ArgKind::AK_Boolean:
394  if (!isBoolean())
395  return false;
396  *Specificity = 1;
397  return true;
398 
399  case ArgKind::AK_Double:
400  if (!isDouble())
401  return false;
402  *Specificity = 1;
403  return true;
404 
406  if (!isUnsigned())
407  return false;
408  *Specificity = 1;
409  return true;
410 
411  case ArgKind::AK_String:
412  if (!isString())
413  return false;
414  *Specificity = 1;
415  return true;
416 
417  case ArgKind::AK_Matcher:
418  if (!isMatcher())
419  return false;
420  return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
421  }
422  llvm_unreachable("Invalid Type");
423 }
424 
426  unsigned *Specificity) const {
427  unsigned MaxSpecificity = 0;
428  for (const ArgKind& Kind : Kinds) {
429  unsigned ThisSpecificity;
430  if (!isConvertibleTo(Kind, &ThisSpecificity))
431  continue;
432  MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
433  }
434  if (Specificity && MaxSpecificity > 0) {
435  *Specificity = MaxSpecificity;
436  }
437  return MaxSpecificity > 0;
438 }
439 
440 std::string VariantValue::getTypeAsString() const {
441  switch (Type) {
442  case VT_String: return "String";
443  case VT_Matcher: return getMatcher().getTypeAsString();
444  case VT_Boolean: return "Boolean";
445  case VT_Double: return "Double";
446  case VT_Unsigned: return "Unsigned";
447  case VT_Nothing: return "Nothing";
448  }
449  llvm_unreachable("Invalid Type");
450 }
451 
452 } // end namespace dynamic
453 } // end namespace ast_matchers
454 } // end namespace clang
std::string asString() const
String representation of the type.
The base class of the type hierarchy.
Definition: Type.h:1472
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:2679
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.
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override
llvm::Optional< DynTypedMatcher > getSingleMatcher() 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.
NodeKind
A kind of a syntax node, used for implementing casts.
Definition: Nodes.h:37
Kind
std::string getTypeAsString() const
String representation of the type of the value.
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const
Determines if the contained matcher can be converted to Kind.
Definition: VariantValue.h:187
const VariantMatcher & getMatcher() const
StringRef asStringRef() const
String representation of the kind.
const std::string & getString() const
Dataflow Directional Tag Classes.
Kind identifier.
Definition: ASTTypeTraits.h:56
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.
bool isBaseOf(ASTNodeKind Other, unsigned *Distance=nullptr) const
Returns true if this is a base kind of (or same as) Other.
void reset()
Makes the matcher the "null" matcher.
void setMatcher(const VariantMatcher &Matcher)
__DEVICE__ int max(int __a, int __b)
llvm::Optional< DynTypedMatcher > getSingleMatcher() const override
Polymorphic value type.
llvm::Optional< DynTypedMatcher > getTypedMatcher(const MatcherOps &Ops) const override
bool isString() const
String value functions.