1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Polymorphic value type.
13 //===----------------------------------------------------------------------===//
15 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
16 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/STLExtras.h"
20 namespace ast_matchers {
23 VariantMatcher::MatcherOps::~MatcherOps() {}
24 VariantMatcher::Payload::~Payload() {}
26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
28 SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
30 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
34 virtual std::string getTypeAsString() const {
35 return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
39 virtual void makeTypedMatcher(MatcherOps &Ops) const {
41 if (Ops.canConstructFrom(Matcher, Ignore))
42 Ops.constructFrom(Matcher);
46 const DynTypedMatcher Matcher;
49 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
51 PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
52 : Matchers(std::move(MatchersIn)) {}
54 virtual ~PolymorphicPayload() {}
56 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
57 if (Matchers.size() != 1)
58 return llvm::Optional<DynTypedMatcher>();
62 virtual std::string getTypeAsString() const {
64 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
67 Inner += Matchers[i].getSupportedKind().asStringRef();
69 return (Twine("Matcher<") + Inner + ">").str();
72 virtual void makeTypedMatcher(MatcherOps &Ops) const {
73 bool FoundIsExact = false;
74 const DynTypedMatcher *Found = nullptr;
76 for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
78 if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
81 assert(!IsExactMatch && "We should not have two exact matches.");
86 FoundIsExact = IsExactMatch;
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);
95 const std::vector<DynTypedMatcher> Matchers;
98 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
100 VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
101 std::vector<VariantMatcher> Args)
102 : Func(Func), Args(std::move(Args)) {}
104 virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
105 return llvm::Optional<DynTypedMatcher>();
108 virtual std::string getTypeAsString() const {
110 for (size_t i = 0, e = Args.size(); i != e; ++i) {
113 Inner += Args[i].getTypeAsString();
118 virtual void makeTypedMatcher(MatcherOps &Ops) const {
119 Ops.constructVariadicOperator(Func, Args);
123 const ast_matchers::internal::VariadicOperatorFunction Func;
124 const std::vector<VariantMatcher> Args;
127 VariantMatcher::VariantMatcher() {}
129 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
130 return VariantMatcher(new SinglePayload(Matcher));
134 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
135 return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
138 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
139 ast_matchers::internal::VariadicOperatorFunction Func,
140 std::vector<VariantMatcher> Args) {
141 return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
144 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
145 return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
148 void VariantMatcher::reset() { Value.reset(); }
150 std::string VariantMatcher::getTypeAsString() const {
151 if (Value) return Value->getTypeAsString();
155 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
159 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
160 setUnsigned(Unsigned);
163 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
167 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
171 VariantValue::~VariantValue() { reset(); }
173 VariantValue &VariantValue::operator=(const VariantValue &Other) {
174 if (this == &Other) return *this;
176 switch (Other.Type) {
178 setUnsigned(Other.getUnsigned());
181 setString(Other.getString());
184 setMatcher(Other.getMatcher());
193 void VariantValue::reset() {
199 delete Value.Matcher;
201 // Cases that do nothing.
209 bool VariantValue::isUnsigned() const {
210 return Type == VT_Unsigned;
213 unsigned VariantValue::getUnsigned() const {
214 assert(isUnsigned());
215 return Value.Unsigned;
218 void VariantValue::setUnsigned(unsigned NewValue) {
221 Value.Unsigned = NewValue;
224 bool VariantValue::isString() const {
225 return Type == VT_String;
228 const std::string &VariantValue::getString() const {
230 return *Value.String;
233 void VariantValue::setString(const std::string &NewValue) {
236 Value.String = new std::string(NewValue);
239 bool VariantValue::isMatcher() const {
240 return Type == VT_Matcher;
243 const VariantMatcher &VariantValue::getMatcher() const {
245 return *Value.Matcher;
248 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
251 Value.Matcher = new VariantMatcher(NewValue);
254 std::string VariantValue::getTypeAsString() const {
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";
261 llvm_unreachable("Invalid Type");
264 } // end namespace dynamic
265 } // end namespace ast_matchers
266 } // end namespace clang