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