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::VariantMatcher() : List() {}
25 
26 VariantMatcher::VariantMatcher(const VariantMatcher& Other) {
27   *this = Other;
28 }
29 
30 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
31   VariantMatcher Out;
32   Out.List.push_back(Matcher.clone());
33   return Out;
34 }
35 
36 VariantMatcher
37 VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
38   VariantMatcher Out;
39   for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
40     Out.List.push_back(Matchers[i]->clone());
41   }
42   return Out;
43 }
44 
45 VariantMatcher::~VariantMatcher() {
46   reset();
47 }
48 
49 VariantMatcher &VariantMatcher::operator=(const VariantMatcher &Other) {
50   if (this == &Other) return *this;
51   reset();
52   for (size_t i = 0, e = Other.List.size(); i != e; ++i) {
53     List.push_back(Other.List[i]->clone());
54   }
55   return *this;
56 }
57 
58 bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
59   if (List.size() != 1) return false;
60   Out = List[0];
61   return true;
62 }
63 
64 void VariantMatcher::reset() {
65   llvm::DeleteContainerPointers(List);
66 }
67 
68 std::string VariantMatcher::getTypeAsString() const {
69   std::string Inner;
70   for (size_t I = 0, E = List.size(); I != E; ++I) {
71     if (I != 0) Inner += "|";
72     Inner += List[I]->getSupportedKind().asStringRef();
73   }
74   return (Twine("Matcher<") + Inner + ">").str();
75 }
76 
77 const DynTypedMatcher *VariantMatcher::getTypedMatcher(
78     bool (*CanConstructCallback)(const DynTypedMatcher &)) const {
79   const DynTypedMatcher *Out = NULL;
80   for (size_t i = 0, e = List.size(); i != e; ++i) {
81     if (CanConstructCallback(*List[i])) {
82       if (Out) return NULL;
83       Out = List[i];
84     }
85   }
86   return Out;
87 }
88 
89 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
90   *this = Other;
91 }
92 
93 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
94   setUnsigned(Unsigned);
95 }
96 
97 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
98   setString(String);
99 }
100 
101 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
102   setMatcher(Matcher);
103 }
104 
105 VariantValue::~VariantValue() { reset(); }
106 
107 VariantValue &VariantValue::operator=(const VariantValue &Other) {
108   if (this == &Other) return *this;
109   reset();
110   switch (Other.Type) {
111   case VT_Unsigned:
112     setUnsigned(Other.getUnsigned());
113     break;
114   case VT_String:
115     setString(Other.getString());
116     break;
117   case VT_Matcher:
118     setMatcher(Other.getMatcher());
119     break;
120   case VT_Nothing:
121     Type = VT_Nothing;
122     break;
123   }
124   return *this;
125 }
126 
127 void VariantValue::reset() {
128   switch (Type) {
129   case VT_String:
130     delete Value.String;
131     break;
132   case VT_Matcher:
133     delete Value.Matcher;
134     break;
135   // Cases that do nothing.
136   case VT_Unsigned:
137   case VT_Nothing:
138     break;
139   }
140   Type = VT_Nothing;
141 }
142 
143 bool VariantValue::isUnsigned() const {
144   return Type == VT_Unsigned;
145 }
146 
147 unsigned VariantValue::getUnsigned() const {
148   assert(isUnsigned());
149   return Value.Unsigned;
150 }
151 
152 void VariantValue::setUnsigned(unsigned NewValue) {
153   reset();
154   Type = VT_Unsigned;
155   Value.Unsigned = NewValue;
156 }
157 
158 bool VariantValue::isString() const {
159   return Type == VT_String;
160 }
161 
162 const std::string &VariantValue::getString() const {
163   assert(isString());
164   return *Value.String;
165 }
166 
167 void VariantValue::setString(const std::string &NewValue) {
168   reset();
169   Type = VT_String;
170   Value.String = new std::string(NewValue);
171 }
172 
173 bool VariantValue::isMatcher() const {
174   return Type == VT_Matcher;
175 }
176 
177 const VariantMatcher &VariantValue::getMatcher() const {
178   assert(isMatcher());
179   return *Value.Matcher;
180 }
181 
182 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
183   reset();
184   Type = VT_Matcher;
185   Value.Matcher = new VariantMatcher(NewValue);
186 }
187 
188 std::string VariantValue::getTypeAsString() const {
189   switch (Type) {
190   case VT_String: return "String";
191   case VT_Matcher: return getMatcher().getTypeAsString();
192   case VT_Unsigned: return "Unsigned";
193   case VT_Nothing: return "Nothing";
194   }
195   llvm_unreachable("Invalid Type");
196 }
197 
198 } // end namespace dynamic
199 } // end namespace ast_matchers
200 } // end namespace clang
201