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