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