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 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<") + 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 35 bool 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 52 VariantMatcher::MatcherOps::~MatcherOps() {} 53 VariantMatcher::Payload::~Payload() {} 54 55 class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 56 public: 57 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} 58 59 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 60 return Matcher; 61 } 62 63 std::string getTypeAsString() const override { 64 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") 65 .str(); 66 } 67 68 void makeTypedMatcher(MatcherOps &Ops) const override { 69 bool Ignore; 70 if (Ops.canConstructFrom(Matcher, Ignore)) 71 Ops.constructFrom(Matcher); 72 } 73 74 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 75 unsigned *Specificity) const override { 76 return ArgKind(Matcher.getSupportedKind()) 77 .isConvertibleTo(Kind, Specificity); 78 } 79 80 private: 81 const DynTypedMatcher Matcher; 82 }; 83 84 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 85 public: 86 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) 87 : Matchers(std::move(MatchersIn)) {} 88 89 ~PolymorphicPayload() override {} 90 91 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 92 if (Matchers.size() != 1) 93 return llvm::Optional<DynTypedMatcher>(); 94 return Matchers[0]; 95 } 96 97 std::string getTypeAsString() const override { 98 std::string Inner; 99 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 100 if (i != 0) 101 Inner += "|"; 102 Inner += Matchers[i].getSupportedKind().asStringRef(); 103 } 104 return (Twine("Matcher<") + Inner + ">").str(); 105 } 106 107 void makeTypedMatcher(MatcherOps &Ops) const override { 108 bool FoundIsExact = false; 109 const DynTypedMatcher *Found = nullptr; 110 int NumFound = 0; 111 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 112 bool IsExactMatch; 113 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { 114 if (Found) { 115 if (FoundIsExact) { 116 assert(!IsExactMatch && "We should not have two exact matches."); 117 continue; 118 } 119 } 120 Found = &Matchers[i]; 121 FoundIsExact = IsExactMatch; 122 ++NumFound; 123 } 124 } 125 // We only succeed if we found exactly one, or if we found an exact match. 126 if (Found && (FoundIsExact || NumFound == 1)) 127 Ops.constructFrom(*Found); 128 } 129 130 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 131 unsigned *Specificity) const override { 132 unsigned MaxSpecificity = 0; 133 for (const DynTypedMatcher &Matcher : Matchers) { 134 unsigned ThisSpecificity; 135 if (ArgKind(Matcher.getSupportedKind()) 136 .isConvertibleTo(Kind, &ThisSpecificity)) { 137 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 138 } 139 } 140 if (Specificity) 141 *Specificity = MaxSpecificity; 142 return MaxSpecificity > 0; 143 } 144 145 const std::vector<DynTypedMatcher> Matchers; 146 }; 147 148 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 149 public: 150 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func, 151 std::vector<VariantMatcher> Args) 152 : Func(Func), Args(std::move(Args)) {} 153 154 llvm::Optional<DynTypedMatcher> getSingleMatcher() const override { 155 return llvm::Optional<DynTypedMatcher>(); 156 } 157 158 std::string getTypeAsString() const override { 159 std::string Inner; 160 for (size_t i = 0, e = Args.size(); i != e; ++i) { 161 if (i != 0) 162 Inner += "&"; 163 Inner += Args[i].getTypeAsString(); 164 } 165 return Inner; 166 } 167 168 void makeTypedMatcher(MatcherOps &Ops) const override { 169 Ops.constructVariadicOperator(Func, Args); 170 } 171 172 bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, 173 unsigned *Specificity) const override { 174 for (const VariantMatcher &Matcher : Args) { 175 if (!Matcher.isConvertibleTo(Kind, Specificity)) 176 return false; 177 } 178 return true; 179 } 180 181 private: 182 const ast_matchers::internal::VariadicOperatorFunction Func; 183 const std::vector<VariantMatcher> Args; 184 }; 185 186 VariantMatcher::VariantMatcher() {} 187 188 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 189 return VariantMatcher(new SinglePayload(Matcher)); 190 } 191 192 VariantMatcher 193 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 194 return VariantMatcher(new PolymorphicPayload(std::move(Matchers))); 195 } 196 197 VariantMatcher VariantMatcher::VariadicOperatorMatcher( 198 ast_matchers::internal::VariadicOperatorFunction Func, 199 std::vector<VariantMatcher> Args) { 200 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args))); 201 } 202 203 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 204 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 205 } 206 207 void VariantMatcher::reset() { Value.reset(); } 208 209 std::string VariantMatcher::getTypeAsString() const { 210 if (Value) return Value->getTypeAsString(); 211 return "<Nothing>"; 212 } 213 214 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 215 *this = Other; 216 } 217 218 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 219 setUnsigned(Unsigned); 220 } 221 222 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) { 223 setString(String); 224 } 225 226 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 227 setMatcher(Matcher); 228 } 229 230 VariantValue::~VariantValue() { reset(); } 231 232 VariantValue &VariantValue::operator=(const VariantValue &Other) { 233 if (this == &Other) return *this; 234 reset(); 235 switch (Other.Type) { 236 case VT_Unsigned: 237 setUnsigned(Other.getUnsigned()); 238 break; 239 case VT_String: 240 setString(Other.getString()); 241 break; 242 case VT_Matcher: 243 setMatcher(Other.getMatcher()); 244 break; 245 case VT_Nothing: 246 Type = VT_Nothing; 247 break; 248 } 249 return *this; 250 } 251 252 void VariantValue::reset() { 253 switch (Type) { 254 case VT_String: 255 delete Value.String; 256 break; 257 case VT_Matcher: 258 delete Value.Matcher; 259 break; 260 // Cases that do nothing. 261 case VT_Unsigned: 262 case VT_Nothing: 263 break; 264 } 265 Type = VT_Nothing; 266 } 267 268 bool VariantValue::isUnsigned() const { 269 return Type == VT_Unsigned; 270 } 271 272 unsigned VariantValue::getUnsigned() const { 273 assert(isUnsigned()); 274 return Value.Unsigned; 275 } 276 277 void VariantValue::setUnsigned(unsigned NewValue) { 278 reset(); 279 Type = VT_Unsigned; 280 Value.Unsigned = NewValue; 281 } 282 283 bool VariantValue::isString() const { 284 return Type == VT_String; 285 } 286 287 const std::string &VariantValue::getString() const { 288 assert(isString()); 289 return *Value.String; 290 } 291 292 void VariantValue::setString(const std::string &NewValue) { 293 reset(); 294 Type = VT_String; 295 Value.String = new std::string(NewValue); 296 } 297 298 bool VariantValue::isMatcher() const { 299 return Type == VT_Matcher; 300 } 301 302 const VariantMatcher &VariantValue::getMatcher() const { 303 assert(isMatcher()); 304 return *Value.Matcher; 305 } 306 307 void VariantValue::setMatcher(const VariantMatcher &NewValue) { 308 reset(); 309 Type = VT_Matcher; 310 Value.Matcher = new VariantMatcher(NewValue); 311 } 312 313 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const { 314 switch (Kind.getArgKind()) { 315 case ArgKind::AK_Unsigned: 316 if (!isUnsigned()) 317 return false; 318 *Specificity = 1; 319 return true; 320 321 case ArgKind::AK_String: 322 if (!isString()) 323 return false; 324 *Specificity = 1; 325 return true; 326 327 case ArgKind::AK_Matcher: 328 if (!isMatcher()) 329 return false; 330 return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity); 331 } 332 llvm_unreachable("Invalid Type"); 333 } 334 335 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds, 336 unsigned *Specificity) const { 337 unsigned MaxSpecificity = 0; 338 for (const ArgKind& Kind : Kinds) { 339 unsigned ThisSpecificity; 340 if (!isConvertibleTo(Kind, &ThisSpecificity)) 341 continue; 342 MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity); 343 } 344 if (Specificity && MaxSpecificity > 0) { 345 *Specificity = MaxSpecificity; 346 } 347 return MaxSpecificity > 0; 348 } 349 350 std::string VariantValue::getTypeAsString() const { 351 switch (Type) { 352 case VT_String: return "String"; 353 case VT_Matcher: return getMatcher().getTypeAsString(); 354 case VT_Unsigned: return "Unsigned"; 355 case VT_Nothing: return "Nothing"; 356 } 357 llvm_unreachable("Invalid Type"); 358 } 359 360 } // end namespace dynamic 361 } // end namespace ast_matchers 362 } // end namespace clang 363