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