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