Author: nerix Date: 2025-12-12T15:33:38+01:00 New Revision: 6f44be6f3e9fb6d373125b17b65bd6e09144b382
URL: https://github.com/llvm/llvm-project/commit/6f44be6f3e9fb6d373125b17b65bd6e09144b382 DIFF: https://github.com/llvm/llvm-project/commit/6f44be6f3e9fb6d373125b17b65bd6e09144b382.diff LOG: [LLDB][NativePDB] Use original struct name when searching for constants (#166845) We used to search for constants using the name we parsed. For C++, this would mean using the demangled struct name (from the unique name). This name is not always equal to the one used for the struct's name by the compiler. For example: ``` 0x105E | LF_STRUCTURE [size = 120, hash = 0xF38F] ``anonymous namespace'::Anonymous<A::B::C<void> >::D` unique name: `.?AUD@?$Anonymous@U?$C@X@B@A@@@?A0x8C295248@@` ``` We would use the unique name and get to `(anonymous namespace)::Anonymous<struct A::B::C<void>>::D`. Then, when finding the constant in the field list, we'd search for `(anonymous namespace)::Anonymous<struct A::B::C<void>>::D::StaticMember`. This wouldn't yield any results, because the constant will use the demangled name as given by the compiler. With this PR, we use the struct's name as given in the PDB and append the member name. Added: Modified: lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 46cf9b8524ede..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,7 +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 = 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; 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 ac0d87e95dbf9..e3af6d21893a7 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp @@ -56,8 +56,14 @@ namespace { int AnonymousMember; // And a nested class within an anonymous namespace struct D { + static constexpr int StaticMember = 1; int AnonymousDMember; }; + + union U { + static constexpr int StaticMember = 2; + int AnonymousUMember; + }; }; } @@ -85,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; }; @@ -131,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 @@ -176,13 +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: | `-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 0; + return AnonABCVoidD.StaticMember + AnonABCVoidU.StaticMember; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
