https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/166845
>From 7566542a194db8d8516432e0213d4f9d43aa488d Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Thu, 6 Nov 2025 21:45:05 +0100 Subject: [PATCH 1/3] [LLDB][NativePDB] Use original struct name when searching for constants --- .../Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp | 8 +++++++- lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 46cf9b8524ede..bfaba7f91b711 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -168,7 +168,13 @@ Error UdtRecordCompleter::visitKnownMember( // Static constant members may be a const[expr] declaration. // Query the symbol's value as the variable initializer if valid. if (member_ct.IsConst() && member_ct.IsCompleteType()) { - std::string qual_name = decl->getQualifiedNameAsString(); + std::string qual_name; + if (m_record.record.kind == Member::Struct) + qual_name = (m_cvr.cr.Name + "::" + static_data_member.Name).str(); + else if (m_record.record.kind == Member::Union) + qual_name = (m_cvr.ur.Name + "::" + static_data_member.Name).str(); + else + qual_name = decl->getQualifiedNameAsString(); auto results = m_index.globals().findRecordsByName(qual_name, m_index.symrecords()); diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp index ac0d87e95dbf9..4b267c398e766 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp @@ -56,6 +56,7 @@ namespace { int AnonymousMember; // And a nested class within an anonymous namespace struct D { + static constexpr int StaticMember = 1; int AnonymousDMember; }; }; @@ -177,6 +178,8 @@ int SI::*mp9 = nullptr; // 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' int main(int argc, char **argv) { @@ -184,5 +187,5 @@ int main(int argc, char **argv) { AnonABCVoid.AnonymousMember = 2; AnonABCVoidD.AnonymousDMember = 3; - return 0; + return AnonABCVoidD.StaticMember; } >From be1123fa94dee98e2a01293cbed7245b56ba7d33 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 10 Dec 2025 17:35:04 +0100 Subject: [PATCH 2/3] refactor: use `CVTagRecord` to store the record --- .../NativePDB/UdtRecordCompleter.cpp | 38 +++++++------------ .../SymbolFile/NativePDB/UdtRecordCompleter.h | 9 +---- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index bfaba7f91b711..8ab06e09b024e 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -41,30 +41,22 @@ UdtRecordCompleter::UdtRecordCompleter( llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &cxx_record_map) - : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl), + : m_cv_tag_record(CVTagRecord::create(index.tpi().getType(id.index))), + m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl), m_ast_builder(ast_builder), m_index(index), m_decl_to_status(decl_to_status), m_cxx_record_map(cxx_record_map) { - CVType cvt = m_index.tpi().getType(m_id.index); - switch (cvt.kind()) { - case LF_ENUM: - m_cvr.er.Options = ClassOptions::None; - llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er)); + switch (m_cv_tag_record.kind()) { + case CVTagRecord::Enum: break; - case LF_UNION: - m_cvr.ur.Options = ClassOptions::None; - llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur)); - m_layout.bit_size = m_cvr.ur.getSize() * 8; + case CVTagRecord::Union: + m_layout.bit_size = m_cv_tag_record.asUnion().getSize() * 8; m_record.record.kind = Member::Union; break; - case LF_CLASS: - case LF_STRUCTURE: - m_cvr.cr.Options = ClassOptions::None; - llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr)); - m_layout.bit_size = m_cvr.cr.getSize() * 8; + case CVTagRecord::Class: + case CVTagRecord::Struct: + m_layout.bit_size = m_cv_tag_record.asClass().getSize() * 8; m_record.record.kind = Member::Struct; break; - default: - llvm_unreachable("unreachable!"); } } @@ -168,13 +160,11 @@ Error UdtRecordCompleter::visitKnownMember( // Static constant members may be a const[expr] declaration. // Query the symbol's value as the variable initializer if valid. if (member_ct.IsConst() && member_ct.IsCompleteType()) { - std::string qual_name; - if (m_record.record.kind == Member::Struct) - qual_name = (m_cvr.cr.Name + "::" + static_data_member.Name).str(); - else if (m_record.record.kind == Member::Union) - qual_name = (m_cvr.ur.Name + "::" + static_data_member.Name).str(); - else - qual_name = decl->getQualifiedNameAsString(); + // Reconstruct the full name for the static member. Use the names as given + // in the PDB. This ensures we match the compiler's style of names (e.g. + // "A<B<int> >::Foo" vs "A<B<int>>::Foo"). + std::string qual_name = + (m_cv_tag_record.name() + "::" + static_data_member.Name).str(); auto results = m_index.globals().findRecordsByName(qual_name, m_index.symrecords()); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index e6e91d0f2c3e4..73c45456899e4 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -11,6 +11,7 @@ #include "PdbAstBuilder.h" #include "PdbSymUid.h" +#include "PdbUtil.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" @@ -41,13 +42,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { using IndexedBase = std::pair<uint64_t, std::unique_ptr<clang::CXXBaseSpecifier>>; - union UdtTagRecord { - UdtTagRecord() {} - llvm::codeview::UnionRecord ur; - llvm::codeview::ClassRecord cr; - llvm::codeview::EnumRecord er; - } m_cvr; - + CVTagRecord m_cv_tag_record; PdbTypeSymId m_id; CompilerType &m_derived_ct; clang::TagDecl &m_tag_decl; >From 3aade9c0a43ae3c880743ac461d98c9e7615f41b Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 10 Dec 2025 17:35:27 +0100 Subject: [PATCH 3/3] test: Add check for static member in union --- .../NativePDB/Inputs/ast-types.lldbinit | 1 + .../Shell/SymbolFile/NativePDB/ast-types.cpp | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit index a79d18fcfbe70..5062faa97db00 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit @@ -19,6 +19,7 @@ target variable ADE target variable AnonInt target variable AnonABCVoid target variable AnonABCVoidD +target variable AnonABCVoidU target variable mp1 mp2 mp3 mp4 mp5 mp6 mp7 mp8 mp9 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp index 4b267c398e766..e3af6d21893a7 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp @@ -59,6 +59,11 @@ namespace { static constexpr int StaticMember = 1; int AnonymousDMember; }; + + union U { + static constexpr int StaticMember = 2; + int AnonymousUMember; + }; }; } @@ -86,6 +91,7 @@ A::D::E ADE; Anonymous<int> AnonInt; Anonymous<A::B::C<void>> AnonABCVoid; Anonymous<A::B::C<void>>::D AnonABCVoidD; +Anonymous<A::B::C<void>>::U AnonABCVoidU; // The following tests that MSInheritanceAttr are set for record decls. class SI { int si; }; @@ -132,6 +138,7 @@ int SI::*mp9 = nullptr; // CHECK: (Anonymous<int>) AnonInt = (AnonymousMember = 0) // CHECK: (Anonymous<A::B::C<void>>) AnonABCVoid = (AnonymousMember = 0) // CHECK: (Anonymous<A::B::C<void>>::D) AnonABCVoidD = (AnonymousDMember = 0) +// CHECK: (Anonymous<A::B::C<void>>::U) AnonABCVoidU = (AnonymousUMember = 0) // CHECK: (void (SI::*)()) mp1 = 0x0000000000000000 // CHECK: (void (MI::*)()) mp2 = 0x0000000000000000 // CHECK: (void (MI2::*)()) mp3 = 0x0000000000000000 @@ -177,15 +184,21 @@ int SI::*mp9 = nullptr; // 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 {{.*}} 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' + int main(int argc, char **argv) { AnonInt.AnonymousMember = 1; AnonABCVoid.AnonymousMember = 2; AnonABCVoidD.AnonymousDMember = 3; + AnonABCVoidU.AnonymousUMember = 4; - return AnonABCVoidD.StaticMember; + return AnonABCVoidD.StaticMember + AnonABCVoidU.StaticMember; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
