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 llvm::Optional<DynTypedMatcher> 63 VariantMatcher::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 81 VariantMatcher::Payload::~Payload() {} 82 83 class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 84 public: 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 110 private: 111 const DynTypedMatcher Matcher; 112 }; 113 114 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 115 public: 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 180 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 181 public: 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 214 private: 215 const DynTypedMatcher::VariadicOperator Op; 216 const std::vector<VariantMatcher> Args; 217 }; 218 219 VariantMatcher::VariantMatcher() {} 220 221 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 222 return VariantMatcher(std::make_shared<SinglePayload>(Matcher)); 223 } 224 225 VariantMatcher 226 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 227 return VariantMatcher( 228 std::make_shared<PolymorphicPayload>(std::move(Matchers))); 229 } 230 231 VariantMatcher 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 238 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 239 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 240 } 241 242 void VariantMatcher::reset() { Value.reset(); } 243 244 std::string VariantMatcher::getTypeAsString() const { 245 if (Value) return Value->getTypeAsString(); 246 return "<Nothing>"; 247 } 248 249 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 250 *this = Other; 251 } 252 253 VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) { 254 setBoolean(Boolean); 255 } 256 257 VariantValue::VariantValue(double Double) : Type(VT_Nothing) { 258 setDouble(Double); 259 } 260 261 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 262 setUnsigned(Unsigned); 263 } 264 265 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) { 266 setString(String); 267 } 268 269 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 270 setMatcher(Matcher); 271 } 272 273 VariantValue::~VariantValue() { reset(); } 274 275 VariantValue &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 301 void 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 319 bool VariantValue::isBoolean() const { 320 return Type == VT_Boolean; 321 } 322 323 bool VariantValue::getBoolean() const { 324 assert(isBoolean()); 325 return Value.Boolean; 326 } 327 328 void VariantValue::setBoolean(bool NewValue) { 329 reset(); 330 Type = VT_Boolean; 331 Value.Boolean = NewValue; 332 } 333 334 bool VariantValue::isDouble() const { 335 return Type == VT_Double; 336 } 337 338 double VariantValue::getDouble() const { 339 assert(isDouble()); 340 return Value.Double; 341 } 342 343 void VariantValue::setDouble(double NewValue) { 344 reset(); 345 Type = VT_Double; 346 Value.Double = NewValue; 347 } 348 349 bool VariantValue::isUnsigned() const { 350 return Type == VT_Unsigned; 351 } 352 353 unsigned VariantValue::getUnsigned() const { 354 assert(isUnsigned()); 355 return Value.Unsigned; 356 } 357 358 void VariantValue::setUnsigned(unsigned NewValue) { 359 reset(); 360 Type = VT_Unsigned; 361 Value.Unsigned = NewValue; 362 } 363 364 bool VariantValue::isString() const { 365 return Type == VT_String; 366 } 367 368 const std::string &VariantValue::getString() const { 369 assert(isString()); 370 return *Value.String; 371 } 372 373 void VariantValue::setString(StringRef NewValue) { 374 reset(); 375 Type = VT_String; 376 Value.String = new std::string(NewValue); 377 } 378 379 bool VariantValue::isMatcher() const { 380 return Type == VT_Matcher; 381 } 382 383 const VariantMatcher &VariantValue::getMatcher() const { 384 assert(isMatcher()); 385 return *Value.Matcher; 386 } 387 388 void VariantValue::setMatcher(const VariantMatcher &NewValue) { 389 reset(); 390 Type = VT_Matcher; 391 Value.Matcher = new VariantMatcher(NewValue); 392 } 393 394 bool 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 428 bool 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 443 std::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