1//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/ 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// \brief Polymorphic value type. 12/// 13//===----------------------------------------------------------------------===// 14 15#include "clang/ASTMatchers/Dynamic/VariantValue.h" 16#include "clang/Basic/LLVM.h" 17#include "llvm/ADT/STLExtras.h" 18 19namespace clang { 20namespace ast_matchers { 21namespace dynamic { 22 23std::string ArgKind::asString() const { 24 switch (getArgKind()) { 25 case AK_Matcher: 26 return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str(); 27 case AK_Unsigned: 28 return "unsigned"; 29 case AK_String: 30 return "string"; 31 } 32 llvm_unreachable("unhandled ArgKind"); 33} 34 35bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const { 36 if (K != To.K) 37 return false; 38 if (K != AK_Matcher) { 39 if (Specificity) 40 *Specificity = 1; 41 return true; 42 } 43 unsigned Distance; 44 if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance)) 45 return false; 46 47 if (Specificity) 48 *Specificity = 100 - Distance; 49 return true; 50} 51 52bool 53VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher, 54 bool &IsExactMatch) const { 55 IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind); 56 return Matcher.canConvertTo(NodeKind); 57} 58 59llvm::Optional<DynTypedMatcher> 60VariantMatcher::MatcherOps::constructVariadicOperator( 61 DynTypedMatcher::VariadicOperator Op, 62 ArrayRef<VariantMatcher> InnerMatchers) const { 63 std::vector<DynTypedMatcher> DynMatchers; 64 for (const auto &InnerMatcher : InnerMatchers) { 65 // Abort if any of the inner matchers can't be converted to 66 // Matcher<T>. 67 if (!InnerMatcher.Value) 68 return llvm::None; 69 llvm::Optional<DynTypedMatcher> Inner = 70 InnerMatcher.Value->getTypedMatcher(*this); 71 if (!Inner) 72 return llvm::None; 73 DynMatchers.push_back(*Inner); 74 } 75 return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers); 76} 77 78VariantMatcher::Payload::~Payload() {} 79 80class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 81public: 82 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} 83 84 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 85 return Matcher; 86 } 87 88 std::string getTypeAsString() const override { 89 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") 90 .str(); 91 } 92 93 llvm::Optional<DynTypedMatcher> 94 getTypedMatcher(const MatcherOps &Ops) const override { 95 bool Ignore; 96 if (Ops.canConstructFrom(Matcher, Ignore)) 97 return Matcher; 98 return llvm::None; 99 } 100 101 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 102 unsigned *Specificity) const override { 103 return ArgKind(Matcher.getSupportedKind()) 104 .isConvertibleTo(Kind, Specificity); 105 } 106 107private: 108 const DynTypedMatcher Matcher; 109}; 110 111class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 112public: 113 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) 114 : Matchers(std::move(MatchersIn)) {} 115 116 ~PolymorphicPayload() override {} 117 118 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 119 if (Matchers.size() != 1) 120 return llvm::Optional<DynTypedMatcher>(); 121 return Matchers[0]; 122 } 123 124 std::string getTypeAsString() const override { 125 std::string Inner; 126 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 127 if (i != 0) 128 Inner += "|"; 129 Inner += Matchers[i].getSupportedKind().asStringRef(); 130 } 131 return (Twine("Matcher<") + Inner + ">").str(); 132 } 133 134 llvm::Optional<DynTypedMatcher> 135 getTypedMatcher(const MatcherOps &Ops) const override { 136 bool FoundIsExact = false; 137 const DynTypedMatcher *Found = nullptr; 138 int NumFound = 0; 139 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 140 bool IsExactMatch; 141 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { 142 if (Found) { 143 if (FoundIsExact) { 144 assert(!IsExactMatch && "We should not have two exact matches."); 145 continue; 146 } 147 } 148 Found = &Matchers[i]; 149 FoundIsExact = IsExactMatch; 150 ++NumFound; 151 } 152 } 153 // We only succeed if we found exactly one, or if we found an exact match. 154 if (Found && (FoundIsExact || NumFound == 1)) 155 return *Found; 156 return llvm::None; 157 } 158 159 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 160 unsigned *Specificity) const override { 161 unsigned MaxSpecificity = 0; 162 for (const DynTypedMatcher &Matcher : Matchers) { 163 unsigned ThisSpecificity; 164 if (ArgKind(Matcher.getSupportedKind()) 165 .isConvertibleTo(Kind, &ThisSpecificity)) { 166 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 167 } 168 } 169 if (Specificity) 170 *Specificity = MaxSpecificity; 171 return MaxSpecificity > 0; 172 } 173 174 const std::vector<DynTypedMatcher> Matchers; 175}; 176 177class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 178public: 179 VariadicOpPayload(DynTypedMatcher::VariadicOperator Op, 180 std::vector<VariantMatcher> Args) 181 : Op(Op), Args(std::move(Args)) {} 182 183 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 184 return llvm::Optional<DynTypedMatcher>(); 185 } 186 187 std::string getTypeAsString() const override { 188 std::string Inner; 189 for (size_t i = 0, e = Args.size(); i != e; ++i) { 190 if (i != 0) 191 Inner += "&"; 192 Inner += Args[i].getTypeAsString(); 193 } 194 return Inner; 195 } 196 197 llvm::Optional<DynTypedMatcher> 198 getTypedMatcher(const MatcherOps &Ops) const override { 199 return Ops.constructVariadicOperator(Op, Args); 200 } 201 202 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 203 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 211private: 212 const DynTypedMatcher::VariadicOperator Op; 213 const std::vector<VariantMatcher> Args; 214}; 215 216VariantMatcher::VariantMatcher() {} 217 218VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 219 return VariantMatcher(new SinglePayload(Matcher)); 220} 221 222VariantMatcher 223VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 224 return VariantMatcher(new PolymorphicPayload(std::move(Matchers))); 225} 226 227VariantMatcher VariantMatcher::VariadicOperatorMatcher( 228 DynTypedMatcher::VariadicOperator Op, 229 std::vector<VariantMatcher> Args) { 230 return VariantMatcher(new VariadicOpPayload(Op, std::move(Args))); 231} 232 233llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 234 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 235} 236 237void VariantMatcher::reset() { Value.reset(); } 238 239std::string VariantMatcher::getTypeAsString() const { 240 if (Value) return Value->getTypeAsString(); 241 return "<Nothing>"; 242} 243 244VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 245 *this = Other; 246} 247 248VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 249 setUnsigned(Unsigned); 250} 251 252VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) { 253 setString(String); 254} 255 256VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 257 setMatcher(Matcher); 258} 259 260VariantValue::~VariantValue() { reset(); } 261 262VariantValue &VariantValue::operator=(const VariantValue &Other) { 263 if (this == &Other) return *this; 264 reset(); 265 switch (Other.Type) { 266 case VT_Unsigned: 267 setUnsigned(Other.getUnsigned()); 268 break; 269 case VT_String: 270 setString(Other.getString()); 271 break; 272 case VT_Matcher: 273 setMatcher(Other.getMatcher()); 274 break; 275 case VT_Nothing: 276 Type = VT_Nothing; 277 break; 278 } 279 return *this; 280} 281 282void VariantValue::reset() { 283 switch (Type) { 284 case VT_String: 285 delete Value.String; 286 break; 287 case VT_Matcher: 288 delete Value.Matcher; 289 break; 290 // Cases that do nothing. 291 case VT_Unsigned: 292 case VT_Nothing: 293 break; 294 } 295 Type = VT_Nothing; 296} 297 298bool VariantValue::isUnsigned() const { 299 return Type == VT_Unsigned; 300} 301 302unsigned VariantValue::getUnsigned() const { 303 assert(isUnsigned()); 304 return Value.Unsigned; 305} 306 307void VariantValue::setUnsigned(unsigned NewValue) { 308 reset(); 309 Type = VT_Unsigned; 310 Value.Unsigned = NewValue; 311} 312 313bool VariantValue::isString() const { 314 return Type == VT_String; 315} 316 317const std::string &VariantValue::getString() const { 318 assert(isString()); 319 return *Value.String; 320} 321 322void VariantValue::setString(StringRef NewValue) { 323 reset(); 324 Type = VT_String; 325 Value.String = new std::string(NewValue); 326} 327 328bool VariantValue::isMatcher() const { 329 return Type == VT_Matcher; 330} 331 332const VariantMatcher &VariantValue::getMatcher() const { 333 assert(isMatcher()); 334 return *Value.Matcher; 335} 336 337void VariantValue::setMatcher(const VariantMatcher &NewValue) { 338 reset(); 339 Type = VT_Matcher; 340 Value.Matcher = new VariantMatcher(NewValue); 341} 342 343bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { 344 switch (Kind.getArgKind()) { 345 case ArgKind::AK_Unsigned: 346 if (!isUnsigned()) 347 return false; 348 *Specificity = 1; 349 return true; 350 351 case ArgKind::AK_String: 352 if (!isString()) 353 return false; 354 *Specificity = 1; 355 return true; 356 357 case ArgKind::AK_Matcher: 358 if (!isMatcher()) 359 return false; 360 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity); 361 } 362 llvm_unreachable("Invalid Type"); 363} 364 365bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds, 366 unsigned *Specificity) const { 367 unsigned MaxSpecificity = 0; 368 for (const ArgKind& Kind : Kinds) { 369 unsigned ThisSpecificity; 370 if (!isConvertibleTo(Kind, &ThisSpecificity)) 371 continue; 372 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 373 } 374 if (Specificity && MaxSpecificity > 0) { 375 *Specificity = MaxSpecificity; 376 } 377 return MaxSpecificity > 0; 378} 379 380std::string VariantValue::getTypeAsString() const { 381 switch (Type) { 382 case VT_String: return "String"; 383 case VT_Matcher: return getMatcher().getTypeAsString(); 384 case VT_Unsigned: return "Unsigned"; 385 case VT_Nothing: return "Nothing"; 386 } 387 llvm_unreachable("Invalid Type"); 388} 389 390} // end namespace dynamic 391} // end namespace ast_matchers 392} // end namespace clang 393