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