[Lldb-commits] [lldb] [lldb][NativePDB] Find namespaces that only contain typedefs (PR #233460)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Fri Oct 30 12:02:08 PDT 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/233460
>From 04cf7dc3d65036223aa9c5e520d9bc9c60a592b0 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Mon, 19 Oct 2026 17:20:03 +0200
Subject: [PATCH 1/3] [lldb][NativePDB] Find namespaces that only contain
typedefs
---
.../NativePDB/SymbolFileNativePDB.cpp | 25 +++++++++++
.../NativePDB/SymbolFileNativePDB.h | 3 ++
.../SymbolFile/NativePDB/typedef-lookup.test | 44 +++++++++++++++++++
3 files changed, 72 insertions(+)
create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 816d06dd346aa3..146b1978b36bd9 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -2927,6 +2927,20 @@ SymbolFileNativePDB::FindNamespace(ConstString name,
if (!ast_builder)
return {};
+ if (CompilerDeclContext ns =
+ ast_builder->FindNamespaceDecl(parent_decl_ctx, name.GetStringRef()))
+ return ns;
+
+ // The AST builder only knows the namespaces of the decls it created so far.
+ BuildParentMap();
+ std::string qualified_name;
+ if (parent_decl_ctx.IsValid())
+ qualified_name = parent_decl_ctx.GetScopeQualifiedName().GetString() + "::";
+ qualified_name += name.GetStringRef();
+ auto it = m_typedef_scopes.find(qualified_name);
+ if (it == m_typedef_scopes.end())
+ return {};
+ GetOrCreateTypedef(PdbGlobalSymId{it->second, false});
return ast_builder->FindNamespaceDecl(parent_decl_ctx, name.GetStringRef());
}
@@ -3055,6 +3069,17 @@ void SymbolFileNativePDB::BuildParentMap() {
llvm::StringRef base_name =
MSVCUndecoratedNameParser::DropScope(udt_or_err->Name);
m_typedef_base_names.Append(ConstString(base_name), gid);
+
+ if (std::optional<Type::ParsedName> parsed_name =
+ Type::GetTypeScopeAndBasename(udt_or_err->Name)) {
+ std::string scope_name;
+ for (llvm::StringRef scope : parsed_name->scope) {
+ if (!scope_name.empty())
+ scope_name += "::";
+ scope_name += scope;
+ m_typedef_scopes.try_emplace(scope_name, gid);
+ }
+ }
}
m_typedef_base_names.Sort(std::less<uint32_t>());
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index edd08e8407ee98..7d2308db073376 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -13,6 +13,7 @@
#include "lldb/Symbol/SymbolFile.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
@@ -358,6 +359,8 @@ class SymbolFileNativePDB : public SymbolFileCommon {
lldb_private::UniqueCStringMap<uint32_t> m_type_base_names;
/// typedef basename -> Global ID(s) of its S_UDT
lldb_private::UniqueCStringMap<uint32_t> m_typedef_base_names;
+ /// Qualified name of a scope of a typedef -> Global ID of a typedef in it.
+ llvm::StringMap<uint32_t> m_typedef_scopes;
/// mangled name/full function name -> Global ID(s)
lldb_private::UniqueCStringMap<uint32_t> m_func_full_names;
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test b/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
new file mode 100644
index 00000000000000..5c9f79352807a8
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
@@ -0,0 +1,44 @@
+# REQUIRES: target-windows
+
+# Test that typedefs are found by name. They are only S_UDT records, not type
+# records, and "ns" isn't the scope of anything but a typedef. Evaluate the
+# expressions first, since looking up the type also creates the namespace.
+# 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[3];
+};
+
+typedef S GlobalTypedef;
+
+namespace ns {
+typedef S NamespaceTypedef;
+} // namespace ns
+
+int main() {
+ GlobalTypedef g;
+ ns::NamespaceTypedef n;
+ return sizeof(g) + sizeof(n);
+}
+
+#--- commands.input
+
+expr sizeof(ns::NamespaceTypedef)
+expr sizeof(GlobalTypedef)
+type lookup ns::NamespaceTypedef
+type lookup GlobalTypedef
+quit
+
+# CHECK: (lldb) expr sizeof(ns::NamespaceTypedef)
+# CHECK-NEXT: ({{.*}}) $0 = 3
+# CHECK: (lldb) expr sizeof(GlobalTypedef)
+# CHECK-NEXT: ({{.*}}) $1 = 3
+# CHECK: (lldb) type lookup ns::NamespaceTypedef
+# CHECK-NEXT: struct S {
+# CHECK: (lldb) type lookup GlobalTypedef
+# CHECK-NEXT: struct S {
>From bf9ddffbdff18ed07fce7652d7d4b12bb9b58048 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 29 Oct 2026 21:46:08 +0000
Subject: [PATCH 2/3] address comments
---
.../SymbolFile/NativePDB/typedef-lookup.test | 22 +++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test b/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
index 5c9f79352807a8..c4573c5533b635 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
+++ b/lldb/test/Shell/SymbolFile/NativePDB/typedef-lookup.test
@@ -1,8 +1,9 @@
# REQUIRES: target-windows
# Test that typedefs are found by name. They are only S_UDT records, not type
-# records, and "ns" isn't the scope of anything but a typedef. Evaluate the
-# expressions first, since looking up the type also creates the namespace.
+# records, and "ns", "outer" and "outer::inner" aren't the scope of anything but
+# a typedef. Evaluate the expressions first, since looking up the type also
+# creates the namespace.
# RUN: split-file %s %t
# RUN: %build --nodefaultlib -o %t.exe -- %t/main.cpp
# RUN: %lldb -f %t.exe -s \
@@ -20,25 +21,38 @@ namespace ns {
typedef S NamespaceTypedef;
} // namespace ns
+namespace outer {
+namespace inner {
+typedef S NestedTypedef;
+} // namespace inner
+} // namespace outer
+
int main() {
GlobalTypedef g;
ns::NamespaceTypedef n;
- return sizeof(g) + sizeof(n);
+ outer::inner::NestedTypedef i;
+ return sizeof(g) + sizeof(n) + sizeof(i);
}
#--- commands.input
expr sizeof(ns::NamespaceTypedef)
+expr sizeof(outer::inner::NestedTypedef)
expr sizeof(GlobalTypedef)
type lookup ns::NamespaceTypedef
+type lookup outer::inner::NestedTypedef
type lookup GlobalTypedef
quit
# CHECK: (lldb) expr sizeof(ns::NamespaceTypedef)
# CHECK-NEXT: ({{.*}}) $0 = 3
-# CHECK: (lldb) expr sizeof(GlobalTypedef)
+# CHECK: (lldb) expr sizeof(outer::inner::NestedTypedef)
# CHECK-NEXT: ({{.*}}) $1 = 3
+# CHECK: (lldb) expr sizeof(GlobalTypedef)
+# CHECK-NEXT: ({{.*}}) $2 = 3
# CHECK: (lldb) type lookup ns::NamespaceTypedef
# CHECK-NEXT: struct S {
+# CHECK: (lldb) type lookup outer::inner::NestedTypedef
+# CHECK-NEXT: struct S {
# CHECK: (lldb) type lookup GlobalTypedef
# CHECK-NEXT: struct S {
>From 51443c5448b6612ee954675c6a3b7d34607daabe Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 30 Oct 2026 11:57:20 -0700
Subject: [PATCH 3/3] Use MSVCUndecoratedNameParser to extract typedef scopes
---
.../NativePDB/SymbolFileNativePDB.cpp | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 146b1978b36bd9..b34f7694da7bac 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -3066,20 +3066,11 @@ void SymbolFileNativePDB::BuildParentMap() {
}
if (!IsTypedefUdt(*udt_or_err))
continue;
- llvm::StringRef base_name =
- MSVCUndecoratedNameParser::DropScope(udt_or_err->Name);
- m_typedef_base_names.Append(ConstString(base_name), gid);
-
- if (std::optional<Type::ParsedName> parsed_name =
- Type::GetTypeScopeAndBasename(udt_or_err->Name)) {
- std::string scope_name;
- for (llvm::StringRef scope : parsed_name->scope) {
- if (!scope_name.empty())
- scope_name += "::";
- scope_name += scope;
- m_typedef_scopes.try_emplace(scope_name, gid);
- }
- }
+ MSVCUndecoratedNameParser parser(udt_or_err->Name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+ m_typedef_base_names.Append(ConstString(specs.back().GetBaseName()), gid);
+ for (const MSVCUndecoratedNameSpecifier &scope : specs.drop_back())
+ m_typedef_scopes.try_emplace(scope.GetFullName(), gid);
}
m_typedef_base_names.Sort(std::less<uint32_t>());
More information about the lldb-commits
mailing list