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