]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Symbol / TypeList.cpp
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
41 TypeList::TypeList() :
42     m_types ()
43 {
44 }
45
46 //----------------------------------------------------------------------
47 // Destructor
48 //----------------------------------------------------------------------
49 TypeList::~TypeList()
50 {
51 }
52
53 void
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
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
109 TypeList::Clear()
110 {
111     m_types.clear();
112 }
113
114 uint32_t
115 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
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
139 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
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
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
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 // 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
186 static bool
187 GetTypeScopeAndBasename(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
225 void
226 TypeList::RemoveMismatchedTypes (const char *qualified_typename,
227                                  bool exact_match)
228 {
229     std::string type_scope;
230     std::string type_basename;
231     TypeClass type_class = eTypeClassAny;
232     if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
233     {
234         type_basename = qualified_typename;
235         type_scope.clear();
236     }
237     return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
238 }
239
240 void
241 TypeList::RemoveMismatchedTypes (const std::string &type_scope,
242                                  const std::string &type_basename,
243                                  TypeClass type_class,
244                                  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;
258         TypeClass match_type_class = eTypeClassAny;
259
260         if (type_class != eTypeClassAny)
261         {
262             match_type_class = the_type->GetClangForwardType().GetTypeClass ();
263             if ((match_type_class & type_class) == 0)
264                 continue;
265         }
266
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,
275                                                match_type_basename,
276                                                match_type_class))
277             {
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
334 void
335 TypeList::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();
351         TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
352         if (match_type_class & type_class)
353             matching_types.insert (*pos);
354     }
355     m_types.swap(matching_types);
356 }