diff --git a/lldb/include/lldb/Symbol/TypeList.h b/lldb/include/lldb/Symbol/TypeList.h --- a/lldb/include/lldb/Symbol/TypeList.h +++ b/lldb/include/lldb/Symbol/TypeList.h @@ -42,7 +42,7 @@ typedef AdaptedIterable TypeIterable; - TypeIterable Types() { return TypeIterable(m_types); } + TypeIterable Types() { return TypeIterable(m_types.Types()); } void ForEach( std::function const &callback) const; @@ -61,7 +61,23 @@ typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; - collection m_types; + class TypeCollection { + typedef std::set setCollection; + collection m_types; + setCollection m_type_set; + + public: + const collection &Types() const { return m_types; }; + collection &Types() { return m_types; }; + iterator Begin() { return m_types.begin(); }; + iterator End() { return m_types.end(); }; + const_iterator Begin() const { return m_types.cbegin(); }; + const_iterator End() const { return m_types.cend(); }; + iterator Erase(iterator iter); + void Insert(const lldb::TypeSP &type); + void Clear(); + }; + TypeCollection m_types; TypeList(const TypeList &) = delete; const TypeList &operator=(const TypeList &) = delete; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1530,7 +1530,6 @@ return type_sp; SymbolFileDWARF *dwarf = die.GetDWARF(); - TypeList &type_list = dwarf->GetTypeList(); DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); dw_tag_t sc_parent_tag = sc_parent_die.Tag(); @@ -1550,10 +1549,6 @@ if (symbol_context_scope != nullptr) type_sp->SetSymbolContextScope(symbol_context_scope); - // We are ready to put this type into the uniqued list up at the module - // level. - type_list.Insert(type_sp); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); return type_sp; } diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -217,7 +217,7 @@ void SymbolFile::Dump(Stream &s) { s.Format("SymbolFile {0} ({1})\n", GetPluginName(), GetMainObjectFile()->GetFileSpec()); - s.PutCString("Types:\n"); + s.Format("Found {0} types:\n", m_type_list.GetSize()); m_type_list.Dump(&s, /*show_context*/ false); s.PutChar('\n'); diff --git a/lldb/source/Symbol/TypeList.cpp b/lldb/source/Symbol/TypeList.cpp --- a/lldb/source/Symbol/TypeList.cpp +++ b/lldb/source/Symbol/TypeList.cpp @@ -24,12 +24,7 @@ // Destructor TypeList::~TypeList() = default; -void TypeList::Insert(const TypeSP &type_sp) { - // Just push each type on the back for now. We will worry about uniquing - // later - if (type_sp) - m_types.push_back(type_sp); -} +void TypeList::Insert(const TypeSP &type_sp) { m_types.Insert(type_sp); } // Find a base type by its unique ID. // TypeSP @@ -55,9 +50,9 @@ // return types; //} -void TypeList::Clear() { m_types.clear(); } +void TypeList::Clear() { m_types.Clear(); } -uint32_t TypeList::GetSize() const { return m_types.size(); } +uint32_t TypeList::GetSize() const { return m_types.Types().size(); } // GetTypeAtIndex isn't used a lot for large type lists, currently only for // type lists that are returned for "image dump -t TYPENAME" commands and other @@ -67,7 +62,7 @@ iterator pos, end; uint32_t i = idx; assert(i < GetSize() && "Accessing past the end of a TypeList"); - for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + for (pos = m_types.Begin(), end = m_types.End(); pos != end; ++pos) { if (i == 0) return *pos; --i; @@ -77,7 +72,7 @@ void TypeList::ForEach( std::function const &callback) const { - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + for (auto pos = m_types.Begin(), end = m_types.End(); pos != end; ++pos) { if (!callback(*pos)) break; } @@ -85,14 +80,14 @@ void TypeList::ForEach( std::function const &callback) { - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + for (auto pos = m_types.Begin(), end = m_types.End(); pos != end; ++pos) { if (!callback(*pos)) break; } } void TypeList::Dump(Stream *s, bool show_context) { - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + for (iterator pos = m_types.Begin(), end = m_types.End(); pos != end; ++pos) { pos->get()->Dump(s, show_context); } } @@ -115,15 +110,9 @@ void TypeList::RemoveMismatchedTypes(const std::string &type_scope, const std::string &type_basename, TypeClass type_class, bool exact_match) { - // Our "collection" type currently is a std::map which doesn't have any good - // way to iterate and remove items from the map so we currently just make a - // new list and add all of the matching types to it, and then swap it into - // m_types at the end - collection matching_types; - - iterator pos, end = m_types.end(); + iterator pos, end = m_types.End(); - for (pos = m_types.begin(); pos != end; ++pos) { + for (pos = m_types.Begin(); pos != end;) { Type *the_type = pos->get(); bool keep_match = false; TypeClass match_type_class = eTypeClassAny; @@ -178,31 +167,43 @@ } } - if (keep_match) { - matching_types.push_back(*pos); - } + if (keep_match) + ++pos; + else + pos = m_types.Erase(pos); } - m_types.swap(matching_types); } void TypeList::RemoveMismatchedTypes(TypeClass type_class) { if (type_class == eTypeClassAny) return; - // Our "collection" type currently is a std::map which doesn't have any good - // way to iterate and remove items from the map so we currently just make a - // new list and add all of the matching types to it, and then swap it into - // m_types at the end - collection matching_types; + iterator pos, end = m_types.End(); - iterator pos, end = m_types.end(); - - for (pos = m_types.begin(); pos != end; ++pos) { + for (pos = m_types.Begin(); pos != end;) { Type *the_type = pos->get(); TypeClass match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); if (match_type_class & type_class) - matching_types.push_back(*pos); + ++pos; + else + pos = m_types.Erase(pos); } - m_types.swap(matching_types); +} + +void TypeList::TypeCollection::Clear() { + m_types.clear(); + m_type_set.clear(); +} + +void TypeList::TypeCollection::Insert(const lldb::TypeSP &type) { + if (type && m_type_set.count(type.get()) == 0) { + m_types.push_back(type); + m_type_set.insert(type.get()); + } +} + +TypeList::iterator TypeList::TypeCollection::Erase(iterator iter) { + m_type_set.erase(iter->get()); + return m_types.erase(iter); } diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-line-tables.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-line-tables.s --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-line-tables.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-line-tables.s @@ -5,7 +5,7 @@ .section .debug_types,"",@progbits -# CHECK: Types: +# CHECK: Found 5 types: # Type unit one: "struct A" defined at b.cc:1 # CHECK-DAG: name = "A", size = 4, decl = b.cc:1 1: diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dump-types.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/dump-types.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dump-types.cpp @@ -0,0 +1,47 @@ +// REQUIRES: lld + +// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -gno-pubnames +// RUN: ld.lld %t.o -o %t +// RUN: lldb-test symbols --find=none %t | FileCheck %s + +// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx +// RUN: lldb-test symbols --find=none %t | FileCheck %s + +// RUN: %clang %s -c -o %t.o --target=x86_64-pc-linux -gdwarf-5 -gpubnames +// RUN: ld.lld %t.o -o %t +// RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix NAMES +// RUN: lldb-test symbols --find=none %t | FileCheck %s + +// NAMES: Name: .debug_names + +struct foo {}; + +namespace bar { +int context; +struct foo {}; + +namespace baz { +struct foo {}; + +} // namespace baz +} // namespace bar + +struct sbar { + struct foo {}; +}; + +struct foobar {}; + +struct Foo {}; + +extern "C" void _start(foo, bar::foo, bar::baz::foo, sbar::foo, foobar, Foo) {} + +// CHECK: Found 8 types: +// CHECK-DAG: name = "foo", size = 1, decl = dump-types.cpp:17 +// CHECK-DAG: name = "foo", size = 1, decl = dump-types.cpp:21 +// CHECK-DAG: name = "foo", size = 1, decl = dump-types.cpp:24 +// CHECK-DAG: name = "sbar", size = 1, decl = dump-types.cpp:29 +// CHECK-DAG: name = "foo", size = 1, decl = dump-types.cpp:30 +// CHECK-DAG: name = "foobar", size = 1, decl = dump-types.cpp:33 +// CHECK-DAG: name = "Foo", size = 1, decl = dump-types.cpp:35 +// CHECK-DAG: name = "int", size = 4 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp b/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp --- a/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp @@ -24,7 +24,7 @@ // CHECK: (lldb) b main // CHECK: Breakpoint 1: where = foo.exe`main + 21 at load-pdb.cpp:19, address = 0x0000000140001015 // CHECK: (lldb) image dump symfile -// CHECK: Types: +// CHECK: Found 1 types: // CHECK: {{.*}}: Type{0x00010024} , size = 0, compiler_type = {{.*}} int (int, char **) // CHECK: Compile units: // CHECK: {{.*}}: CompileUnit{0x00000000}, language = "c++", file = '{{.*}}load-pdb.cpp'