https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/149876
>From fa3c96b19ba174904036b031015a073cfd759c76 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 21 Jul 2025 20:32:58 +0200 Subject: [PATCH 1/4] [LLDB][NativePDB] Allow type lookup in namespaces --- .../NativePDB/SymbolFileNativePDB.cpp | 58 ++++++++- .../NativePDB/SymbolFileNativePDB.h | 4 + lldb/source/Symbol/Type.cpp | 8 +- .../Inputs/namespace-access.lldbinit | 18 +++ .../SymbolFile/NativePDB/namespace-access.cpp | 114 ++++++++++++++++++ 5 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 20d8c1acf9c42..5141632649dd5 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1630,6 +1630,53 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope( return count; } +void SymbolFileNativePDB::CacheTypeNames() { + if (!m_type_base_names.IsEmpty()) + return; + + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { + CVType cvt = types.getType(*ti); + llvm::StringRef name; + // We are only interested in records, unions, and enums. + // We aren't interested in forward references as we'll visit the actual + // type later anyway. + switch (cvt.kind()) { + case LF_STRUCTURE: + case LF_CLASS: { + ClassRecord cr; + llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); + if (cr.isForwardRef()) + continue; + name = cr.Name; + } break; + case LF_UNION: { + UnionRecord ur; + llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); + if (ur.isForwardRef()) + continue; + name = ur.Name; + } break; + case LF_ENUM: { + EnumRecord er; + llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); + if (er.isForwardRef()) + continue; + name = er.Name; + } break; + default: + continue; + } + if (name.empty()) + continue; + + auto base_name = MSVCUndecoratedNameParser::DropScope(name); + m_type_base_names.Append(ConstString(base_name), ti->getIndex()); + } + + m_type_base_names.Sort(); +} + void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) @@ -1720,11 +1767,14 @@ void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - std::vector<TypeIndex> matches = - m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef()); + // We can't query for the basename or full name because the type might reside + // in an anonymous namespace. Cache the basenames first. + CacheTypeNames(); + std::vector<uint32_t> matches; + m_type_base_names.GetValues(query.GetTypeBasename(), matches); - for (TypeIndex type_idx : matches) { - TypeSP type_sp = GetOrCreateType(type_idx); + for (uint32_t match_idx : matches) { + TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx)); if (!type_sp) continue; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 9891313f11d0b..457b301c4a486 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -258,6 +258,8 @@ class SymbolFileNativePDB : public SymbolFileCommon { void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); + void CacheTypeNames(); + llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; @@ -278,6 +280,8 @@ class SymbolFileNativePDB : public SymbolFileCommon { llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites; llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex> m_parent_types; + + lldb_private::UniqueCStringMap<uint32_t> m_type_base_names; }; } // namespace npdb diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 0a886e56100a1..ddb22d611140b 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -134,7 +134,9 @@ bool TypeQuery::ContextMatches( if (ctx == ctx_end) return false; // Pattern too long. - if (ctx->kind == CompilerContextKind::Namespace && ctx->name.IsEmpty()) { + if ((ctx->kind & CompilerContextKind::Namespace) == + CompilerContextKind::Namespace && + ctx->name.IsEmpty()) { // We're matching an anonymous namespace. These are optional, so we check // if the pattern expects an anonymous namespace. if (pat->name.IsEmpty() && (pat->kind & CompilerContextKind::Namespace) == @@ -164,7 +166,9 @@ bool TypeQuery::ContextMatches( auto should_skip = [this](const CompilerContext &ctx) { if (ctx.kind == CompilerContextKind::Module) return GetIgnoreModules(); - if (ctx.kind == CompilerContextKind::Namespace && ctx.name.IsEmpty()) + if ((ctx.kind & CompilerContextKind::Namespace) == + CompilerContextKind::Namespace && + ctx.name.IsEmpty()) return !GetStrictNamespaces(); return false; }; diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit new file mode 100644 index 0000000000000..e61ed2e2f453e --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit @@ -0,0 +1,18 @@ +b main +r + +type lookup S +type lookup ::S +type lookup Outer::S +type lookup Outer::Inner1::S +type lookup Inner1::S +type lookup Outer::Inner1::Inner2::S +type lookup Inner2::S +type lookup Outer::Inner2::S +type lookup Outer::A +type lookup A +type lookup ::A +expr sizeof(S) +expr sizeof(A) + +quit diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp new file mode 100644 index 0000000000000..e171d189347d9 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp @@ -0,0 +1,114 @@ +// clang-format off +// REQUIRES: target-windows + +// Test namespace lookup. +// RUN: %build --nodefaultlib -o %t.exe -- %s +// RUN: %lldb -f %t.exe -s \ +// RUN: %p/Inputs/namespace-access.lldbinit 2>&1 | FileCheck %s + +struct S { + char a[1]; +}; + +namespace Outer { + + struct S { + char a[2]; + }; + + namespace Inner1 { + struct S { + char a[3]; + }; + + namespace Inner2 { + struct S { + char a[4]; + }; + } // namespace Inner2 + } // namespace Inner1 + + namespace Inner2 { + struct S { + char a[5]; + }; + } // namespace Inner2 + + namespace { + struct A { + char a[6]; + }; + } // namespace + +} // namespace Outer + +namespace { + struct A { + char a[7]; + }; +} // namespace + +int main(int argc, char **argv) { + S s; + Outer::S os; + Outer::Inner1::S oi1s; + Outer::Inner1::Inner2::S oi1i2s; + Outer::Inner2::S oi2s; + A a1; + Outer::A a2; + return sizeof(s) + sizeof(os) + sizeof(oi1s) + sizeof(oi1i2s) + sizeof(oi2s) + sizeof(a1) + sizeof(a2); +} + + + +// CHECK: (lldb) type lookup S +// CHECK: struct S { +// CHECK: struct S { +// CHECK: struct S { +// CHECK: struct S { +// CHECK: struct S { +// CHECK: } +// CHECK-NEXT: (lldb) type lookup ::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[1]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Outer::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[2]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Outer::Inner1::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[3]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Inner1::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[3]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Outer::Inner1::Inner2::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[4]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Inner2::S +// CHECK-NEXT: struct S { +// CHECK: struct S { +// CHECK: } +// CHECK-NEXT: (lldb) type lookup Outer::Inner2::S +// CHECK-NEXT: struct S { +// CHECK-NEXT: char a[5]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup Outer::A +// CHECK-NEXT: struct A { +// CHECK-NEXT: char a[6]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) type lookup A +// CHECK-NEXT: struct A { +// CHECK: struct A { +// CHECK: } +// CHECK-NEXT: (lldb) type lookup ::A +// CHECK-NEXT: struct A { +// CHECK-NEXT: char a[7]; +// CHECK-NEXT: } +// CHECK-NEXT: (lldb) expr sizeof(S) +// CHECK-NEXT: (__size_t) $0 = 1 +// CHECK-NEXT: (lldb) expr sizeof(A) +// CHECK-NEXT: (__size_t) $1 = 7 >From 288b5f7ddbca800509434f945495d972252f43a5 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Tue, 22 Jul 2025 14:35:34 +0200 Subject: [PATCH 2/4] refactor: move basename discovery to `BuildParentMap` --- .../NativePDB/SymbolFileNativePDB.cpp | 61 +++---------------- .../NativePDB/SymbolFileNativePDB.h | 2 - 2 files changed, 10 insertions(+), 53 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 5141632649dd5..cae4c510a0e5f 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1630,53 +1630,6 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope( return count; } -void SymbolFileNativePDB::CacheTypeNames() { - if (!m_type_base_names.IsEmpty()) - return; - - LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); - for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { - CVType cvt = types.getType(*ti); - llvm::StringRef name; - // We are only interested in records, unions, and enums. - // We aren't interested in forward references as we'll visit the actual - // type later anyway. - switch (cvt.kind()) { - case LF_STRUCTURE: - case LF_CLASS: { - ClassRecord cr; - llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); - if (cr.isForwardRef()) - continue; - name = cr.Name; - } break; - case LF_UNION: { - UnionRecord ur; - llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); - if (ur.isForwardRef()) - continue; - name = ur.Name; - } break; - case LF_ENUM: { - EnumRecord er; - llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); - if (er.isForwardRef()) - continue; - name = er.Name; - } break; - default: - continue; - } - if (name.empty()) - continue; - - auto base_name = MSVCUndecoratedNameParser::DropScope(name); - m_type_base_names.Append(ConstString(base_name), ti->getIndex()); - } - - m_type_base_names.Sort(); -} - void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) @@ -1767,9 +1720,9 @@ void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // We can't query for the basename or full name because the type might reside - // in an anonymous namespace. Cache the basenames first. - CacheTypeNames(); + // We can't query for the full name because the type might reside + // in an anonymous namespace. Search for the basename in our map and check the + // matching types afterwards. std::vector<uint32_t> matches; m_type_base_names.GetValues(query.GetTypeBasename(), matches); @@ -2253,9 +2206,13 @@ void SymbolFileNativePDB::BuildParentMap() { RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; if (tag.asTag().isForwardRef()) indices.forward = *ti; - else + else { indices.full = *ti; + auto base_name = MSVCUndecoratedNameParser::DropScope(tag.name()); + m_type_base_names.Append(ConstString(base_name), ti->getIndex()); + } + if (indices.full != TypeIndex::None() && indices.forward != TypeIndex::None()) { forward_to_full[indices.forward] = indices.full; @@ -2341,6 +2298,8 @@ void SymbolFileNativePDB::BuildParentMap() { TypeIndex fwd = full_to_forward[full]; m_parent_types[fwd] = m_parent_types[full]; } + + m_type_base_names.Sort(); } std::optional<PdbCompilandSymId> diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 457b301c4a486..02e56484d7525 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -258,8 +258,6 @@ class SymbolFileNativePDB : public SymbolFileCommon { void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); - void CacheTypeNames(); - llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; >From 1dbde101df5aa51cc31f789da2545a75a3cf4475 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 28 Jul 2025 12:19:38 +0200 Subject: [PATCH 3/4] refactor: convert test to use split-file --- .../Inputs/namespace-access.lldbinit | 18 --- .../SymbolFile/NativePDB/namespace-access.cpp | 114 --------------- .../NativePDB/namespace-access.test | 135 ++++++++++++++++++ 3 files changed, 135 insertions(+), 132 deletions(-) delete mode 100644 lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit delete mode 100644 lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit deleted file mode 100644 index e61ed2e2f453e..0000000000000 --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/namespace-access.lldbinit +++ /dev/null @@ -1,18 +0,0 @@ -b main -r - -type lookup S -type lookup ::S -type lookup Outer::S -type lookup Outer::Inner1::S -type lookup Inner1::S -type lookup Outer::Inner1::Inner2::S -type lookup Inner2::S -type lookup Outer::Inner2::S -type lookup Outer::A -type lookup A -type lookup ::A -expr sizeof(S) -expr sizeof(A) - -quit diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp deleted file mode 100644 index e171d189347d9..0000000000000 --- a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// clang-format off -// REQUIRES: target-windows - -// Test namespace lookup. -// RUN: %build --nodefaultlib -o %t.exe -- %s -// RUN: %lldb -f %t.exe -s \ -// RUN: %p/Inputs/namespace-access.lldbinit 2>&1 | FileCheck %s - -struct S { - char a[1]; -}; - -namespace Outer { - - struct S { - char a[2]; - }; - - namespace Inner1 { - struct S { - char a[3]; - }; - - namespace Inner2 { - struct S { - char a[4]; - }; - } // namespace Inner2 - } // namespace Inner1 - - namespace Inner2 { - struct S { - char a[5]; - }; - } // namespace Inner2 - - namespace { - struct A { - char a[6]; - }; - } // namespace - -} // namespace Outer - -namespace { - struct A { - char a[7]; - }; -} // namespace - -int main(int argc, char **argv) { - S s; - Outer::S os; - Outer::Inner1::S oi1s; - Outer::Inner1::Inner2::S oi1i2s; - Outer::Inner2::S oi2s; - A a1; - Outer::A a2; - return sizeof(s) + sizeof(os) + sizeof(oi1s) + sizeof(oi1i2s) + sizeof(oi2s) + sizeof(a1) + sizeof(a2); -} - - - -// CHECK: (lldb) type lookup S -// CHECK: struct S { -// CHECK: struct S { -// CHECK: struct S { -// CHECK: struct S { -// CHECK: struct S { -// CHECK: } -// CHECK-NEXT: (lldb) type lookup ::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[1]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Outer::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[2]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Outer::Inner1::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[3]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Inner1::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[3]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Outer::Inner1::Inner2::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[4]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Inner2::S -// CHECK-NEXT: struct S { -// CHECK: struct S { -// CHECK: } -// CHECK-NEXT: (lldb) type lookup Outer::Inner2::S -// CHECK-NEXT: struct S { -// CHECK-NEXT: char a[5]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup Outer::A -// CHECK-NEXT: struct A { -// CHECK-NEXT: char a[6]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) type lookup A -// CHECK-NEXT: struct A { -// CHECK: struct A { -// CHECK: } -// CHECK-NEXT: (lldb) type lookup ::A -// CHECK-NEXT: struct A { -// CHECK-NEXT: char a[7]; -// CHECK-NEXT: } -// CHECK-NEXT: (lldb) expr sizeof(S) -// CHECK-NEXT: (__size_t) $0 = 1 -// CHECK-NEXT: (lldb) expr sizeof(A) -// CHECK-NEXT: (__size_t) $1 = 7 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test new file mode 100644 index 0000000000000..f6c1ccf22fa18 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test @@ -0,0 +1,135 @@ +# REQUIRES: target-windows + +# Test namespace lookup. +# RUN: split-file %s %t +# RUN: %build --nodefaultlib -o %t.exe -- %t/main.cpp +# RUN: %lldb -f %t.exe -s \ +# RUN: %t/commands.input 2>&1 | FileCheck %s + +#--- main.cpp + +struct S { + char a[1]; +}; + +namespace Outer { + + struct S { + char a[2]; + }; + + namespace Inner1 { + struct S { + char a[3]; + }; + + namespace Inner2 { + struct S { + char a[4]; + }; + } // namespace Inner2 + } // namespace Inner1 + + namespace Inner2 { + struct S { + char a[5]; + }; + } // namespace Inner2 + + namespace { + struct A { + char a[6]; + }; + } // namespace + +} // namespace Outer + +namespace { + struct A { + char a[7]; + }; +} // namespace + +int main(int argc, char **argv) { + S s; + Outer::S os; + Outer::Inner1::S oi1s; + Outer::Inner1::Inner2::S oi1i2s; + Outer::Inner2::S oi2s; + A a1; + Outer::A a2; + return sizeof(s) + sizeof(os) + sizeof(oi1s) + sizeof(oi1i2s) + sizeof(oi2s) + sizeof(a1) + sizeof(a2); +} + +#--- commands.input + +b main +r + +type lookup S +type lookup ::S +type lookup Outer::S +type lookup Outer::Inner1::S +type lookup Inner1::S +type lookup Outer::Inner1::Inner2::S +type lookup Inner2::S +type lookup Outer::Inner2::S +type lookup Outer::A +type lookup A +type lookup ::A +expr sizeof(S) +expr sizeof(A) + +quit + +# CHECK: (lldb) type lookup S +# CHECK: struct S { +# CHECK: struct S { +# CHECK: struct S { +# CHECK: struct S { +# CHECK: struct S { +# CHECK: } +# CHECK-NEXT: (lldb) type lookup ::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[1]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Outer::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[2]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Outer::Inner1::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[3]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Inner1::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[3]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Outer::Inner1::Inner2::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[4]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Inner2::S +# CHECK-NEXT: struct S { +# CHECK: struct S { +# CHECK: } +# CHECK-NEXT: (lldb) type lookup Outer::Inner2::S +# CHECK-NEXT: struct S { +# CHECK-NEXT: char a[5]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup Outer::A +# CHECK-NEXT: struct A { +# CHECK-NEXT: char a[6]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) type lookup A +# CHECK-NEXT: struct A { +# CHECK: struct A { +# CHECK: } +# CHECK-NEXT: (lldb) type lookup ::A +# CHECK-NEXT: struct A { +# CHECK-NEXT: char a[7]; +# CHECK-NEXT: } +# CHECK-NEXT: (lldb) expr sizeof(S) +# CHECK-NEXT: (__size_t) $0 = 1 +# CHECK-NEXT: (lldb) expr sizeof(A) +# CHECK-NEXT: (__size_t) $1 = 7 >From 8344a98e1302081e2c71475e914b3d041d80f175 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 28 Jul 2025 12:19:55 +0200 Subject: [PATCH 4/4] refactor: create context in symbol file plugin --- .../Plugins/SymbolFile/NativePDB/PdbUtil.h | 8 +++ .../NativePDB/SymbolFileNativePDB.cpp | 62 +++++++++++++++++-- .../NativePDB/SymbolFileNativePDB.h | 2 + lldb/source/Symbol/Type.cpp | 14 ++--- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 1f888f4de1fed..505224c207fc9 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -72,6 +72,14 @@ struct CVTagRecord { return cvunion.Name; } + CompilerContextKind contextKind() const { + if (m_kind == Struct || m_kind == Class) + return CompilerContextKind::ClassOrStruct; + if (m_kind == Enum) + return CompilerContextKind::Enum; + return CompilerContextKind::Union; + } + private: CVTagRecord(llvm::codeview::ClassRecord &&c); CVTagRecord(llvm::codeview::UnionRecord &&u); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index cae4c510a0e5f..71cfb4b360f62 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1727,14 +1727,15 @@ void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, m_type_base_names.GetValues(query.GetTypeBasename(), matches); for (uint32_t match_idx : matches) { - TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx)); - if (!type_sp) + std::vector context = GetContextForType(TypeIndex(match_idx)); + if (context.empty()) continue; - // We resolved a type. Get the fully qualified name to ensure it matches. - ConstString name = type_sp->GetQualifiedName(); - TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); - if (query.ContextMatches(type_match.GetContextRef())) { + if (query.ContextMatches(context)) { + TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx)); + if (!type_sp) + continue; + results.InsertUnique(type_sp); if (results.Done(query)) return; @@ -2362,3 +2363,52 @@ SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) { return std::nullopt; return parent_iter->second; } + +std::vector<CompilerContext> +SymbolFileNativePDB::GetContextForType(TypeIndex ti) { + CVType type = m_index->tpi().getType(ti); + if (!IsTagRecord(type)) + return {}; + + CVTagRecord tag = CVTagRecord::create(type); + + std::optional<Type::ParsedName> parsed_name = + Type::GetTypeScopeAndBasename(tag.name()); + if (!parsed_name) + return {{tag.contextKind(), ConstString(tag.name())}}; + + std::vector<CompilerContext> ctx; + // assume everything is a namespace at first + for (llvm::StringRef scope : parsed_name->scope) { + ctx.emplace_back(CompilerContextKind::Namespace, ConstString(scope)); + } + // we know the kind of our own type + ctx.emplace_back(tag.contextKind(), ConstString(parsed_name->basename)); + + // try to find the kind of parents + for (auto &el : llvm::reverse(llvm::drop_end(ctx))) { + std::optional<TypeIndex> parent = GetParentType(ti); + if (!parent) + break; + + ti = *parent; + type = m_index->tpi().getType(ti); + switch (type.kind()) { + case LF_CLASS: + case LF_STRUCTURE: + case LF_INTERFACE: + el.kind = CompilerContextKind::ClassOrStruct; + continue; + case LF_UNION: + el.kind = CompilerContextKind::Union; + continue; + case LF_ENUM: + el.kind = CompilerContextKind::Enum; + continue; + default: + break; + } + break; + } + return ctx; +} diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 02e56484d7525..eda375d4cebe7 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -258,6 +258,8 @@ class SymbolFileNativePDB : public SymbolFileCommon { void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); + std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti); + llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index ddb22d611140b..c20dd87aeb3b5 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -134,9 +134,7 @@ bool TypeQuery::ContextMatches( if (ctx == ctx_end) return false; // Pattern too long. - if ((ctx->kind & CompilerContextKind::Namespace) == - CompilerContextKind::Namespace && - ctx->name.IsEmpty()) { + if (ctx->kind == CompilerContextKind::Namespace && ctx->name.IsEmpty()) { // We're matching an anonymous namespace. These are optional, so we check // if the pattern expects an anonymous namespace. if (pat->name.IsEmpty() && (pat->kind & CompilerContextKind::Namespace) == @@ -166,9 +164,7 @@ bool TypeQuery::ContextMatches( auto should_skip = [this](const CompilerContext &ctx) { if (ctx.kind == CompilerContextKind::Module) return GetIgnoreModules(); - if ((ctx.kind & CompilerContextKind::Namespace) == - CompilerContextKind::Namespace && - ctx.name.IsEmpty()) + if (ctx.kind == CompilerContextKind::Namespace && ctx.name.IsEmpty()) return !GetStrictNamespaces(); return false; }; @@ -820,10 +816,12 @@ Type::GetTypeScopeAndBasename(llvm::StringRef name) { case ':': if (prev_is_colon && template_depth == 0) { llvm::StringRef scope_name = name.slice(name_begin, pos.index() - 1); - // The itanium demangler uses this string to represent anonymous + // The demanglers use these strings to represent anonymous // namespaces. Convert it to a more language-agnostic form (which is // also used in DWARF). - if (scope_name == "(anonymous namespace)") + if (scope_name == "(anonymous namespace)" || + scope_name == "`anonymous namespace'" || + scope_name == "`anonymous-namespace'") scope_name = ""; result.scope.push_back(scope_name); name_begin = pos.index() + 1; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits