[Lldb-commits] [lldb] [LLDB][NativePDB] Create typedefs in structs (PR #169248)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Dec 12 12:19:44 PST 2025
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/169248
>From 66148315c58efd99056b91fd8984da33048052e0 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Sun, 23 Nov 2025 23:01:12 +0100
Subject: [PATCH 1/2] [LLDB][NativePDB] Create typedefs in structs
---
.../NativePDB/UdtRecordCompleter.cpp | 26 +++++++++
.../Shell/SymbolFile/NativePDB/ast-types.cpp | 6 +-
.../SymbolFile/NativePDB/nested-types.cpp | 57 ++++++++++++++-----
3 files changed, 72 insertions(+), 17 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 46cf9b8524ede..d8e4255b4823f 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -233,6 +233,32 @@ Error UdtRecordCompleter::visitKnownMember(
Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
NestedTypeRecord &nested) {
+ // Typedefs can only be added on structs.
+ if (m_record.record.kind != Member::Struct)
+ return Error::success();
+
+ clang::QualType qt =
+ m_ast_builder.GetOrCreateType(PdbTypeSymId(nested.Type, false));
+ if (qt.isNull())
+ return Error::success();
+ CompilerType ct = m_ast_builder.ToCompilerType(qt);
+
+ // There's no distinction between nested types and typedefs, so check if we
+ // encountered a nested type.
+ auto *pdb = static_cast<SymbolFileNativePDB *>(
+ m_ast_builder.clang().GetSymbolFile()->GetBackingSymbolFile());
+ std::optional<TypeIndex> parent = pdb->GetParentType(nested.Type);
+ if (parent && *parent == m_id.index && ct.GetTypeName(true) == nested.Name)
+ return Error::success();
+
+ clang::DeclContext *decl_ctx =
+ m_ast_builder.GetOrCreateDeclContextForUid(m_id);
+ if (!decl_ctx)
+ return Error::success();
+
+ std::string name = nested.Name.str();
+ ct.CreateTypedef(name.c_str(), m_ast_builder.ToCompilerDeclContext(*decl_ctx),
+ 0);
return Error::success();
}
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
index ac0d87e95dbf9..dea124c6d6145 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
@@ -175,9 +175,9 @@ int SI::*mp9 = nullptr;
// CHECK: | |-CXXRecordDecl {{.*}} struct Anonymous<int> definition
// CHECK: | | `-FieldDecl {{.*}} AnonymousMember 'int'
// CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition
-// CHECK: | |-FieldDecl {{.*}} AnonymousMember 'int'
-// CHECK: | `-CXXRecordDecl {{.*}} struct D definition
-// CHECK: | `-FieldDecl {{.*}} AnonymousDMember 'int'
+// CHECK: | |-CXXRecordDecl {{.*}} struct D definition
+// CHECK: | | `-FieldDecl {{.*}} AnonymousDMember 'int'
+// CHECK: | `-FieldDecl {{.*}} AnonymousMember 'int'
int main(int argc, char **argv) {
AnonInt.AnonymousMember = 1;
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/nested-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/nested-types.cpp
index f725037a220d9..a4b07cdb1b1b7 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/nested-types.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/nested-types.cpp
@@ -126,30 +126,59 @@ int main(int argc, char **argv) {
// CHECK: (lldb) target modules dump ast
// CHECK: Dumping clang ast for 1 modules.
// CHECK: TranslationUnitDecl {{.*}}
+
// CHECK: |-CXXRecordDecl {{.*}} struct S definition
-// CHECK: | |-FieldDecl {{.*}} C 'int'
-// CHECK: | |-FieldDecl {{.*}} D 'int'
-// CHECK: | |-FieldDecl {{.*}} DD 'void *'
// CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition
// CHECK: | | |-FieldDecl {{.*}} A 'int'
// CHECK: | | `-FieldDecl {{.*}} B 'int'
-// CHECK: | `-EnumDecl {{.*}} NestedEnum
-// CHECK: | |-EnumConstantDecl {{.*}} EnumValue1 'S::NestedEnum'
-// CHECK: | `-EnumConstantDecl {{.*}} EnumValue2 'S::NestedEnum'
+// CHECK: | |-EnumDecl {{.*}} NestedEnum
+// CHECK: | | |-EnumConstantDecl {{.*}} EnumValue1 'S::NestedEnum'
+// CHECK: | | `-EnumConstantDecl {{.*}} EnumValue2 'S::NestedEnum'
+// CHECK: | |-TypedefDecl {{.*}} VoidPtrT 'void *'
+// CHECK: | | `-PointerType {{.*}} 'void *'
+// CHECK: | | `-BuiltinType {{.*}} 'void'
+// CHECK: | |-FieldDecl {{.*}} C 'int'
+// CHECK: | |-FieldDecl {{.*}} D 'int'
+// CHECK: | `-FieldDecl {{.*}} DD 'void *'
+
// CHECK: |-CXXRecordDecl {{.*}} struct T definition
-// CHECK: | |-FieldDecl {{.*}} NT 'int'
+// CHECK: | |-TypedefDecl {{.*}} NestedTypedef 'int'
+// CHECK: | | `-BuiltinType {{.*}} 'int'
+// CHECK: | |-TypedefDecl {{.*}} NestedTypedef2 'S'
+// CHECK: | | `-RecordType {{.*}} 'S' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'S'
// CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition
// CHECK: | | |-FieldDecl {{.*}} E 'int'
// CHECK: | | `-FieldDecl {{.*}} F 'int'
-// CHECK: | `-CXXRecordDecl {{.*}} struct U definition
-// CHECK: | |-FieldDecl {{.*}} G 'int'
-// CHECK: | `-FieldDecl {{.*}} H 'int'
+// CHECK: | |-TypedefDecl {{.*}} NestedStructAlias 'T::NestedStruct'
+// CHECK: | | `-RecordType {{.*}} 'T::NestedStruct' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'NestedStruct'
+// CHECK: | |-TypedefDecl {{.*}} NST 'S::NestedStruct'
+// CHECK: | | `-RecordType {{.*}} 'S::NestedStruct' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'NestedStruct'
+// CHECK: | |-CXXRecordDecl {{.*}} struct U definition
+// CHECK: | | |-FieldDecl {{.*}} G 'int'
+// CHECK: | | `-FieldDecl {{.*}} H 'int'
+// CHECK: | `-FieldDecl {{.*}} NT 'int'
+
// CHECK: |-CXXRecordDecl {{.*}} class U<int> definition
+// CHECK: | |-CXXRecordDecl {{.*}} struct W definition
+// CHECK: | | |-FieldDecl {{.*}} M 'int'
+// CHECK: | | `-FieldDecl {{.*}} N 'int'
+// CHECK: | |-TypedefDecl {{.*}} Y 'U<int>::V<int>'
+// CHECK: | | `-RecordType {{.*}} 'U<int>::V<int>' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'U<int>::V<int>'
+// CHECK: | |-TypedefDecl {{.*}} Z 'U<int>::V<T>'
+// CHECK: | | `-RecordType {{.*}} 'U<int>::V<T>' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'U<int>::V<T>'
// CHECK: | |-FieldDecl {{.*}} K 'int'
-// CHECK: | |-FieldDecl {{.*}} L 'int'
-// CHECK: | `-CXXRecordDecl {{.*}} struct W definition
-// CHECK: | |-FieldDecl {{.*}} M 'int'
-// CHECK: | `-FieldDecl {{.*}} N 'int'
+// CHECK: | `-FieldDecl {{.*}} L 'int'
+
// CHECK: |-CXXRecordDecl {{.*}} struct U<int>::V<int> definition
+// CHECK: | |-TypedefDecl {{.*}}> W 'int'
+// CHECK: | | `-BuiltinType {{.*}} 'int'
+// CHECK: | |-TypedefDecl {{.*}} X 'U<int>'
+// CHECK: | | `-RecordType {{.*}} 'U<int>' canonical
+// CHECK: | | `-CXXRecord {{.*}} 'U<int>'
// CHECK: | |-FieldDecl {{.*}} I 'int'
// CHECK: | `-FieldDecl {{.*}} J 'int'
>From e19984600ae12c58c093af82e72d06edb9373591 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Fri, 12 Dec 2025 21:19:23 +0100
Subject: [PATCH 2/2] fix: test (fields are now at the bottom)
---
lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
index e3af6d21893a7..4cc0b376d3ef9 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
@@ -183,15 +183,15 @@ int SI::*mp9 = nullptr;
// CHECK: | |-CXXRecordDecl {{.*}} struct Anonymous<int> definition
// CHECK: | | `-FieldDecl {{.*}} AnonymousMember 'int'
// CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition
-// CHECK: | |-FieldDecl {{.*}} AnonymousMember 'int'
// CHECK: | |-CXXRecordDecl {{.*}} struct D definition
// CHECK: | | |-VarDecl {{.*}} StaticMember 'const int' static cinit
// CHECK: | | | `-IntegerLiteral {{.*}} 'int' 1
// CHECK: | | `-FieldDecl {{.*}} AnonymousDMember 'int'
-// CHECK: | `-CXXRecordDecl {{.*}} union U definition
-// CHECK: | |-VarDecl {{.*}} StaticMember 'const int' static
-// CHECK: | | `-IntegerLiteral {{.*}} 'int' 2
-// CHECK: | `-FieldDecl {{.*}} AnonymousUMember 'int'
+// CHECK: | |-CXXRecordDecl {{.*}} union U definition
+// CHECK: | | |-VarDecl {{.*}} StaticMember 'const int' static
+// CHECK: | | | `-IntegerLiteral {{.*}} 'int' 2
+// CHECK: | | `-FieldDecl {{.*}} AnonymousUMember 'int'
+// CHECK: | `-FieldDecl {{.*}} AnonymousMember 'int'
int main(int argc, char **argv) {
More information about the lldb-commits
mailing list