[Lldb-commits] [lldb] 6f44be6 - [LLDB][NativePDB] Use original struct name when searching for constants (#166845)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Dec 12 06:33:42 PST 2025
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 at U?$C at X@B at 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;
}
More information about the lldb-commits
mailing list