xref: /freebsd/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry 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 
620b57cec5SDimitry Andric llvm::Optional<DynTypedMatcher>
630b57cec5SDimitry Andric VariantMatcher::MatcherOps::constructVariadicOperator(
640b57cec5SDimitry Andric     DynTypedMatcher::VariadicOperator Op,
650b57cec5SDimitry Andric     ArrayRef<VariantMatcher> InnerMatchers) const {
660b57cec5SDimitry Andric   std::vector<DynTypedMatcher> DynMatchers;
670b57cec5SDimitry Andric   for (const auto &InnerMatcher : InnerMatchers) {
680b57cec5SDimitry Andric     // Abort if any of the inner matchers can't be converted to
690b57cec5SDimitry Andric     // Matcher<T>.
700b57cec5SDimitry Andric     if (!InnerMatcher.Value)
710b57cec5SDimitry Andric       return llvm::None;
720b57cec5SDimitry Andric     llvm::Optional<DynTypedMatcher> Inner =
730b57cec5SDimitry Andric         InnerMatcher.Value->getTypedMatcher(*this);
740b57cec5SDimitry Andric     if (!Inner)
750b57cec5SDimitry Andric       return llvm::None;
760b57cec5SDimitry Andric     DynMatchers.push_back(*Inner);
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric   return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric VariantMatcher::Payload::~Payload() {}
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
840b57cec5SDimitry Andric public:
850b57cec5SDimitry Andric   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
880b57cec5SDimitry Andric     return Matcher;
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   std::string getTypeAsString() const override {
920b57cec5SDimitry Andric     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
930b57cec5SDimitry Andric         .str();
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
970b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
980b57cec5SDimitry Andric     bool Ignore;
990b57cec5SDimitry Andric     if (Ops.canConstructFrom(Matcher, Ignore))
1000b57cec5SDimitry Andric       return Matcher;
1010b57cec5SDimitry Andric     return llvm::None;
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric 
104*5ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
1050b57cec5SDimitry Andric     return ArgKind(Matcher.getSupportedKind())
1060b57cec5SDimitry Andric         .isConvertibleTo(Kind, Specificity);
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric private:
1100b57cec5SDimitry Andric   const DynTypedMatcher Matcher;
1110b57cec5SDimitry Andric };
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
1140b57cec5SDimitry Andric public:
1150b57cec5SDimitry Andric   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
1160b57cec5SDimitry Andric       : Matchers(std::move(MatchersIn)) {}
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   ~PolymorphicPayload() override {}
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
1210b57cec5SDimitry Andric     if (Matchers.size() != 1)
1220b57cec5SDimitry Andric       return llvm::Optional<DynTypedMatcher>();
1230b57cec5SDimitry Andric     return Matchers[0];
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   std::string getTypeAsString() const override {
1270b57cec5SDimitry Andric     std::string Inner;
1280b57cec5SDimitry Andric     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1290b57cec5SDimitry Andric       if (i != 0)
1300b57cec5SDimitry Andric         Inner += "|";
1310b57cec5SDimitry Andric       Inner += Matchers[i].getSupportedKind().asStringRef();
1320b57cec5SDimitry Andric     }
1330b57cec5SDimitry Andric     return (Twine("Matcher<") + Inner + ">").str();
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
1370b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
1380b57cec5SDimitry Andric     bool FoundIsExact = false;
1390b57cec5SDimitry Andric     const DynTypedMatcher *Found = nullptr;
1400b57cec5SDimitry Andric     int NumFound = 0;
1410b57cec5SDimitry Andric     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1420b57cec5SDimitry Andric       bool IsExactMatch;
1430b57cec5SDimitry Andric       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
1440b57cec5SDimitry Andric         if (Found) {
1450b57cec5SDimitry Andric           if (FoundIsExact) {
1460b57cec5SDimitry Andric             assert(!IsExactMatch && "We should not have two exact matches.");
1470b57cec5SDimitry Andric             continue;
1480b57cec5SDimitry Andric           }
1490b57cec5SDimitry Andric         }
1500b57cec5SDimitry Andric         Found = &Matchers[i];
1510b57cec5SDimitry Andric         FoundIsExact = IsExactMatch;
1520b57cec5SDimitry Andric         ++NumFound;
1530b57cec5SDimitry Andric       }
1540b57cec5SDimitry Andric     }
1550b57cec5SDimitry Andric     // We only succeed if we found exactly one, or if we found an exact match.
1560b57cec5SDimitry Andric     if (Found && (FoundIsExact || NumFound == 1))
1570b57cec5SDimitry Andric       return *Found;
1580b57cec5SDimitry Andric     return llvm::None;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
161*5ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
1620b57cec5SDimitry Andric     unsigned MaxSpecificity = 0;
1630b57cec5SDimitry Andric     for (const DynTypedMatcher &Matcher : Matchers) {
1640b57cec5SDimitry Andric       unsigned ThisSpecificity;
1650b57cec5SDimitry Andric       if (ArgKind(Matcher.getSupportedKind())
1660b57cec5SDimitry Andric               .isConvertibleTo(Kind, &ThisSpecificity)) {
1670b57cec5SDimitry Andric         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
1680b57cec5SDimitry Andric       }
1690b57cec5SDimitry Andric     }
1700b57cec5SDimitry Andric     if (Specificity)
1710b57cec5SDimitry Andric       *Specificity = MaxSpecificity;
1720b57cec5SDimitry Andric     return MaxSpecificity > 0;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   const std::vector<DynTypedMatcher> Matchers;
1760b57cec5SDimitry Andric };
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
1790b57cec5SDimitry Andric public:
1800b57cec5SDimitry Andric   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
1810b57cec5SDimitry Andric                     std::vector<VariantMatcher> Args)
1820b57cec5SDimitry Andric       : Op(Op), Args(std::move(Args)) {}
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
1850b57cec5SDimitry Andric     return llvm::Optional<DynTypedMatcher>();
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   std::string getTypeAsString() const override {
1890b57cec5SDimitry Andric     std::string Inner;
1900b57cec5SDimitry Andric     for (size_t i = 0, e = Args.size(); i != e; ++i) {
1910b57cec5SDimitry Andric       if (i != 0)
1920b57cec5SDimitry Andric         Inner += "&";
1930b57cec5SDimitry Andric       Inner += Args[i].getTypeAsString();
1940b57cec5SDimitry Andric     }
1950b57cec5SDimitry Andric     return Inner;
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   llvm::Optional<DynTypedMatcher>
1990b57cec5SDimitry Andric   getTypedMatcher(const MatcherOps &Ops) const override {
2000b57cec5SDimitry Andric     return Ops.constructVariadicOperator(Op, Args);
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
203*5ffd83dbSDimitry Andric   bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
2040b57cec5SDimitry Andric     for (const VariantMatcher &Matcher : Args) {
2050b57cec5SDimitry Andric       if (!Matcher.isConvertibleTo(Kind, Specificity))
2060b57cec5SDimitry Andric         return false;
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric     return true;
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric private:
2120b57cec5SDimitry Andric   const DynTypedMatcher::VariadicOperator Op;
2130b57cec5SDimitry Andric   const std::vector<VariantMatcher> Args;
2140b57cec5SDimitry Andric };
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric VariantMatcher::VariantMatcher() {}
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
2190b57cec5SDimitry Andric   return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric VariantMatcher
2230b57cec5SDimitry Andric VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
2240b57cec5SDimitry Andric   return VariantMatcher(
2250b57cec5SDimitry Andric       std::make_shared<PolymorphicPayload>(std::move(Matchers)));
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric VariantMatcher VariantMatcher::VariadicOperatorMatcher(
2290b57cec5SDimitry Andric     DynTypedMatcher::VariadicOperator Op,
2300b57cec5SDimitry Andric     std::vector<VariantMatcher> Args) {
2310b57cec5SDimitry Andric   return VariantMatcher(
2320b57cec5SDimitry Andric       std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
2360b57cec5SDimitry Andric   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric void VariantMatcher::reset() { Value.reset(); }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric std::string VariantMatcher::getTypeAsString() const {
2420b57cec5SDimitry Andric   if (Value) return Value->getTypeAsString();
2430b57cec5SDimitry Andric   return "<Nothing>";
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
2470b57cec5SDimitry Andric   *this = Other;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
2510b57cec5SDimitry Andric   setBoolean(Boolean);
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
2550b57cec5SDimitry Andric   setDouble(Double);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
2590b57cec5SDimitry Andric   setUnsigned(Unsigned);
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
2630b57cec5SDimitry Andric   setString(String);
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
2670b57cec5SDimitry Andric   setMatcher(Matcher);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric VariantValue::~VariantValue() { reset(); }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric VariantValue &VariantValue::operator=(const VariantValue &Other) {
2730b57cec5SDimitry Andric   if (this == &Other) return *this;
2740b57cec5SDimitry Andric   reset();
2750b57cec5SDimitry Andric   switch (Other.Type) {
2760b57cec5SDimitry Andric   case VT_Boolean:
2770b57cec5SDimitry Andric     setBoolean(Other.getBoolean());
2780b57cec5SDimitry Andric     break;
2790b57cec5SDimitry Andric   case VT_Double:
2800b57cec5SDimitry Andric     setDouble(Other.getDouble());
2810b57cec5SDimitry Andric     break;
2820b57cec5SDimitry Andric   case VT_Unsigned:
2830b57cec5SDimitry Andric     setUnsigned(Other.getUnsigned());
2840b57cec5SDimitry Andric     break;
2850b57cec5SDimitry Andric   case VT_String:
2860b57cec5SDimitry Andric     setString(Other.getString());
2870b57cec5SDimitry Andric     break;
2880b57cec5SDimitry Andric   case VT_Matcher:
2890b57cec5SDimitry Andric     setMatcher(Other.getMatcher());
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric   case VT_Nothing:
2920b57cec5SDimitry Andric     Type = VT_Nothing;
2930b57cec5SDimitry Andric     break;
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric   return *this;
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric void VariantValue::reset() {
2990b57cec5SDimitry Andric   switch (Type) {
3000b57cec5SDimitry Andric   case VT_String:
3010b57cec5SDimitry Andric     delete Value.String;
3020b57cec5SDimitry Andric     break;
3030b57cec5SDimitry Andric   case VT_Matcher:
3040b57cec5SDimitry Andric     delete Value.Matcher;
3050b57cec5SDimitry Andric     break;
3060b57cec5SDimitry Andric   // Cases that do nothing.
3070b57cec5SDimitry Andric   case VT_Boolean:
3080b57cec5SDimitry Andric   case VT_Double:
3090b57cec5SDimitry Andric   case VT_Unsigned:
3100b57cec5SDimitry Andric   case VT_Nothing:
3110b57cec5SDimitry Andric     break;
3120b57cec5SDimitry Andric   }
3130b57cec5SDimitry Andric   Type = VT_Nothing;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric bool VariantValue::isBoolean() const {
3170b57cec5SDimitry Andric   return Type == VT_Boolean;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric bool VariantValue::getBoolean() const {
3210b57cec5SDimitry Andric   assert(isBoolean());
3220b57cec5SDimitry Andric   return Value.Boolean;
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric void VariantValue::setBoolean(bool NewValue) {
3260b57cec5SDimitry Andric   reset();
3270b57cec5SDimitry Andric   Type = VT_Boolean;
3280b57cec5SDimitry Andric   Value.Boolean = NewValue;
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric bool VariantValue::isDouble() const {
3320b57cec5SDimitry Andric   return Type == VT_Double;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric double VariantValue::getDouble() const {
3360b57cec5SDimitry Andric   assert(isDouble());
3370b57cec5SDimitry Andric   return Value.Double;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric void VariantValue::setDouble(double NewValue) {
3410b57cec5SDimitry Andric   reset();
3420b57cec5SDimitry Andric   Type = VT_Double;
3430b57cec5SDimitry Andric   Value.Double = NewValue;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric bool VariantValue::isUnsigned() const {
3470b57cec5SDimitry Andric   return Type == VT_Unsigned;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric unsigned VariantValue::getUnsigned() const {
3510b57cec5SDimitry Andric   assert(isUnsigned());
3520b57cec5SDimitry Andric   return Value.Unsigned;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric void VariantValue::setUnsigned(unsigned NewValue) {
3560b57cec5SDimitry Andric   reset();
3570b57cec5SDimitry Andric   Type = VT_Unsigned;
3580b57cec5SDimitry Andric   Value.Unsigned = NewValue;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric bool VariantValue::isString() const {
3620b57cec5SDimitry Andric   return Type == VT_String;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric const std::string &VariantValue::getString() const {
3660b57cec5SDimitry Andric   assert(isString());
3670b57cec5SDimitry Andric   return *Value.String;
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric void VariantValue::setString(StringRef NewValue) {
3710b57cec5SDimitry Andric   reset();
3720b57cec5SDimitry Andric   Type = VT_String;
3730b57cec5SDimitry Andric   Value.String = new std::string(NewValue);
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric bool VariantValue::isMatcher() const {
3770b57cec5SDimitry Andric   return Type == VT_Matcher;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric const VariantMatcher &VariantValue::getMatcher() const {
3810b57cec5SDimitry Andric   assert(isMatcher());
3820b57cec5SDimitry Andric   return *Value.Matcher;
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric void VariantValue::setMatcher(const VariantMatcher &NewValue) {
3860b57cec5SDimitry Andric   reset();
3870b57cec5SDimitry Andric   Type = VT_Matcher;
3880b57cec5SDimitry Andric   Value.Matcher = new VariantMatcher(NewValue);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
3920b57cec5SDimitry Andric   switch (Kind.getArgKind()) {
3930b57cec5SDimitry Andric   case ArgKind::AK_Boolean:
3940b57cec5SDimitry Andric     if (!isBoolean())
3950b57cec5SDimitry Andric       return false;
3960b57cec5SDimitry Andric     *Specificity = 1;
3970b57cec5SDimitry Andric     return true;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   case ArgKind::AK_Double:
4000b57cec5SDimitry Andric     if (!isDouble())
4010b57cec5SDimitry Andric       return false;
4020b57cec5SDimitry Andric     *Specificity = 1;
4030b57cec5SDimitry Andric     return true;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   case ArgKind::AK_Unsigned:
4060b57cec5SDimitry Andric     if (!isUnsigned())
4070b57cec5SDimitry Andric       return false;
4080b57cec5SDimitry Andric     *Specificity = 1;
4090b57cec5SDimitry Andric     return true;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   case ArgKind::AK_String:
4120b57cec5SDimitry Andric     if (!isString())
4130b57cec5SDimitry Andric       return false;
4140b57cec5SDimitry Andric     *Specificity = 1;
4150b57cec5SDimitry Andric     return true;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   case ArgKind::AK_Matcher:
4180b57cec5SDimitry Andric     if (!isMatcher())
4190b57cec5SDimitry Andric       return false;
4200b57cec5SDimitry Andric     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric   llvm_unreachable("Invalid Type");
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
4260b57cec5SDimitry Andric                                    unsigned *Specificity) const {
4270b57cec5SDimitry Andric   unsigned MaxSpecificity = 0;
4280b57cec5SDimitry Andric   for (const ArgKind& Kind : Kinds) {
4290b57cec5SDimitry Andric     unsigned ThisSpecificity;
4300b57cec5SDimitry Andric     if (!isConvertibleTo(Kind, &ThisSpecificity))
4310b57cec5SDimitry Andric       continue;
4320b57cec5SDimitry Andric     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric   if (Specificity && MaxSpecificity > 0) {
4350b57cec5SDimitry Andric     *Specificity = MaxSpecificity;
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric   return MaxSpecificity > 0;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric std::string VariantValue::getTypeAsString() const {
4410b57cec5SDimitry Andric   switch (Type) {
4420b57cec5SDimitry Andric   case VT_String: return "String";
4430b57cec5SDimitry Andric   case VT_Matcher: return getMatcher().getTypeAsString();
4440b57cec5SDimitry Andric   case VT_Boolean: return "Boolean";
4450b57cec5SDimitry Andric   case VT_Double: return "Double";
4460b57cec5SDimitry Andric   case VT_Unsigned: return "Unsigned";
4470b57cec5SDimitry Andric   case VT_Nothing: return "Nothing";
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric   llvm_unreachable("Invalid Type");
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric } // end namespace dynamic
4530b57cec5SDimitry Andric } // end namespace ast_matchers
4540b57cec5SDimitry Andric } // end namespace clang
455