1254721Semaste//===-- TypeList.cpp --------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste
11254721Semaste// C Includes
12254721Semaste// C++ Includes
13254721Semaste#include <vector>
14254721Semaste
15254721Semaste// Other libraries and framework includes
16254721Semaste#include "clang/AST/ASTConsumer.h"
17254721Semaste#include "clang/AST/ASTContext.h"
18254721Semaste#include "clang/AST/Decl.h"
19254721Semaste#include "clang/AST/DeclCXX.h"
20254721Semaste#include "clang/AST/DeclGroup.h"
21254721Semaste
22254721Semaste#include "clang/Basic/Builtins.h"
23254721Semaste#include "clang/Basic/IdentifierTable.h"
24254721Semaste#include "clang/Basic/LangOptions.h"
25254721Semaste#include "clang/Basic/SourceManager.h"
26254721Semaste#include "clang/Basic/TargetInfo.h"
27254721Semaste
28254721Semaste#include "llvm/Support/FormattedStream.h"
29254721Semaste#include "llvm/Support/raw_ostream.h"
30254721Semaste
31254721Semaste// Project includes
32254721Semaste#include "lldb/Symbol/SymbolFile.h"
33254721Semaste#include "lldb/Symbol/SymbolVendor.h"
34254721Semaste#include "lldb/Symbol/Type.h"
35254721Semaste#include "lldb/Symbol/TypeList.h"
36254721Semaste
37254721Semasteusing namespace lldb;
38254721Semasteusing namespace lldb_private;
39254721Semasteusing namespace clang;
40254721Semaste
41254721SemasteTypeList::TypeList() :
42254721Semaste    m_types ()
43254721Semaste{
44254721Semaste}
45254721Semaste
46254721Semaste//----------------------------------------------------------------------
47254721Semaste// Destructor
48254721Semaste//----------------------------------------------------------------------
49254721SemasteTypeList::~TypeList()
50254721Semaste{
51254721Semaste}
52254721Semaste
53254721Semastevoid
54254721SemasteTypeList::Insert (const TypeSP& type_sp)
55254721Semaste{
56254721Semaste    // Just push each type on the back for now. We will worry about uniquing later
57254721Semaste    if (type_sp)
58254721Semaste        m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
59254721Semaste}
60254721Semaste
61254721Semaste
62254721Semastebool
63254721SemasteTypeList::InsertUnique (const TypeSP& type_sp)
64254721Semaste{
65254721Semaste    if (type_sp)
66254721Semaste    {
67254721Semaste        user_id_t type_uid = type_sp->GetID();
68254721Semaste        iterator pos, end = m_types.end();
69254721Semaste
70254721Semaste        for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos)
71254721Semaste        {
72254721Semaste            if (pos->second.get() == type_sp.get())
73254721Semaste                return false;
74254721Semaste        }
75254721Semaste    }
76254721Semaste    Insert (type_sp);
77254721Semaste    return true;
78254721Semaste}
79254721Semaste
80254721Semaste//----------------------------------------------------------------------
81254721Semaste// Find a base type by its unique ID.
82254721Semaste//----------------------------------------------------------------------
83254721Semaste//TypeSP
84254721Semaste//TypeList::FindType(lldb::user_id_t uid)
85254721Semaste//{
86254721Semaste//    iterator pos = m_types.find(uid);
87254721Semaste//    if (pos != m_types.end())
88254721Semaste//        return pos->second;
89254721Semaste//    return TypeSP();
90254721Semaste//}
91254721Semaste
92254721Semaste//----------------------------------------------------------------------
93254721Semaste// Find a type by name.
94254721Semaste//----------------------------------------------------------------------
95254721Semaste//TypeList
96254721Semaste//TypeList::FindTypes (const ConstString &name)
97254721Semaste//{
98254721Semaste//    // Do we ever need to make a lookup by name map? Here we are doing
99254721Semaste//    // a linear search which isn't going to be fast.
100254721Semaste//    TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
101254721Semaste//    iterator pos, end;
102254721Semaste//    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
103254721Semaste//        if (pos->second->GetName() == name)
104254721Semaste//            types.Insert (pos->second);
105254721Semaste//    return types;
106254721Semaste//}
107254721Semaste
108254721Semastevoid
109254721SemasteTypeList::Clear()
110254721Semaste{
111254721Semaste    m_types.clear();
112254721Semaste}
113254721Semaste
114254721Semasteuint32_t
115254721SemasteTypeList::GetSize() const
116254721Semaste{
117254721Semaste    return m_types.size();
118254721Semaste}
119254721Semaste
120254721Semaste// GetTypeAtIndex isn't used a lot for large type lists, currently only for
121254721Semaste// type lists that are returned for "image dump -t TYPENAME" commands and other
122254721Semaste// simple symbol queries that grab the first result...
123254721Semaste
124254721SemasteTypeSP
125254721SemasteTypeList::GetTypeAtIndex(uint32_t idx)
126254721Semaste{
127254721Semaste    iterator pos, end;
128254721Semaste    uint32_t i = idx;
129254721Semaste    for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
130254721Semaste    {
131254721Semaste        if (i == 0)
132254721Semaste            return pos->second;
133254721Semaste        --i;
134254721Semaste    }
135254721Semaste    return TypeSP();
136254721Semaste}
137254721Semaste
138254721Semastevoid
139254721SemasteTypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const
140254721Semaste{
141254721Semaste    for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
142254721Semaste    {
143254721Semaste        if (!callback(pos->second))
144254721Semaste            break;
145254721Semaste    }
146254721Semaste}
147254721Semaste
148254721Semastevoid
149254721SemasteTypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
150254721Semaste{
151254721Semaste    for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
152254721Semaste    {
153254721Semaste        if (!callback(pos->second))
154254721Semaste            break;
155254721Semaste    }
156254721Semaste}
157254721Semaste
158254721Semaste
159254721Semastebool
160254721SemasteTypeList::RemoveTypeWithUID (user_id_t uid)
161254721Semaste{
162254721Semaste    iterator pos = m_types.find(uid);
163254721Semaste
164254721Semaste    if (pos != m_types.end())
165254721Semaste    {
166254721Semaste        m_types.erase(pos);
167254721Semaste        return true;
168254721Semaste    }
169254721Semaste    return false;
170254721Semaste}
171254721Semaste
172254721Semaste
173254721Semastevoid
174254721SemasteTypeList::Dump(Stream *s, bool show_context)
175254721Semaste{
176254721Semaste    for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
177254721Semaste    {
178254721Semaste        pos->second->Dump(s, show_context);
179254721Semaste    }
180254721Semaste}
181254721Semaste
182254721Semaste// depending on implementation details, type lookup might fail because of
183254721Semaste// embedded spurious namespace:: prefixes. this call strips them, paying
184254721Semaste// attention to the fact that a type might have namespace'd type names as
185254721Semaste// arguments to templates, and those must not be stripped off
186254721Semastestatic bool
187254721SemasteGetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr)
188254721Semaste{
189254721Semaste    // Protect against null c string.
190254721Semaste
191254721Semaste    if (name_cstr && name_cstr[0])
192254721Semaste    {
193254721Semaste        const char *basename_cstr = name_cstr;
194254721Semaste        const char* namespace_separator = ::strstr (basename_cstr, "::");
195254721Semaste        if (namespace_separator)
196254721Semaste        {
197254721Semaste            const char* template_arg_char = ::strchr (basename_cstr, '<');
198254721Semaste            while (namespace_separator != NULL)
199254721Semaste            {
200254721Semaste                if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go
201254721Semaste                    break;
202254721Semaste                basename_cstr = namespace_separator + 2;
203254721Semaste                namespace_separator = strstr(basename_cstr, "::");
204254721Semaste            }
205254721Semaste            if (basename_cstr > name_cstr)
206254721Semaste            {
207254721Semaste                scope.assign (name_cstr, basename_cstr - name_cstr);
208254721Semaste                if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':')
209254721Semaste                {
210254721Semaste                    // The typename passed in started with "::" so make sure we only do exact matches
211254721Semaste                    if (exact_ptr)
212254721Semaste                        *exact_ptr = true;
213254721Semaste                    // Strip the leading "::" as this won't ever show in qualified typenames we get
214254721Semaste                    // from clang.
215254721Semaste                    scope.erase(0,2);
216254721Semaste                }
217254721Semaste                basename.assign (basename_cstr);
218254721Semaste                return true;
219254721Semaste            }
220254721Semaste        }
221254721Semaste    }
222254721Semaste    return false;
223254721Semaste}
224254721Semaste
225254721Semastevoid
226254721SemasteTypeList::RemoveMismatchedTypes (const char *qualified_typename,
227254721Semaste                                 bool exact_match)
228254721Semaste{
229254721Semaste    std::string type_scope;
230254721Semaste    std::string type_basename;
231254721Semaste    TypeClass type_class = eTypeClassAny;
232254721Semaste    if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
233254721Semaste    {
234254721Semaste        type_basename = qualified_typename;
235254721Semaste        type_scope.clear();
236254721Semaste    }
237254721Semaste    return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
238254721Semaste}
239254721Semaste
240254721Semastevoid
241254721SemasteTypeList::RemoveMismatchedTypes (const std::string &type_scope,
242254721Semaste                                 const std::string &type_basename,
243254721Semaste                                 TypeClass type_class,
244254721Semaste                                 bool exact_match)
245254721Semaste{
246254721Semaste    // Our "collection" type currently is a std::map which doesn't
247254721Semaste    // have any good way to iterate and remove items from the map
248254721Semaste    // so we currently just make a new list and add all of the matching
249254721Semaste    // types to it, and then swap it into m_types at the end
250254721Semaste    collection matching_types;
251254721Semaste
252254721Semaste    iterator pos, end = m_types.end();
253254721Semaste
254254721Semaste    for (pos = m_types.begin(); pos != end; ++pos)
255254721Semaste    {
256254721Semaste        Type* the_type = pos->second.get();
257254721Semaste        bool keep_match = false;
258254721Semaste        TypeClass match_type_class = eTypeClassAny;
259254721Semaste
260254721Semaste        if (type_class != eTypeClassAny)
261254721Semaste        {
262254721Semaste            match_type_class = the_type->GetClangForwardType().GetTypeClass ();
263254721Semaste            if ((match_type_class & type_class) == 0)
264254721Semaste                continue;
265254721Semaste        }
266254721Semaste
267254721Semaste        ConstString match_type_name_const_str (the_type->GetQualifiedName());
268254721Semaste        if (match_type_name_const_str)
269254721Semaste        {
270254721Semaste            const char *match_type_name = match_type_name_const_str.GetCString();
271254721Semaste            std::string match_type_scope;
272254721Semaste            std::string match_type_basename;
273254721Semaste            if (Type::GetTypeScopeAndBasename (match_type_name,
274254721Semaste                                               match_type_scope,
275254721Semaste                                               match_type_basename,
276254721Semaste                                               match_type_class))
277254721Semaste            {
278254721Semaste                if (match_type_basename == type_basename)
279254721Semaste                {
280254721Semaste                    const size_t type_scope_size = type_scope.size();
281254721Semaste                    const size_t match_type_scope_size = match_type_scope.size();
282254721Semaste                    if (exact_match || (type_scope_size == match_type_scope_size))
283254721Semaste                    {
284254721Semaste                        keep_match = match_type_scope == type_scope;
285254721Semaste                    }
286254721Semaste                    else
287254721Semaste                    {
288254721Semaste                        if (match_type_scope_size > type_scope_size)
289254721Semaste                        {
290254721Semaste                            const size_t type_scope_pos = match_type_scope.rfind(type_scope);
291254721Semaste                            if (type_scope_pos == match_type_scope_size - type_scope_size)
292254721Semaste                            {
293254721Semaste                                if (type_scope_pos >= 2)
294254721Semaste                                {
295254721Semaste                                    // Our match scope ends with the type scope we were lookikng for,
296254721Semaste                                    // but we need to make sure what comes before the matching
297254721Semaste                                    // type scope is a namepace boundary in case we are trying to match:
298254721Semaste                                    // type_basename = "d"
299254721Semaste                                    // type_scope = "b::c::"
300254721Semaste                                    // We want to match:
301254721Semaste                                    //  match_type_scope "a::b::c::"
302254721Semaste                                    // But not:
303254721Semaste                                    //  match_type_scope "a::bb::c::"
304254721Semaste                                    // So below we make sure what comes before "b::c::" in match_type_scope
305254721Semaste                                    // is "::", or the namespace boundary
306254721Semaste                                    if (match_type_scope[type_scope_pos - 1] == ':' &&
307254721Semaste                                        match_type_scope[type_scope_pos - 2] == ':')
308254721Semaste                                    {
309254721Semaste                                        keep_match = true;
310254721Semaste                                    }
311254721Semaste                                }
312254721Semaste                            }
313254721Semaste                        }
314254721Semaste                    }
315254721Semaste                }
316254721Semaste            }
317254721Semaste            else
318254721Semaste            {
319254721Semaste                // The type we are currently looking at doesn't exists
320254721Semaste                // in a namespace or class, so it only matches if there
321254721Semaste                // is no type scope...
322254721Semaste                keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0;
323254721Semaste            }
324254721Semaste        }
325254721Semaste
326254721Semaste        if (keep_match)
327254721Semaste        {
328254721Semaste            matching_types.insert (*pos);
329254721Semaste        }
330254721Semaste    }
331254721Semaste    m_types.swap(matching_types);
332254721Semaste}
333254721Semaste
334254721Semastevoid
335254721SemasteTypeList::RemoveMismatchedTypes (TypeClass type_class)
336254721Semaste{
337254721Semaste    if (type_class == eTypeClassAny)
338254721Semaste        return;
339254721Semaste
340254721Semaste    // Our "collection" type currently is a std::map which doesn't
341254721Semaste    // have any good way to iterate and remove items from the map
342254721Semaste    // so we currently just make a new list and add all of the matching
343254721Semaste    // types to it, and then swap it into m_types at the end
344254721Semaste    collection matching_types;
345254721Semaste
346254721Semaste    iterator pos, end = m_types.end();
347254721Semaste
348254721Semaste    for (pos = m_types.begin(); pos != end; ++pos)
349254721Semaste    {
350254721Semaste        Type* the_type = pos->second.get();
351254721Semaste        TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
352254721Semaste        if (match_type_class & type_class)
353254721Semaste            matching_types.insert (*pos);
354254721Semaste    }
355254721Semaste    m_types.swap(matching_types);
356254721Semaste}
357