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 19namespace clang { 20namespace ast_matchers { 21namespace dynamic { 22 23VariantMatcher::MatcherOps::~MatcherOps() {} 24VariantMatcher::Payload::~Payload() {} 25 26class VariantMatcher::SinglePayload : public VariantMatcher::Payload { 27public: 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 45private: 46 const DynTypedMatcher Matcher; 47}; 48 49class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { 50public: 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 98class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { 99public: 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 122private: 123 const ast_matchers::internal::VariadicOperatorFunction Func; 124 const std::vector<VariantMatcher> Args; 125}; 126 127VariantMatcher::VariantMatcher() {} 128 129VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { 130 return VariantMatcher(new SinglePayload(Matcher)); 131} 132 133VariantMatcher 134VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { 135 return VariantMatcher(new PolymorphicPayload(std::move(Matchers))); 136} 137 138VariantMatcher VariantMatcher::VariadicOperatorMatcher( 139 ast_matchers::internal::VariadicOperatorFunction Func, 140 std::vector<VariantMatcher> Args) { 141 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args))); 142} 143 144llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { 145 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>(); 146} 147 148void VariantMatcher::reset() { Value.reset(); } 149 150std::string VariantMatcher::getTypeAsString() const { 151 if (Value) return Value->getTypeAsString(); 152 return "<Nothing>"; 153} 154 155VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { 156 *this = Other; 157} 158 159VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { 160 setUnsigned(Unsigned); 161} 162 163VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) { 164 setString(String); 165} 166 167VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) { 168 setMatcher(Matcher); 169} 170 171VariantValue::~VariantValue() { reset(); } 172 173VariantValue &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 193void 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 209bool VariantValue::isUnsigned() const { 210 return Type == VT_Unsigned; 211} 212 213unsigned VariantValue::getUnsigned() const { 214 assert(isUnsigned()); 215 return Value.Unsigned; 216} 217 218void VariantValue::setUnsigned(unsigned NewValue) { 219 reset(); 220 Type = VT_Unsigned; 221 Value.Unsigned = NewValue; 222} 223 224bool VariantValue::isString() const { 225 return Type == VT_String; 226} 227 228const std::string &VariantValue::getString() const { 229 assert(isString()); 230 return *Value.String; 231} 232 233void VariantValue::setString(const std::string &NewValue) { 234 reset(); 235 Type = VT_String; 236 Value.String = new std::string(NewValue); 237} 238 239bool VariantValue::isMatcher() const { 240 return Type == VT_Matcher; 241} 242 243const VariantMatcher &VariantValue::getMatcher() const { 244 assert(isMatcher()); 245 return *Value.Matcher; 246} 247 248void VariantValue::setMatcher(const VariantMatcher &NewValue) { 249 reset(); 250 Type = VT_Matcher; 251 Value.Matcher = new VariantMatcher(NewValue); 252} 253 254std::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