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 VariantMatcher::MatcherOps::~MatcherOps() {} 24 VariantMatcher::Payload::~Payload() {} 25 26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 27 public: 28 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {} 29 30 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const { 31 return Matcher; 32 } 33 34 virtual std::string getTypeAsString() const { 35 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">") 36 .str(); 37 } 38 39 virtual void makeTypedMatcher(MatcherOps &Ops) const { 40 bool Ignore; 41 if (Ops.canConstructFrom(Matcher, Ignore)) 42 Ops.constructFrom(Matcher); 43 } 44 45 private: 46 const DynTypedMatcher Matcher; 47 }; 48 49 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 50 public: 51 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) 52 : Matchers(std::move(MatchersIn)) {} 53 54 virtual ~PolymorphicPayload() {} 55 56 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const { 57 if (Matchers.size() != 1) 58 return llvm::Optional<DynTypedMatcher>(); 59 return Matchers[0]; 60 } 61 62 virtual std::string getTypeAsString() const { 63 std::string Inner; 64 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 65 if (i != 0) 66 Inner += "|"; 67 Inner += Matchers[i].getSupportedKind().asStringRef(); 68 } 69 return (Twine("Matcher<") + Inner + ">").str(); 70 } 71 72 virtual void makeTypedMatcher(MatcherOps &Ops) const { 73 bool FoundIsExact = false; 74 const DynTypedMatcher *Found = nullptr; 75 int NumFound = 0; 76 for (size_t i = 0, e = Matchers.size(); i != e; ++i) { 77 bool IsExactMatch; 78 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { 79 if (Found) { 80 if (FoundIsExact) { 81 assert(!IsExactMatch && "We should not have two exact matches."); 82 continue; 83 } 84 } 85 Found = &Matchers[i]; 86 FoundIsExact = IsExactMatch; 87 ++NumFound; 88 } 89 } 90 // We only succeed if we found exactly one, or if we found an exact match. 91 if (Found && (FoundIsExact || NumFound == 1)) 92 Ops.constructFrom(*Found); 93 } 94 95 const std::vector<DynTypedMatcher> Matchers; 96 }; 97 98 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 99 public: 100 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func, 101 std::vector<VariantMatcher> Args) 102 : Func(Func), Args(std::move(Args)) {} 103 104 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const { 105 return llvm::Optional<DynTypedMatcher>(); 106 } 107 108 virtual std::string getTypeAsString() const { 109 std::string Inner; 110 for (size_t i = 0, e = Args.size(); i != e; ++i) { 111 if (i != 0) 112 Inner += "&"; 113 Inner += Args[i].getTypeAsString(); 114 } 115 return Inner; 116 } 117 118 virtual void makeTypedMatcher(MatcherOps &Ops) const { 119 Ops.constructVariadicOperator(Func, Args); 120 } 121 122 private: 123 const ast_matchers::internal::VariadicOperatorFunction Func; 124 const std::vector<VariantMatcher> Args; 125 }; 126 127 VariantMatcher::VariantMatcher() {} 128 129 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 130 return VariantMatcher(new SinglePayload(Matcher)); 131 } 132 133 VariantMatcher 134 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 135 return VariantMatcher(new PolymorphicPayload(std::move(Matchers))); 136 } 137 138 VariantMatcher VariantMatcher::VariadicOperatorMatcher( 139 ast_matchers::internal::VariadicOperatorFunction Func, 140 std::vector<VariantMatcher> Args) { 141 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args))); 142 } 143 144 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 145 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 146 } 147 148 void VariantMatcher::reset() { Value.reset(); } 149 150 std::string VariantMatcher::getTypeAsString() const { 151 if (Value) return Value->getTypeAsString(); 152 return "<Nothing>"; 153 } 154 155 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 156 *this = Other; 157 } 158 159 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 160 setUnsigned(Unsigned); 161 } 162 163 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) { 164 setString(String); 165 } 166 167 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 168 setMatcher(Matcher); 169 } 170 171 VariantValue::~VariantValue() { reset(); } 172 173 VariantValue &VariantValue::operator=(const VariantValue &Other) { 174 if (this == &Other) return *this; 175 reset(); 176 switch (Other.Type) { 177 case VT_Unsigned: 178 setUnsigned(Other.getUnsigned()); 179 break; 180 case VT_String: 181 setString(Other.getString()); 182 break; 183 case VT_Matcher: 184 setMatcher(Other.getMatcher()); 185 break; 186 case VT_Nothing: 187 Type = VT_Nothing; 188 break; 189 } 190 return *this; 191 } 192 193 void VariantValue::reset() { 194 switch (Type) { 195 case VT_String: 196 delete Value.String; 197 break; 198 case VT_Matcher: 199 delete Value.Matcher; 200 break; 201 // Cases that do nothing. 202 case VT_Unsigned: 203 case VT_Nothing: 204 break; 205 } 206 Type = VT_Nothing; 207 } 208 209 bool VariantValue::isUnsigned() const { 210 return Type == VT_Unsigned; 211 } 212 213 unsigned VariantValue::getUnsigned() const { 214 assert(isUnsigned()); 215 return Value.Unsigned; 216 } 217 218 void VariantValue::setUnsigned(unsigned NewValue) { 219 reset(); 220 Type = VT_Unsigned; 221 Value.Unsigned = NewValue; 222 } 223 224 bool VariantValue::isString() const { 225 return Type == VT_String; 226 } 227 228 const std::string &VariantValue::getString() const { 229 assert(isString()); 230 return *Value.String; 231 } 232 233 void VariantValue::setString(const std::string &NewValue) { 234 reset(); 235 Type = VT_String; 236 Value.String = new std::string(NewValue); 237 } 238 239 bool VariantValue::isMatcher() const { 240 return Type == VT_Matcher; 241 } 242 243 const VariantMatcher &VariantValue::getMatcher() const { 244 assert(isMatcher()); 245 return *Value.Matcher; 246 } 247 248 void VariantValue::setMatcher(const VariantMatcher &NewValue) { 249 reset(); 250 Type = VT_Matcher; 251 Value.Matcher = new VariantMatcher(NewValue); 252 } 253 254 std::string VariantValue::getTypeAsString() const { 255 switch (Type) { 256 case VT_String: return "String"; 257 case VT_Matcher: return getMatcher().getTypeAsString(); 258 case VT_Unsigned: return "Unsigned"; 259 case VT_Nothing: return "Nothing"; 260 } 261 llvm_unreachable("Invalid Type"); 262 } 263 264 } // end namespace dynamic 265 } // end namespace ast_matchers 266 } // end namespace clang 267