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