1 //===-- TypeList.cpp --------------------------------------------*- 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
11 // C Includes
12 // C++ Includes
13 #include <vector>
14
15 // Other libraries and framework includes
16 #include "clang/AST/ASTConsumer.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclGroup.h"
21
22 #include "clang/Basic/Builtins.h"
23 #include "clang/Basic/IdentifierTable.h"
24 #include "clang/Basic/LangOptions.h"
25 #include "clang/Basic/SourceManager.h"
26 #include "clang/Basic/TargetInfo.h"
27
28 #include "llvm/Support/FormattedStream.h"
29 #include "llvm/Support/raw_ostream.h"
30
31 // Project includes
32 #include "lldb/Symbol/SymbolFile.h"
33 #include "lldb/Symbol/SymbolVendor.h"
34 #include "lldb/Symbol/Type.h"
35 #include "lldb/Symbol/TypeList.h"
36
37 using namespace lldb;
38 using namespace lldb_private;
39 using namespace clang;
40
TypeList()41 TypeList::TypeList() :
42 m_types ()
43 {
44 }
45
46 //----------------------------------------------------------------------
47 // Destructor
48 //----------------------------------------------------------------------
~TypeList()49 TypeList::~TypeList()
50 {
51 }
52
53 void
Insert(const TypeSP & type_sp)54 TypeList::Insert (const TypeSP& type_sp)
55 {
56 // Just push each type on the back for now. We will worry about uniquing later
57 if (type_sp)
58 m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
59 }
60
61
62 bool
InsertUnique(const TypeSP & type_sp)63 TypeList::InsertUnique (const TypeSP& type_sp)
64 {
65 if (type_sp)
66 {
67 user_id_t type_uid = type_sp->GetID();
68 iterator pos, end = m_types.end();
69
70 for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos)
71 {
72 if (pos->second.get() == type_sp.get())
73 return false;
74 }
75 }
76 Insert (type_sp);
77 return true;
78 }
79
80 //----------------------------------------------------------------------
81 // Find a base type by its unique ID.
82 //----------------------------------------------------------------------
83 //TypeSP
84 //TypeList::FindType(lldb::user_id_t uid)
85 //{
86 // iterator pos = m_types.find(uid);
87 // if (pos != m_types.end())
88 // return pos->second;
89 // return TypeSP();
90 //}
91
92 //----------------------------------------------------------------------
93 // Find a type by name.
94 //----------------------------------------------------------------------
95 //TypeList
96 //TypeList::FindTypes (const ConstString &name)
97 //{
98 // // Do we ever need to make a lookup by name map? Here we are doing
99 // // a linear search which isn't going to be fast.
100 // TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
101 // iterator pos, end;
102 // for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
103 // if (pos->second->GetName() == name)
104 // types.Insert (pos->second);
105 // return types;
106 //}
107
108 void
Clear()109 TypeList::Clear()
110 {
111 m_types.clear();
112 }
113
114 uint32_t
GetSize() const115 TypeList::GetSize() const
116 {
117 return m_types.size();
118 }
119
120 // GetTypeAtIndex isn't used a lot for large type lists, currently only for
121 // type lists that are returned for "image dump -t TYPENAME" commands and other
122 // simple symbol queries that grab the first result...
123
124 TypeSP
GetTypeAtIndex(uint32_t idx)125 TypeList::GetTypeAtIndex(uint32_t idx)
126 {
127 iterator pos, end;
128 uint32_t i = idx;
129 for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
130 {
131 if (i == 0)
132 return pos->second;
133 --i;
134 }
135 return TypeSP();
136 }
137
138 void
ForEach(std::function<bool (const lldb::TypeSP & type_sp)> const & callback) const139 TypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const
140 {
141 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
142 {
143 if (!callback(pos->second))
144 break;
145 }
146 }
147
148 void
ForEach(std::function<bool (lldb::TypeSP & type_sp)> const & callback)149 TypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
150 {
151 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
152 {
153 if (!callback(pos->second))
154 break;
155 }
156 }
157
158
159 bool
RemoveTypeWithUID(user_id_t uid)160 TypeList::RemoveTypeWithUID (user_id_t uid)
161 {
162 iterator pos = m_types.find(uid);
163
164 if (pos != m_types.end())
165 {
166 m_types.erase(pos);
167 return true;
168 }
169 return false;
170 }
171
172
173 void
Dump(Stream * s,bool show_context)174 TypeList::Dump(Stream *s, bool show_context)
175 {
176 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
177 {
178 pos->second->Dump(s, show_context);
179 }
180 }
181
182 void
RemoveMismatchedTypes(const char * qualified_typename,bool exact_match)183 TypeList::RemoveMismatchedTypes (const char *qualified_typename,
184 bool exact_match)
185 {
186 std::string type_scope;
187 std::string type_basename;
188 TypeClass type_class = eTypeClassAny;
189 if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
190 {
191 type_basename = qualified_typename;
192 type_scope.clear();
193 }
194 return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
195 }
196
197 void
RemoveMismatchedTypes(const std::string & type_scope,const std::string & type_basename,TypeClass type_class,bool exact_match)198 TypeList::RemoveMismatchedTypes (const std::string &type_scope,
199 const std::string &type_basename,
200 TypeClass type_class,
201 bool exact_match)
202 {
203 // Our "collection" type currently is a std::map which doesn't
204 // have any good way to iterate and remove items from the map
205 // so we currently just make a new list and add all of the matching
206 // types to it, and then swap it into m_types at the end
207 collection matching_types;
208
209 iterator pos, end = m_types.end();
210
211 for (pos = m_types.begin(); pos != end; ++pos)
212 {
213 Type* the_type = pos->second.get();
214 bool keep_match = false;
215 TypeClass match_type_class = eTypeClassAny;
216
217 if (type_class != eTypeClassAny)
218 {
219 match_type_class = the_type->GetClangForwardType().GetTypeClass ();
220 if ((match_type_class & type_class) == 0)
221 continue;
222 }
223
224 ConstString match_type_name_const_str (the_type->GetQualifiedName());
225 if (match_type_name_const_str)
226 {
227 const char *match_type_name = match_type_name_const_str.GetCString();
228 std::string match_type_scope;
229 std::string match_type_basename;
230 if (Type::GetTypeScopeAndBasename (match_type_name,
231 match_type_scope,
232 match_type_basename,
233 match_type_class))
234 {
235 if (match_type_basename == type_basename)
236 {
237 const size_t type_scope_size = type_scope.size();
238 const size_t match_type_scope_size = match_type_scope.size();
239 if (exact_match || (type_scope_size == match_type_scope_size))
240 {
241 keep_match = match_type_scope == type_scope;
242 }
243 else
244 {
245 if (match_type_scope_size > type_scope_size)
246 {
247 const size_t type_scope_pos = match_type_scope.rfind(type_scope);
248 if (type_scope_pos == match_type_scope_size - type_scope_size)
249 {
250 if (type_scope_pos >= 2)
251 {
252 // Our match scope ends with the type scope we were lookikng for,
253 // but we need to make sure what comes before the matching
254 // type scope is a namepace boundary in case we are trying to match:
255 // type_basename = "d"
256 // type_scope = "b::c::"
257 // We want to match:
258 // match_type_scope "a::b::c::"
259 // But not:
260 // match_type_scope "a::bb::c::"
261 // So below we make sure what comes before "b::c::" in match_type_scope
262 // is "::", or the namespace boundary
263 if (match_type_scope[type_scope_pos - 1] == ':' &&
264 match_type_scope[type_scope_pos - 2] == ':')
265 {
266 keep_match = true;
267 }
268 }
269 }
270 }
271 }
272 }
273 }
274 else
275 {
276 // The type we are currently looking at doesn't exists
277 // in a namespace or class, so it only matches if there
278 // is no type scope...
279 keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0;
280 }
281 }
282
283 if (keep_match)
284 {
285 matching_types.insert (*pos);
286 }
287 }
288 m_types.swap(matching_types);
289 }
290
291 void
RemoveMismatchedTypes(TypeClass type_class)292 TypeList::RemoveMismatchedTypes (TypeClass type_class)
293 {
294 if (type_class == eTypeClassAny)
295 return;
296
297 // Our "collection" type currently is a std::map which doesn't
298 // have any good way to iterate and remove items from the map
299 // so we currently just make a new list and add all of the matching
300 // types to it, and then swap it into m_types at the end
301 collection matching_types;
302
303 iterator pos, end = m_types.end();
304
305 for (pos = m_types.begin(); pos != end; ++pos)
306 {
307 Type* the_type = pos->second.get();
308 TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
309 if (match_type_class & type_class)
310 matching_types.insert (*pos);
311 }
312 m_types.swap(matching_types);
313 }
314