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