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