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