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<") + 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
38bool 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
55bool
56VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
57                                             bool &IsExactMatch) const {
58  IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
59  return Matcher.canConvertTo(NodeKind);
60}
61
62llvm::Optional<DynTypedMatcher>
63VariantMatcher::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;
72    llvm::Optional<DynTypedMatcher> Inner =
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
81VariantMatcher::Payload::~Payload() {}
82
83class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
84public:
85  SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
86
87  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
88    return Matcher;
89  }
90
91  std::string getTypeAsString() const override {
92    return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
93        .str();
94  }
95
96  llvm::Optional<DynTypedMatcher>
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(ast_type_traits::ASTNodeKind Kind,
105                       unsigned *Specificity) const override {
106    return ArgKind(Matcher.getSupportedKind())
107        .isConvertibleTo(Kind, Specificity);
108  }
109
110private:
111  const DynTypedMatcher Matcher;
112};
113
114class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
115public:
116  PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
117      : Matchers(std::move(MatchersIn)) {}
118
119  ~PolymorphicPayload() override {}
120
121  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
122    if (Matchers.size() != 1)
123      return llvm::Optional<DynTypedMatcher>();
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
137  llvm::Optional<DynTypedMatcher>
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
162  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
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
180class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
181public:
182  VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
183                    std::vector<VariantMatcher> Args)
184      : Op(Op), Args(std::move(Args)) {}
185
186  llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
187    return llvm::Optional<DynTypedMatcher>();
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
200  llvm::Optional<DynTypedMatcher>
201  getTypedMatcher(const MatcherOps &Ops) const override {
202    return Ops.constructVariadicOperator(Op, Args);
203  }
204
205  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
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
214private:
215  const DynTypedMatcher::VariadicOperator Op;
216  const std::vector<VariantMatcher> Args;
217};
218
219VariantMatcher::VariantMatcher() {}
220
221VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
222  return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
223}
224
225VariantMatcher
226VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
227  return VariantMatcher(
228      std::make_shared<PolymorphicPayload>(std::move(Matchers)));
229}
230
231VariantMatcher VariantMatcher::VariadicOperatorMatcher(
232    DynTypedMatcher::VariadicOperator Op,
233    std::vector<VariantMatcher> Args) {
234  return VariantMatcher(
235      std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
236}
237
238llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
239  return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
240}
241
242void VariantMatcher::reset() { Value.reset(); }
243
244std::string VariantMatcher::getTypeAsString() const {
245  if (Value) return Value->getTypeAsString();
246  return "<Nothing>";
247}
248
249VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
250  *this = Other;
251}
252
253VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
254  setBoolean(Boolean);
255}
256
257VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
258  setDouble(Double);
259}
260
261VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
262  setUnsigned(Unsigned);
263}
264
265VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
266  setString(String);
267}
268
269VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
270  setMatcher(Matcher);
271}
272
273VariantValue::~VariantValue() { reset(); }
274
275VariantValue &VariantValue::operator=(const VariantValue &Other) {
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
301void 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
319bool VariantValue::isBoolean() const {
320  return Type == VT_Boolean;
321}
322
323bool VariantValue::getBoolean() const {
324  assert(isBoolean());
325  return Value.Boolean;
326}
327
328void VariantValue::setBoolean(bool NewValue) {
329  reset();
330  Type = VT_Boolean;
331  Value.Boolean = NewValue;
332}
333
334bool VariantValue::isDouble() const {
335  return Type == VT_Double;
336}
337
338double VariantValue::getDouble() const {
339  assert(isDouble());
340  return Value.Double;
341}
342
343void VariantValue::setDouble(double NewValue) {
344  reset();
345  Type = VT_Double;
346  Value.Double = NewValue;
347}
348
349bool VariantValue::isUnsigned() const {
350  return Type == VT_Unsigned;
351}
352
353unsigned VariantValue::getUnsigned() const {
354  assert(isUnsigned());
355  return Value.Unsigned;
356}
357
358void VariantValue::setUnsigned(unsigned NewValue) {
359  reset();
360  Type = VT_Unsigned;
361  Value.Unsigned = NewValue;
362}
363
364bool VariantValue::isString() const {
365  return Type == VT_String;
366}
367
368const std::string &VariantValue::getString() const {
369  assert(isString());
370  return *Value.String;
371}
372
373void VariantValue::setString(StringRef NewValue) {
374  reset();
375  Type = VT_String;
376  Value.String = new std::string(NewValue);
377}
378
379bool VariantValue::isMatcher() const {
380  return Type == VT_Matcher;
381}
382
383const VariantMatcher &VariantValue::getMatcher() const {
384  assert(isMatcher());
385  return *Value.Matcher;
386}
387
388void VariantValue::setMatcher(const VariantMatcher &NewValue) {
389  reset();
390  Type = VT_Matcher;
391  Value.Matcher = new VariantMatcher(NewValue);
392}
393
394bool 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
408  case ArgKind::AK_Unsigned:
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
428bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
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
443std::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
458