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