blob: a033edd22e1fa97bfc957437eec1ead8e3bef5f8 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Chris Lattner24943d22010-06-08 16:52:24 +000032#include "lldb/Symbol/SymbolFile.h"
33#include "lldb/Symbol/SymbolVendor.h"
34#include "lldb/Symbol/Type.h"
35#include "lldb/Symbol/TypeList.h"
36
37using namespace lldb;
38using namespace lldb_private;
39using namespace clang;
40
Greg Claytonb01000f2011-01-17 03:46:26 +000041TypeList::TypeList() :
Benjamin Kramer7a45a2f2010-07-20 14:37:45 +000042 m_types ()
Chris Lattner24943d22010-06-08 16:52:24 +000043{
44}
45
46//----------------------------------------------------------------------
47// Destructor
48//----------------------------------------------------------------------
49TypeList::~TypeList()
50{
51}
52
Greg Clayton3f5ee7f2010-10-29 04:59:35 +000053void
Greg Clayton4c8353b2011-10-18 23:36:41 +000054TypeList::Insert (const TypeSP& type_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000055{
Chris Lattner24943d22010-06-08 16:52:24 +000056 // Just push each type on the back for now. We will worry about uniquing later
Greg Clayton3f5ee7f2010-10-29 04:59:35 +000057 if (type_sp)
58 m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
59}
Chris Lattner24943d22010-06-08 16:52:24 +000060
Greg Clayton3f5ee7f2010-10-29 04:59:35 +000061
62bool
Greg Clayton4c8353b2011-10-18 23:36:41 +000063TypeList::InsertUnique (const TypeSP& type_sp)
Greg Clayton3f5ee7f2010-10-29 04:59:35 +000064{
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;
Chris Lattner24943d22010-06-08 16:52:24 +000078}
79
80//----------------------------------------------------------------------
81// Find a base type by its unique ID.
82//----------------------------------------------------------------------
Greg Clayton4c8353b2011-10-18 23:36:41 +000083//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//}
Chris Lattner24943d22010-06-08 16:52:24 +000091
92//----------------------------------------------------------------------
93// Find a type by name.
94//----------------------------------------------------------------------
Greg Claytonb01000f2011-01-17 03:46:26 +000095//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//}
Chris Lattner24943d22010-06-08 16:52:24 +0000107
108void
109TypeList::Clear()
110{
111 m_types.clear();
112}
113
114uint32_t
115TypeList::GetSize() const
116{
117 return m_types.size();
118}
119
Greg Clayton3f5ee7f2010-10-29 04:59:35 +0000120// 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
Chris Lattner24943d22010-06-08 16:52:24 +0000124TypeSP
125TypeList::GetTypeAtIndex(uint32_t idx)
126{
Greg Clayton3f5ee7f2010-10-29 04:59:35 +0000127 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();
Chris Lattner24943d22010-06-08 16:52:24 +0000136}
137
Greg Claytona8b56232013-06-18 22:51:05 +0000138void
139TypeList::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
148void
149TypeList::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
Greg Claytondc0a38c2012-03-26 23:03:23 +0000159bool
160TypeList::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
Chris Lattner24943d22010-06-08 16:52:24 +0000173void
174TypeList::Dump(Stream *s, bool show_context)
175{
Greg Clayton3f5ee7f2010-10-29 04:59:35 +0000176 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
Greg Clayton3f5ee7f2010-10-29 04:59:35 +0000178 pos->second->Dump(s, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000179 }
Chris Lattner24943d22010-06-08 16:52:24 +0000180}
181
Greg Claytondc0a38c2012-03-26 23:03:23 +0000182// depending on implementation details, type lookup might fail because of
183// embedded spurious namespace:: prefixes. this call strips them, paying
184// attention to the fact that a type might have namespace'd type names as
185// arguments to templates, and those must not be stripped off
186static bool
187GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
188{
189 // Protect against null c string.
190
191 if (name_cstr && name_cstr[0])
192 {
193 const char *basename_cstr = name_cstr;
194 const char* namespace_separator = ::strstr (basename_cstr, "::");
195 if (namespace_separator)
196 {
197 const char* template_arg_char = ::strchr (basename_cstr, '<');
198 while (namespace_separator != NULL)
199 {
200 if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go
201 break;
202 basename_cstr = namespace_separator + 2;
203 namespace_separator = strstr(basename_cstr, "::");
204 }
205 if (basename_cstr > name_cstr)
206 {
207 scope.assign (name_cstr, basename_cstr - name_cstr);
208 if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':')
209 {
210 // The typename passed in started with "::" so make sure we only do exact matches
211 if (exact_ptr)
212 *exact_ptr = true;
213 // Strip the leading "::" as this won't ever show in qualified typenames we get
214 // from clang.
215 scope.erase(0,2);
216 }
217 basename.assign (basename_cstr);
218 return true;
219 }
220 }
221 }
222 return false;
223}
224
225void
226TypeList::RemoveMismatchedTypes (const char *qualified_typename,
227 bool exact_match)
228{
229 std::string type_scope;
230 std::string type_basename;
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000231 TypeClass type_class = eTypeClassAny;
232 if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
Greg Claytondc0a38c2012-03-26 23:03:23 +0000233 {
234 type_basename = qualified_typename;
235 type_scope.clear();
236 }
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000237 return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
Greg Claytondc0a38c2012-03-26 23:03:23 +0000238}
239
240void
241TypeList::RemoveMismatchedTypes (const std::string &type_scope,
242 const std::string &type_basename,
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000243 TypeClass type_class,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000244 bool exact_match)
245{
246 // Our "collection" type currently is a std::map which doesn't
247 // have any good way to iterate and remove items from the map
248 // so we currently just make a new list and add all of the matching
249 // types to it, and then swap it into m_types at the end
250 collection matching_types;
251
252 iterator pos, end = m_types.end();
253
254 for (pos = m_types.begin(); pos != end; ++pos)
255 {
256 Type* the_type = pos->second.get();
257 bool keep_match = false;
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000258 TypeClass match_type_class = eTypeClassAny;
259
260 if (type_class != eTypeClassAny)
261 {
Greg Clayton52f79232013-07-11 22:46:58 +0000262 match_type_class = the_type->GetClangForwardType().GetTypeClass ();
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000263 if ((match_type_class & type_class) == 0)
264 continue;
265 }
Greg Claytondc0a38c2012-03-26 23:03:23 +0000266
267 ConstString match_type_name_const_str (the_type->GetQualifiedName());
268 if (match_type_name_const_str)
269 {
270 const char *match_type_name = match_type_name_const_str.GetCString();
271 std::string match_type_scope;
272 std::string match_type_basename;
273 if (Type::GetTypeScopeAndBasename (match_type_name,
274 match_type_scope,
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000275 match_type_basename,
276 match_type_class))
Greg Claytondc0a38c2012-03-26 23:03:23 +0000277 {
278 if (match_type_basename == type_basename)
279 {
280 const size_t type_scope_size = type_scope.size();
281 const size_t match_type_scope_size = match_type_scope.size();
282 if (exact_match || (type_scope_size == match_type_scope_size))
283 {
284 keep_match = match_type_scope == type_scope;
285 }
286 else
287 {
288 if (match_type_scope_size > type_scope_size)
289 {
290 const size_t type_scope_pos = match_type_scope.rfind(type_scope);
291 if (type_scope_pos == match_type_scope_size - type_scope_size)
292 {
293 if (type_scope_pos >= 2)
294 {
295 // Our match scope ends with the type scope we were lookikng for,
296 // but we need to make sure what comes before the matching
297 // type scope is a namepace boundary in case we are trying to match:
298 // type_basename = "d"
299 // type_scope = "b::c::"
300 // We want to match:
301 // match_type_scope "a::b::c::"
302 // But not:
303 // match_type_scope "a::bb::c::"
304 // So below we make sure what comes before "b::c::" in match_type_scope
305 // is "::", or the namespace boundary
306 if (match_type_scope[type_scope_pos - 1] == ':' &&
307 match_type_scope[type_scope_pos - 2] == ':')
308 {
309 keep_match = true;
310 }
311 }
312 }
313 }
314 }
315 }
316 }
317 else
318 {
319 // The type we are currently looking at doesn't exists
320 // in a namespace or class, so it only matches if there
321 // is no type scope...
322 keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0;
323 }
324 }
325
326 if (keep_match)
327 {
328 matching_types.insert (*pos);
329 }
330 }
331 m_types.swap(matching_types);
332}
333
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000334void
335TypeList::RemoveMismatchedTypes (TypeClass type_class)
336{
337 if (type_class == eTypeClassAny)
338 return;
339
340 // Our "collection" type currently is a std::map which doesn't
341 // have any good way to iterate and remove items from the map
342 // so we currently just make a new list and add all of the matching
343 // types to it, and then swap it into m_types at the end
344 collection matching_types;
345
346 iterator pos, end = m_types.end();
347
348 for (pos = m_types.begin(); pos != end; ++pos)
349 {
350 Type* the_type = pos->second.get();
Greg Clayton52f79232013-07-11 22:46:58 +0000351 TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
Greg Claytonb9bd4ee2012-10-22 16:19:56 +0000352 if (match_type_class & type_class)
353 matching_types.insert (*pos);
354 }
355 m_types.swap(matching_types);
356}