From 2fa8f02e7aea995e01af4eac20303db47315fea6 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Mon, 4 Aug 2025 14:03:10 +0200 Subject: [PATCH 1/2] [LLDB][NativePDB] Implement `FindNamespace` --- .../SymbolFile/NativePDB/PdbAstBuilder.cpp | 32 +++++++++++++++++- .../SymbolFile/NativePDB/PdbAstBuilder.h | 13 +++++++- .../NativePDB/SymbolFileNativePDB.cpp | 33 +++++++++++++++++-- .../NativePDB/namespace-access.test | 30 ++++++++++++++++- 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 8137622842253..92a102bbc92a8 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -644,9 +644,12 @@ clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const { clang::NamespaceDecl * PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name, clang::DeclContext &context) { - return m_clang.GetUniqueNamespaceDeclaration( + clang::NamespaceDecl *ns = m_clang.GetUniqueNamespaceDeclaration( IsAnonymousNamespaceName(name) ? nullptr : name, &context, OptionalClangModuleID()); + m_known_namespaces.insert(ns); + m_parent_to_namespaces[&context].insert(ns); + return ns; } clang::BlockDecl * @@ -1452,3 +1455,30 @@ PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) { void PdbAstBuilder::Dump(Stream &stream, llvm::StringRef filter) { m_clang.Dump(stream.AsRawOstream(), filter); } + +clang::NamespaceDecl * +PdbAstBuilder::FindNamespaceDecl(const clang::DeclContext *parent, + llvm::StringRef name) { + NamespaceSet *set; + if (parent) { + auto it = m_parent_to_namespaces.find(parent); + if (it == m_parent_to_namespaces.end()) + return nullptr; + + set = &it->second; + } else { + // In this case, search through all known namespaces + set = &m_known_namespaces; + } + assert(set); + + for (clang::NamespaceDecl *namespace_decl : *set) + if (namespace_decl->getName() == name) + return namespace_decl; + + for (clang::NamespaceDecl *namespace_decl : *set) + if (namespace_decl->isAnonymousNamespace()) + return FindNamespaceDecl(namespace_decl, name); + + return nullptr; +} diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index 66a3836fac053..fef65227bc8f5 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -89,6 +89,9 @@ class PdbAstBuilder { void Dump(Stream &stream, llvm::StringRef filter); + clang::NamespaceDecl *FindNamespaceDecl(const clang::DeclContext *parent, + llvm::StringRef name); + private: clang::Decl *TryGetDecl(PdbSymUid uid) const; @@ -150,7 +153,15 @@ class PdbAstBuilder { llvm::DenseMap, 8>> m_cxx_record_map; - llvm::DenseSet m_parsed_namespaces; + + using NamespaceSet = llvm::DenseSet; + + // These namespaces are fully parsed + NamespaceSet m_parsed_namespaces; + + // We know about these namespaces, but they might not be completely parsed yet + NamespaceSet m_known_namespaces; + llvm::DenseMap m_parent_to_namespaces; }; } // namespace npdb diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7af53e16ce9d5..0fe411e598545 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -2164,9 +2164,36 @@ void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, TypeClass type_mask, lldb_private::TypeList &type_list) {} -CompilerDeclContext SymbolFileNativePDB::FindNamespace( - ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) { - return {}; +CompilerDeclContext +SymbolFileNativePDB::FindNamespace(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + bool /* only_root_namespaces */) { + std::lock_guard guard(GetModuleMutex()); + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return {}; + auto ts = *ts_or_err; + if (!ts) + return {}; + auto *clang = llvm::dyn_cast_or_null(ts.get()); + if (!clang) + return {}; + + PdbAstBuilder *ast_builder = clang->GetNativePDBParser(); + if (!ast_builder) + return {}; + + clang::DeclContext *decl_context = nullptr; + if (parent_decl_ctx) + decl_context = static_cast( + parent_decl_ctx.GetOpaqueDeclContext()); + + auto *namespace_decl = + ast_builder->FindNamespaceDecl(decl_context, name.GetStringRef()); + if (!namespace_decl) + return CompilerDeclContext(); + + return clang->CreateDeclContext(namespace_decl); } llvm::Expected diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test index f6c1ccf22fa18..22ecfa16a11fb 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test +++ b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test @@ -77,8 +77,18 @@ type lookup Outer::Inner2::S type lookup Outer::A type lookup A type lookup ::A +# Test that Clang can find the namespaces as well expr sizeof(S) +expr sizeof(::S) +expr sizeof(Outer::S) +expr sizeof(Outer::Inner1::S) +expr sizeof(Inner1::S) +expr sizeof(Outer::Inner1::Inner2::S) +expr sizeof(Inner2::S) +expr sizeof(Outer::Inner2::S) +expr sizeof(Outer::A) expr sizeof(A) +expr sizeof(::A) quit @@ -131,5 +141,23 @@ quit # CHECK-NEXT: } # CHECK-NEXT: (lldb) expr sizeof(S) # CHECK-NEXT: (__size_t) $0 = 1 +# CHECK-NEXT: (lldb) expr sizeof(::S) +# CHECK-NEXT: (__size_t) $1 = 1 +# CHECK-NEXT: (lldb) expr sizeof(Outer::S) +# CHECK-NEXT: (__size_t) $2 = 2 +# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner1::S) +# CHECK-NEXT: (__size_t) $3 = 3 +# CHECK-NEXT: (lldb) expr sizeof(Inner1::S) +# CHECK-NEXT: (__size_t) $4 = 3 +# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner1::Inner2::S) +# CHECK-NEXT: (__size_t) $5 = 4 +# CHECK-NEXT: (lldb) expr sizeof(Inner2::S) +# CHECK-NEXT: (__size_t) $6 = 5 +# CHECK-NEXT: (lldb) expr sizeof(Outer::Inner2::S) +# CHECK-NEXT: (__size_t) $7 = 5 +# CHECK-NEXT: (lldb) expr sizeof(Outer::A) +# CHECK-NEXT: (__size_t) $8 = 6 # CHECK-NEXT: (lldb) expr sizeof(A) -# CHECK-NEXT: (__size_t) $1 = 7 +# CHECK-NEXT: (__size_t) $9 = 7 +# CHECK-NEXT: (lldb) expr sizeof(::A) +# CHECK-NEXT: (__size_t) $10 = 7 From 0d46cbb054510437a7217e795cca470cf8f99e78 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Mon, 4 Aug 2025 18:40:15 +0200 Subject: [PATCH 2/2] fix: remove flakey sizeof check --- .../Shell/SymbolFile/NativePDB/namespace-access.test | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test index 22ecfa16a11fb..197ac234dea75 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test +++ b/lldb/test/Shell/SymbolFile/NativePDB/namespace-access.test @@ -84,7 +84,6 @@ expr sizeof(Outer::S) expr sizeof(Outer::Inner1::S) expr sizeof(Inner1::S) expr sizeof(Outer::Inner1::Inner2::S) -expr sizeof(Inner2::S) expr sizeof(Outer::Inner2::S) expr sizeof(Outer::A) expr sizeof(A) @@ -151,13 +150,11 @@ quit # CHECK-NEXT: (__size_t) $4 = 3 # CHECK-NEXT: (lldb) expr sizeof(Outer::Inner1::Inner2::S) # CHECK-NEXT: (__size_t) $5 = 4 -# CHECK-NEXT: (lldb) expr sizeof(Inner2::S) -# CHECK-NEXT: (__size_t) $6 = 5 # CHECK-NEXT: (lldb) expr sizeof(Outer::Inner2::S) -# CHECK-NEXT: (__size_t) $7 = 5 +# CHECK-NEXT: (__size_t) $6 = 5 # CHECK-NEXT: (lldb) expr sizeof(Outer::A) -# CHECK-NEXT: (__size_t) $8 = 6 +# CHECK-NEXT: (__size_t) $7 = 6 # CHECK-NEXT: (lldb) expr sizeof(A) -# CHECK-NEXT: (__size_t) $9 = 7 +# CHECK-NEXT: (__size_t) $8 = 7 # CHECK-NEXT: (lldb) expr sizeof(::A) -# CHECK-NEXT: (__size_t) $10 = 7 +# CHECK-NEXT: (__size_t) $9 = 7