xref: /freebsd/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Polymorphic value type.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/ASTMatchers/Dynamic/VariantValue.h"
150b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace clang {
190b57cec5SDimitry Andric namespace ast_matchers {
200b57cec5SDimitry Andric namespace dynamic {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric std::string ArgKind::asString() const {
230b57cec5SDimitry Andric   switch (getArgKind()) {
240b57cec5SDimitry Andric   case AK_Matcher:
250b57cec5SDimitry Andric     return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
260b57cec5SDimitry Andric   case AK_Boolean:
270b57cec5SDimitry Andric     return "boolean";
280b57cec5SDimitry Andric   case AK_Double:
290b57cec5SDimitry Andric     return "double";
300b57cec5SDimitry Andric   case AK_Unsigned:
310b57cec5SDimitry Andric     return "unsigned";
320b57cec5SDimitry Andric   case AK_String:
330b57cec5SDimitry Andric     return "string";
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric   llvm_unreachable("unhandled ArgKind");
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
390b57cec5SDimitry Andric   if (K != To.K)
400b57cec5SDimitry Andric     return false;
410b57cec5SDimitry Andric   if (K != AK_Matcher) {
420b57cec5SDimitry Andric     if (Specificity)
430b57cec5SDimitry Andric       *Specificity = 1;
440b57cec5SDimitry Andric     return true;
450b57cec5SDimitry Andric   }
460b57cec5SDimitry Andric   unsigned Distance;
470b57cec5SDimitry Andric   if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
480b57cec5SDimitry Andric     return false;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   if (Specificity)
510b57cec5SDimitry Andric     *Specificity = 100 - Distance;
520b57cec5SDimitry Andric   return true;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric bool
560b57cec5SDimitry Andric VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
570b57cec5SDimitry Andric                                              bool &IsExactMatch) const {
580b57cec5SDimitry Andric   IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
590b57cec5SDimitry Andric   return Matcher.canConvertTo(NodeKind);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
62*e8d8bef9SDimitry Andric DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
63*e8d8bef9SDimitry Andric     const DynTypedMatcher &Matcher) const {
64*e8d8bef9SDimitry Andric   return Matcher.dynCastTo(NodeKind);
65*e8d8bef9SDimitry Andric }
66*e8d8bef9SDimitry Andric 
670b57cec5SDimitry Andric llvm::Optional<DynTypedMatcher>
680b57cec5SDimitry Andric VariantMatcher::MatcherOps::constructVariadicOperator(
690b57cec5SDimitry Andric     DynTypedMatcher::VariadicOperator Op,
700b57cec5SDimitry Andric     ArrayRef<VariantMatcher> InnerMatchers) const {
710b57cec5SDimitry Andric   std::vector<DynTypedMatcher> DynMatchers;
720b57cec5SDimitry Andric   for (const auto &InnerMatcher : InnerMatchers) {
730b57cec5SDimitry Andric     // Abort if any of the inner matchers can't be converted to
740b57cec5SDimitry Andric     // Matcher<T>.
750b57cec5SDimitry Andric     if (!InnerMatcher.Value)
760b57cec5SDimitry Andric       return llvm::None;
770b57cec5SDimitry Andric     llvm::Optional<DynTypedMatcher> Inner =
780b57cec5SDimitry Andric         InnerMatcher.Value->getTypedMatcher(*this);
790b57cec5SDimitry Andric     if (!Inner)
800b57cec5SDimitry Andric       return llvm::None;
810b57cec5SDimitry Andric     DynMatchers.push_back(*Inner);
820b57cec5SDimitry Andric   }
830b57cec5SDimitry Andric   return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric VariantMatcher::Payload::~Payload() {}
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
890b57cec5SDimitry Andric public:
900b57cec5SDimitry Andric   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
930b57cec5SDimitry Andric     return Matcher;
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   std::string getTypeAsString() const override {
970b57cec5SDimitry Andric     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
980b57cec5SDimitry Andric         .str();
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
1020b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
1030b57cec5SDimitry Andric     bool Ignore;
1040b57cec5SDimitry Andric     if (Ops.canConstructFrom(Matcher, Ignore))
1050b57cec5SDimitry Andric       return Matcher;
1060b57cec5SDimitry Andric     return llvm::None;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1095ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
1100b57cec5SDimitry Andric     return ArgKind(Matcher.getSupportedKind())
1110b57cec5SDimitry Andric         .isConvertibleTo(Kind, Specificity);
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric private:
1150b57cec5SDimitry Andric   const DynTypedMatcher Matcher;
1160b57cec5SDimitry Andric };
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
1190b57cec5SDimitry Andric public:
1200b57cec5SDimitry Andric   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
1210b57cec5SDimitry Andric       : Matchers(std::move(MatchersIn)) {}
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   ~PolymorphicPayload() override {}
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
1260b57cec5SDimitry Andric     if (Matchers.size() != 1)
1270b57cec5SDimitry Andric       return llvm::Optional<DynTypedMatcher>();
1280b57cec5SDimitry Andric     return Matchers[0];
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   std::string getTypeAsString() const override {
1320b57cec5SDimitry Andric     std::string Inner;
1330b57cec5SDimitry Andric     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1340b57cec5SDimitry Andric       if (i != 0)
1350b57cec5SDimitry Andric         Inner += "|";
1360b57cec5SDimitry Andric       Inner += Matchers[i].getSupportedKind().asStringRef();
1370b57cec5SDimitry Andric     }
1380b57cec5SDimitry Andric     return (Twine("Matcher<") + Inner + ">").str();
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
1420b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
1430b57cec5SDimitry Andric     bool FoundIsExact = false;
1440b57cec5SDimitry Andric     const DynTypedMatcher *Found = nullptr;
1450b57cec5SDimitry Andric     int NumFound = 0;
1460b57cec5SDimitry Andric     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1470b57cec5SDimitry Andric       bool IsExactMatch;
1480b57cec5SDimitry Andric       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
1490b57cec5SDimitry Andric         if (Found) {
1500b57cec5SDimitry Andric           if (FoundIsExact) {
1510b57cec5SDimitry Andric             assert(!IsExactMatch && "We should not have two exact matches.");
1520b57cec5SDimitry Andric             continue;
1530b57cec5SDimitry Andric           }
1540b57cec5SDimitry Andric         }
1550b57cec5SDimitry Andric         Found = &Matchers[i];
1560b57cec5SDimitry Andric         FoundIsExact = IsExactMatch;
1570b57cec5SDimitry Andric         ++NumFound;
1580b57cec5SDimitry Andric       }
1590b57cec5SDimitry Andric     }
1600b57cec5SDimitry Andric     // We only succeed if we found exactly one, or if we found an exact match.
1610b57cec5SDimitry Andric     if (Found && (FoundIsExact || NumFound == 1))
1620b57cec5SDimitry Andric       return *Found;
1630b57cec5SDimitry Andric     return llvm::None;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
1665ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
1670b57cec5SDimitry Andric     unsigned MaxSpecificity = 0;
1680b57cec5SDimitry Andric     for (const DynTypedMatcher &Matcher : Matchers) {
1690b57cec5SDimitry Andric       unsigned ThisSpecificity;
1700b57cec5SDimitry Andric       if (ArgKind(Matcher.getSupportedKind())
1710b57cec5SDimitry Andric               .isConvertibleTo(Kind, &ThisSpecificity)) {
1720b57cec5SDimitry Andric         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
1730b57cec5SDimitry Andric       }
1740b57cec5SDimitry Andric     }
1750b57cec5SDimitry Andric     if (Specificity)
1760b57cec5SDimitry Andric       *Specificity = MaxSpecificity;
1770b57cec5SDimitry Andric     return MaxSpecificity > 0;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   const std::vector<DynTypedMatcher> Matchers;
1810b57cec5SDimitry Andric };
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
1840b57cec5SDimitry Andric public:
1850b57cec5SDimitry Andric   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
1860b57cec5SDimitry Andric                     std::vector<VariantMatcher> Args)
1870b57cec5SDimitry Andric       : Op(Op), Args(std::move(Args)) {}
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
1900b57cec5SDimitry Andric     return llvm::Optional<DynTypedMatcher>();
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   std::string getTypeAsString() const override {
1940b57cec5SDimitry Andric     std::string Inner;
1950b57cec5SDimitry Andric     for (size_t i = 0, e = Args.size(); i != e; ++i) {
1960b57cec5SDimitry Andric       if (i != 0)
1970b57cec5SDimitry Andric         Inner += "&";
1980b57cec5SDimitry Andric       Inner += Args[i].getTypeAsString();
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric     return Inner;
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
2040b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
2050b57cec5SDimitry Andric     return Ops.constructVariadicOperator(Op, Args);
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
2085ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
2090b57cec5SDimitry Andric     for (const VariantMatcher &Matcher : Args) {
2100b57cec5SDimitry Andric       if (!Matcher.isConvertibleTo(Kind, Specificity))
2110b57cec5SDimitry Andric         return false;
2120b57cec5SDimitry Andric     }
2130b57cec5SDimitry Andric     return true;
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric private:
2170b57cec5SDimitry Andric   const DynTypedMatcher::VariadicOperator Op;
2180b57cec5SDimitry Andric   const std::vector<VariantMatcher> Args;
2190b57cec5SDimitry Andric };
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric VariantMatcher::VariantMatcher() {}
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
2240b57cec5SDimitry Andric   return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric VariantMatcher
2280b57cec5SDimitry Andric VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
2290b57cec5SDimitry Andric   return VariantMatcher(
2300b57cec5SDimitry Andric       std::make_shared<PolymorphicPayload>(std::move(Matchers)));
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric VariantMatcher VariantMatcher::VariadicOperatorMatcher(
2340b57cec5SDimitry Andric     DynTypedMatcher::VariadicOperator Op,
2350b57cec5SDimitry Andric     std::vector<VariantMatcher> Args) {
2360b57cec5SDimitry Andric   return VariantMatcher(
2370b57cec5SDimitry Andric       std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
2410b57cec5SDimitry Andric   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric void VariantMatcher::reset() { Value.reset(); }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric std::string VariantMatcher::getTypeAsString() const {
2470b57cec5SDimitry Andric   if (Value) return Value->getTypeAsString();
2480b57cec5SDimitry Andric   return "<Nothing>";
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
2520b57cec5SDimitry Andric   *this = Other;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
2560b57cec5SDimitry Andric   setBoolean(Boolean);
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
2600b57cec5SDimitry Andric   setDouble(Double);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
2640b57cec5SDimitry Andric   setUnsigned(Unsigned);
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
2680b57cec5SDimitry Andric   setString(String);
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
271*e8d8bef9SDimitry Andric VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
272*e8d8bef9SDimitry Andric   setNodeKind(NodeKind);
273*e8d8bef9SDimitry Andric }
274*e8d8bef9SDimitry Andric 
2750b57cec5SDimitry Andric VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
2760b57cec5SDimitry Andric   setMatcher(Matcher);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric VariantValue::~VariantValue() { reset(); }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric VariantValue &VariantValue::operator=(const VariantValue &Other) {
2820b57cec5SDimitry Andric   if (this == &Other) return *this;
2830b57cec5SDimitry Andric   reset();
2840b57cec5SDimitry Andric   switch (Other.Type) {
2850b57cec5SDimitry Andric   case VT_Boolean:
2860b57cec5SDimitry Andric     setBoolean(Other.getBoolean());
2870b57cec5SDimitry Andric     break;
2880b57cec5SDimitry Andric   case VT_Double:
2890b57cec5SDimitry Andric     setDouble(Other.getDouble());
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric   case VT_Unsigned:
2920b57cec5SDimitry Andric     setUnsigned(Other.getUnsigned());
2930b57cec5SDimitry Andric     break;
2940b57cec5SDimitry Andric   case VT_String:
2950b57cec5SDimitry Andric     setString(Other.getString());
2960b57cec5SDimitry Andric     break;
297*e8d8bef9SDimitry Andric   case VT_NodeKind:
298*e8d8bef9SDimitry Andric     setNodeKind(Other.getNodeKind());
299*e8d8bef9SDimitry Andric     break;
3000b57cec5SDimitry Andric   case VT_Matcher:
3010b57cec5SDimitry Andric     setMatcher(Other.getMatcher());
3020b57cec5SDimitry Andric     break;
3030b57cec5SDimitry Andric   case VT_Nothing:
3040b57cec5SDimitry Andric     Type = VT_Nothing;
3050b57cec5SDimitry Andric     break;
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric   return *this;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric void VariantValue::reset() {
3110b57cec5SDimitry Andric   switch (Type) {
3120b57cec5SDimitry Andric   case VT_String:
3130b57cec5SDimitry Andric     delete Value.String;
3140b57cec5SDimitry Andric     break;
3150b57cec5SDimitry Andric   case VT_Matcher:
3160b57cec5SDimitry Andric     delete Value.Matcher;
3170b57cec5SDimitry Andric     break;
318*e8d8bef9SDimitry Andric   case VT_NodeKind:
319*e8d8bef9SDimitry Andric     delete Value.NodeKind;
320*e8d8bef9SDimitry Andric     break;
3210b57cec5SDimitry Andric   // Cases that do nothing.
3220b57cec5SDimitry Andric   case VT_Boolean:
3230b57cec5SDimitry Andric   case VT_Double:
3240b57cec5SDimitry Andric   case VT_Unsigned:
3250b57cec5SDimitry Andric   case VT_Nothing:
3260b57cec5SDimitry Andric     break;
3270b57cec5SDimitry Andric   }
3280b57cec5SDimitry Andric   Type = VT_Nothing;
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric bool VariantValue::isBoolean() const {
3320b57cec5SDimitry Andric   return Type == VT_Boolean;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric bool VariantValue::getBoolean() const {
3360b57cec5SDimitry Andric   assert(isBoolean());
3370b57cec5SDimitry Andric   return Value.Boolean;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric void VariantValue::setBoolean(bool NewValue) {
3410b57cec5SDimitry Andric   reset();
3420b57cec5SDimitry Andric   Type = VT_Boolean;
3430b57cec5SDimitry Andric   Value.Boolean = NewValue;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric bool VariantValue::isDouble() const {
3470b57cec5SDimitry Andric   return Type == VT_Double;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric double VariantValue::getDouble() const {
3510b57cec5SDimitry Andric   assert(isDouble());
3520b57cec5SDimitry Andric   return Value.Double;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric void VariantValue::setDouble(double NewValue) {
3560b57cec5SDimitry Andric   reset();
3570b57cec5SDimitry Andric   Type = VT_Double;
3580b57cec5SDimitry Andric   Value.Double = NewValue;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric bool VariantValue::isUnsigned() const {
3620b57cec5SDimitry Andric   return Type == VT_Unsigned;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric unsigned VariantValue::getUnsigned() const {
3660b57cec5SDimitry Andric   assert(isUnsigned());
3670b57cec5SDimitry Andric   return Value.Unsigned;
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric void VariantValue::setUnsigned(unsigned NewValue) {
3710b57cec5SDimitry Andric   reset();
3720b57cec5SDimitry Andric   Type = VT_Unsigned;
3730b57cec5SDimitry Andric   Value.Unsigned = NewValue;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric bool VariantValue::isString() const {
3770b57cec5SDimitry Andric   return Type == VT_String;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric const std::string &VariantValue::getString() const {
3810b57cec5SDimitry Andric   assert(isString());
3820b57cec5SDimitry Andric   return *Value.String;
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric void VariantValue::setString(StringRef NewValue) {
3860b57cec5SDimitry Andric   reset();
3870b57cec5SDimitry Andric   Type = VT_String;
3880b57cec5SDimitry Andric   Value.String = new std::string(NewValue);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
391*e8d8bef9SDimitry Andric bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
392*e8d8bef9SDimitry Andric 
393*e8d8bef9SDimitry Andric const ASTNodeKind &VariantValue::getNodeKind() const {
394*e8d8bef9SDimitry Andric   assert(isNodeKind());
395*e8d8bef9SDimitry Andric   return *Value.NodeKind;
396*e8d8bef9SDimitry Andric }
397*e8d8bef9SDimitry Andric 
398*e8d8bef9SDimitry Andric void VariantValue::setNodeKind(ASTNodeKind NewValue) {
399*e8d8bef9SDimitry Andric   reset();
400*e8d8bef9SDimitry Andric   Type = VT_NodeKind;
401*e8d8bef9SDimitry Andric   Value.NodeKind = new ASTNodeKind(NewValue);
402*e8d8bef9SDimitry Andric }
403*e8d8bef9SDimitry Andric 
4040b57cec5SDimitry Andric bool VariantValue::isMatcher() const {
4050b57cec5SDimitry Andric   return Type == VT_Matcher;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric const VariantMatcher &VariantValue::getMatcher() const {
4090b57cec5SDimitry Andric   assert(isMatcher());
4100b57cec5SDimitry Andric   return *Value.Matcher;
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric void VariantValue::setMatcher(const VariantMatcher &NewValue) {
4140b57cec5SDimitry Andric   reset();
4150b57cec5SDimitry Andric   Type = VT_Matcher;
4160b57cec5SDimitry Andric   Value.Matcher = new VariantMatcher(NewValue);
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
4200b57cec5SDimitry Andric   switch (Kind.getArgKind()) {
4210b57cec5SDimitry Andric   case ArgKind::AK_Boolean:
4220b57cec5SDimitry Andric     if (!isBoolean())
4230b57cec5SDimitry Andric       return false;
4240b57cec5SDimitry Andric     *Specificity = 1;
4250b57cec5SDimitry Andric     return true;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   case ArgKind::AK_Double:
4280b57cec5SDimitry Andric     if (!isDouble())
4290b57cec5SDimitry Andric       return false;
4300b57cec5SDimitry Andric     *Specificity = 1;
4310b57cec5SDimitry Andric     return true;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   case ArgKind::AK_Unsigned:
4340b57cec5SDimitry Andric     if (!isUnsigned())
4350b57cec5SDimitry Andric       return false;
4360b57cec5SDimitry Andric     *Specificity = 1;
4370b57cec5SDimitry Andric     return true;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case ArgKind::AK_String:
4400b57cec5SDimitry Andric     if (!isString())
4410b57cec5SDimitry Andric       return false;
4420b57cec5SDimitry Andric     *Specificity = 1;
4430b57cec5SDimitry Andric     return true;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   case ArgKind::AK_Matcher:
4460b57cec5SDimitry Andric     if (!isMatcher())
4470b57cec5SDimitry Andric       return false;
4480b57cec5SDimitry Andric     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric   llvm_unreachable("Invalid Type");
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
4540b57cec5SDimitry Andric                                    unsigned *Specificity) const {
4550b57cec5SDimitry Andric   unsigned MaxSpecificity = 0;
4560b57cec5SDimitry Andric   for (const ArgKind& Kind : Kinds) {
4570b57cec5SDimitry Andric     unsigned ThisSpecificity;
4580b57cec5SDimitry Andric     if (!isConvertibleTo(Kind, &ThisSpecificity))
4590b57cec5SDimitry Andric       continue;
4600b57cec5SDimitry Andric     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric   if (Specificity && MaxSpecificity > 0) {
4630b57cec5SDimitry Andric     *Specificity = MaxSpecificity;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric   return MaxSpecificity > 0;
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric std::string VariantValue::getTypeAsString() const {
4690b57cec5SDimitry Andric   switch (Type) {
4700b57cec5SDimitry Andric   case VT_String: return "String";
4710b57cec5SDimitry Andric   case VT_Matcher: return getMatcher().getTypeAsString();
4720b57cec5SDimitry Andric   case VT_Boolean: return "Boolean";
4730b57cec5SDimitry Andric   case VT_Double: return "Double";
4740b57cec5SDimitry Andric   case VT_Unsigned: return "Unsigned";
475*e8d8bef9SDimitry Andric   case VT_NodeKind:
476*e8d8bef9SDimitry Andric     return getNodeKind().asStringRef().str();
4770b57cec5SDimitry Andric   case VT_Nothing: return "Nothing";
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric   llvm_unreachable("Invalid Type");
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric } // end namespace dynamic
4830b57cec5SDimitry Andric } // end namespace ast_matchers
4840b57cec5SDimitry Andric } // end namespace clang
485