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