TypeList.cpp revision 254721
1181344Sdfr//===-- TypeList.cpp --------------------------------------------*- C++ -*-===//
2181344Sdfr//
3181344Sdfr//                     The LLVM Compiler Infrastructure
4181344Sdfr//
5181344Sdfr// This file is distributed under the University of Illinois Open Source
6181344Sdfr// License. See LICENSE.TXT for details.
7181344Sdfr//
8181344Sdfr//===----------------------------------------------------------------------===//
9181344Sdfr
10181344Sdfr
11181344Sdfr// C Includes
12181344Sdfr// C++ Includes
13181344Sdfr#include <vector>
14181344Sdfr
15181344Sdfr// Other libraries and framework includes
16181344Sdfr#include "clang/AST/ASTConsumer.h"
17181344Sdfr#include "clang/AST/ASTContext.h"
18181344Sdfr#include "clang/AST/Decl.h"
19181344Sdfr#include "clang/AST/DeclCXX.h"
20181344Sdfr#include "clang/AST/DeclGroup.h"
21181344Sdfr
22181344Sdfr#include "clang/Basic/Builtins.h"
23181344Sdfr#include "clang/Basic/IdentifierTable.h"
24181344Sdfr#include "clang/Basic/LangOptions.h"
25181344Sdfr#include "clang/Basic/SourceManager.h"
26181344Sdfr#include "clang/Basic/TargetInfo.h"
27181344Sdfr
28181344Sdfr#include "llvm/Support/FormattedStream.h"
29181344Sdfr#include "llvm/Support/raw_ostream.h"
30181344Sdfr
31181344Sdfr// Project includes
32181344Sdfr#include "lldb/Symbol/SymbolFile.h"
33181344Sdfr#include "lldb/Symbol/SymbolVendor.h"
34181344Sdfr#include "lldb/Symbol/Type.h"
35181344Sdfr#include "lldb/Symbol/TypeList.h"
36181344Sdfr
37181344Sdfrusing namespace lldb;
38181344Sdfrusing namespace lldb_private;
39181344Sdfrusing namespace clang;
40181344Sdfr
41181344SdfrTypeList::TypeList() :
42181344Sdfr    m_types ()
43181344Sdfr{
44181344Sdfr}
45181344Sdfr
46181344Sdfr//----------------------------------------------------------------------
47181344Sdfr// Destructor
48181344Sdfr//----------------------------------------------------------------------
49181344SdfrTypeList::~TypeList()
50181344Sdfr{
51181344Sdfr}
52181344Sdfr
53181344Sdfrvoid
54181344SdfrTypeList::Insert (const TypeSP& type_sp)
55181344Sdfr{
56181344Sdfr    // Just push each type on the back for now. We will worry about uniquing later
57181344Sdfr    if (type_sp)
58181344Sdfr        m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
59181344Sdfr}
60181344Sdfr
61181344Sdfr
62181344Sdfrbool
63181344SdfrTypeList::InsertUnique (const TypeSP& type_sp)
64181344Sdfr{
65181344Sdfr    if (type_sp)
66181344Sdfr    {
67181344Sdfr        user_id_t type_uid = type_sp->GetID();
68181344Sdfr        iterator pos, end = m_types.end();
69181344Sdfr
70181344Sdfr        for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos)
71181344Sdfr        {
72181344Sdfr            if (pos->second.get() == type_sp.get())
73181344Sdfr                return false;
74181344Sdfr        }
75181344Sdfr    }
76181344Sdfr    Insert (type_sp);
77181344Sdfr    return true;
78181344Sdfr}
79181344Sdfr
80181344Sdfr//----------------------------------------------------------------------
81181344Sdfr// Find a base type by its unique ID.
82181344Sdfr//----------------------------------------------------------------------
83181344Sdfr//TypeSP
84181344Sdfr//TypeList::FindType(lldb::user_id_t uid)
85181344Sdfr//{
86181344Sdfr//    iterator pos = m_types.find(uid);
87181344Sdfr//    if (pos != m_types.end())
88181344Sdfr//        return pos->second;
89181344Sdfr//    return TypeSP();
90181344Sdfr//}
91181344Sdfr
92181344Sdfr//----------------------------------------------------------------------
93181344Sdfr// Find a type by name.
94181344Sdfr//----------------------------------------------------------------------
95181344Sdfr//TypeList
96181344Sdfr//TypeList::FindTypes (const ConstString &name)
97181344Sdfr//{
98181344Sdfr//    // Do we ever need to make a lookup by name map? Here we are doing
99181344Sdfr//    // a linear search which isn't going to be fast.
100181344Sdfr//    TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
101181344Sdfr//    iterator pos, end;
102181344Sdfr//    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
103181344Sdfr//        if (pos->second->GetName() == name)
104181344Sdfr//            types.Insert (pos->second);
105181344Sdfr//    return types;
106181344Sdfr//}
107181344Sdfr
108181344Sdfrvoid
109181344SdfrTypeList::Clear()
110181344Sdfr{
111181344Sdfr    m_types.clear();
112181344Sdfr}
113181344Sdfr
114181344Sdfruint32_t
115181344SdfrTypeList::GetSize() const
116181344Sdfr{
117181344Sdfr    return m_types.size();
118181344Sdfr}
119181344Sdfr
120181344Sdfr// GetTypeAtIndex isn't used a lot for large type lists, currently only for
121181344Sdfr// type lists that are returned for "image dump -t TYPENAME" commands and other
122181344Sdfr// simple symbol queries that grab the first result...
123181344Sdfr
124181344SdfrTypeSP
125181344SdfrTypeList::GetTypeAtIndex(uint32_t idx)
126181344Sdfr{
127181344Sdfr    iterator pos, end;
128181344Sdfr    uint32_t i = idx;
129181344Sdfr    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
130181344Sdfr    {
131181344Sdfr        if (i == 0)
132181344Sdfr            return pos->second;
133181344Sdfr        --i;
134181344Sdfr    }
135181344Sdfr    return TypeSP();
136181344Sdfr}
137181344Sdfr
138181344Sdfrvoid
139181344SdfrTypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const
140181344Sdfr{
141181344Sdfr    for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
142181344Sdfr    {
143181344Sdfr        if (!callback(pos->second))
144181344Sdfr            break;
145181344Sdfr    }
146181344Sdfr}
147181344Sdfr
148181344Sdfrvoid
149181344SdfrTypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
150181344Sdfr{
151181344Sdfr    for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
152181344Sdfr    {
153181344Sdfr        if (!callback(pos->second))
154181344Sdfr            break;
155181344Sdfr    }
156181344Sdfr}
157181344Sdfr
158181344Sdfr
159181344Sdfrbool
160181344SdfrTypeList::RemoveTypeWithUID (user_id_t uid)
161181344Sdfr{
162181344Sdfr    iterator pos = m_types.find(uid);
163181344Sdfr
164181344Sdfr    if (pos != m_types.end())
165181344Sdfr    {
166181344Sdfr        m_types.erase(pos);
167181344Sdfr        return true;
168181344Sdfr    }
169181344Sdfr    return false;
170181344Sdfr}
171181344Sdfr
172181344Sdfr
173181344Sdfrvoid
174181344SdfrTypeList::Dump(Stream *s, bool show_context)
175181344Sdfr{
176181344Sdfr    for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
177181344Sdfr    {
178181344Sdfr        pos->second->Dump(s, show_context);
179181344Sdfr    }
180181344Sdfr}
181181344Sdfr
182181344Sdfr// depending on implementation details, type lookup might fail because of
183181344Sdfr// embedded spurious namespace:: prefixes. this call strips them, paying
184181344Sdfr// attention to the fact that a type might have namespace'd type names as
185181344Sdfr// arguments to templates, and those must not be stripped off
186181344Sdfrstatic bool
187181344SdfrGetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
188181344Sdfr{
189181344Sdfr    // Protect against null c string.
190181344Sdfr
191181344Sdfr    if (name_cstr && name_cstr[0])
192181344Sdfr    {
193181344Sdfr        const char *basename_cstr = name_cstr;
194181344Sdfr        const char* namespace_separator = ::strstr (basename_cstr, "::");
195181344Sdfr        if (namespace_separator)
196181344Sdfr        {
197181344Sdfr            const char* template_arg_char = ::strchr (basename_cstr, '<');
198181344Sdfr            while (namespace_separator != NULL)
199181344Sdfr            {
200181344Sdfr                if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go
201181344Sdfr                    break;
202181344Sdfr                basename_cstr = namespace_separator + 2;
203181344Sdfr                namespace_separator = strstr(basename_cstr, "::");
204181344Sdfr            }
205181344Sdfr            if (basename_cstr > name_cstr)
206181344Sdfr            {
207181344Sdfr                scope.assign (name_cstr, basename_cstr - name_cstr);
208181344Sdfr                if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':')
209181344Sdfr                {
210181344Sdfr                    // The typename passed in started with "::" so make sure we only do exact matches
211181344Sdfr                    if (exact_ptr)
212181344Sdfr                        *exact_ptr = true;
213181344Sdfr                    // Strip the leading "::" as this won't ever show in qualified typenames we get
214181344Sdfr                    // from clang.
215181344Sdfr                    scope.erase(0,2);
216181344Sdfr                }
217181344Sdfr                basename.assign (basename_cstr);
218181344Sdfr                return true;
219181344Sdfr            }
220181344Sdfr        }
221181344Sdfr    }
222181344Sdfr    return false;
223181344Sdfr}
224181344Sdfr
225181344Sdfrvoid
226181344SdfrTypeList::RemoveMismatchedTypes (const char *qualified_typename,
227181344Sdfr                                 bool exact_match)
228181344Sdfr{
229181344Sdfr    std::string type_scope;
230181344Sdfr    std::string type_basename;
231181344Sdfr    TypeClass type_class = eTypeClassAny;
232181344Sdfr    if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
233181344Sdfr    {
234181344Sdfr        type_basename = qualified_typename;
235181344Sdfr        type_scope.clear();
236181344Sdfr    }
237181344Sdfr    return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
238181344Sdfr}
239181344Sdfr
240181344Sdfrvoid
241181344SdfrTypeList::RemoveMismatchedTypes (const std::string &type_scope,
242181344Sdfr                                 const std::string &type_basename,
243181344Sdfr                                 TypeClass type_class,
244181344Sdfr                                 bool exact_match)
245181344Sdfr{
246181344Sdfr    // Our "collection" type currently is a std::map which doesn't
247181344Sdfr    // have any good way to iterate and remove items from the map
248181344Sdfr    // so we currently just make a new list and add all of the matching
249181344Sdfr    // types to it, and then swap it into m_types at the end
250181344Sdfr    collection matching_types;
251181344Sdfr
252181344Sdfr    iterator pos, end = m_types.end();
253181344Sdfr
254181344Sdfr    for (pos = m_types.begin(); pos != end; ++pos)
255181344Sdfr    {
256181344Sdfr        Type* the_type = pos->second.get();
257181344Sdfr        bool keep_match = false;
258181344Sdfr        TypeClass match_type_class = eTypeClassAny;
259181344Sdfr
260181344Sdfr        if (type_class != eTypeClassAny)
261181344Sdfr        {
262181344Sdfr            match_type_class = the_type->GetClangForwardType().GetTypeClass ();
263181344Sdfr            if ((match_type_class & type_class) == 0)
264181344Sdfr                continue;
265181344Sdfr        }
266181344Sdfr
267181344Sdfr        ConstString match_type_name_const_str (the_type->GetQualifiedName());
268181344Sdfr        if (match_type_name_const_str)
269181344Sdfr        {
270181344Sdfr            const char *match_type_name = match_type_name_const_str.GetCString();
271181344Sdfr            std::string match_type_scope;
272181344Sdfr            std::string match_type_basename;
273181344Sdfr            if (Type::GetTypeScopeAndBasename (match_type_name,
274181344Sdfr                                               match_type_scope,
275181344Sdfr                                               match_type_basename,
276181344Sdfr                                               match_type_class))
277181344Sdfr            {
278181344Sdfr                if (match_type_basename == type_basename)
279181344Sdfr                {
280181344Sdfr                    const size_t type_scope_size = type_scope.size();
281181344Sdfr                    const size_t match_type_scope_size = match_type_scope.size();
282181344Sdfr                    if (exact_match || (type_scope_size == match_type_scope_size))
283181344Sdfr                    {
284181344Sdfr                        keep_match = match_type_scope == type_scope;
285181344Sdfr                    }
286181344Sdfr                    else
287181344Sdfr                    {
288181344Sdfr                        if (match_type_scope_size > type_scope_size)
289181344Sdfr                        {
290181344Sdfr                            const size_t type_scope_pos = match_type_scope.rfind(type_scope);
291181344Sdfr                            if (type_scope_pos == match_type_scope_size - type_scope_size)
292181344Sdfr                            {
293181344Sdfr                                if (type_scope_pos >= 2)
294181344Sdfr                                {
295181344Sdfr                                    // Our match scope ends with the type scope we were lookikng for,
296181344Sdfr                                    // but we need to make sure what comes before the matching
297181344Sdfr                                    // type scope is a namepace boundary in case we are trying to match:
298181344Sdfr                                    // type_basename = "d"
299181344Sdfr                                    // type_scope = "b::c::"
300181344Sdfr                                    // We want to match:
301181344Sdfr                                    //  match_type_scope "a::b::c::"
302181344Sdfr                                    // But not:
303181344Sdfr                                    //  match_type_scope "a::bb::c::"
304181344Sdfr                                    // So below we make sure what comes before "b::c::" in match_type_scope
305181344Sdfr                                    // is "::", or the namespace boundary
306181344Sdfr                                    if (match_type_scope[type_scope_pos - 1] == ':' &&
307181344Sdfr                                        match_type_scope[type_scope_pos - 2] == ':')
308181344Sdfr                                    {
309181344Sdfr                                        keep_match = true;
310181344Sdfr                                    }
311181344Sdfr                                }
312181344Sdfr                            }
313181344Sdfr                        }
314181344Sdfr                    }
315181344Sdfr                }
316181344Sdfr            }
317181344Sdfr            else
318181344Sdfr            {
319181344Sdfr                // The type we are currently looking at doesn't exists
320181344Sdfr                // in a namespace or class, so it only matches if there
321181344Sdfr                // is no type scope...
322181344Sdfr                keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0;
323181344Sdfr            }
324181344Sdfr        }
325181344Sdfr
326181344Sdfr        if (keep_match)
327181344Sdfr        {
328181344Sdfr            matching_types.insert (*pos);
329181344Sdfr        }
330181344Sdfr    }
331181344Sdfr    m_types.swap(matching_types);
332181344Sdfr}
333181344Sdfr
334181344Sdfrvoid
335181344SdfrTypeList::RemoveMismatchedTypes (TypeClass type_class)
336181344Sdfr{
337181344Sdfr    if (type_class == eTypeClassAny)
338181344Sdfr        return;
339181344Sdfr
340181344Sdfr    // Our "collection" type currently is a std::map which doesn't
341181344Sdfr    // have any good way to iterate and remove items from the map
342181344Sdfr    // so we currently just make a new list and add all of the matching
343181344Sdfr    // types to it, and then swap it into m_types at the end
344181344Sdfr    collection matching_types;
345181344Sdfr
346181344Sdfr    iterator pos, end = m_types.end();
347181344Sdfr
348181344Sdfr    for (pos = m_types.begin(); pos != end; ++pos)
349181344Sdfr    {
350181344Sdfr        Type* the_type = pos->second.get();
351181344Sdfr        TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
352181344Sdfr        if (match_type_class & type_class)
353181344Sdfr            matching_types.insert (*pos);
354181344Sdfr    }
355181344Sdfr    m_types.swap(matching_types);
356181344Sdfr}
357181344Sdfr