Skip to content

Commit 0457ab5

Browse files
Nerixyzanonymouspc
authored andcommitted
[LLDB][NativePDB] Use original struct name when searching for constants (llvm#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.
1 parent f3169e2 commit 0457ab5

File tree

4 files changed

+36
-28
lines changed

4 files changed

+36
-28
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,22 @@ UdtRecordCompleter::UdtRecordCompleter(
4141
llvm::DenseMap<lldb::opaque_compiler_type_t,
4242
llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
4343
&cxx_record_map)
44-
: m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
44+
: m_cv_tag_record(CVTagRecord::create(index.tpi().getType(id.index))),
45+
m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
4546
m_ast_builder(ast_builder), m_index(index),
4647
m_decl_to_status(decl_to_status), m_cxx_record_map(cxx_record_map) {
47-
CVType cvt = m_index.tpi().getType(m_id.index);
48-
switch (cvt.kind()) {
49-
case LF_ENUM:
50-
m_cvr.er.Options = ClassOptions::None;
51-
llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
48+
switch (m_cv_tag_record.kind()) {
49+
case CVTagRecord::Enum:
5250
break;
53-
case LF_UNION:
54-
m_cvr.ur.Options = ClassOptions::None;
55-
llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
56-
m_layout.bit_size = m_cvr.ur.getSize() * 8;
51+
case CVTagRecord::Union:
52+
m_layout.bit_size = m_cv_tag_record.asUnion().getSize() * 8;
5753
m_record.record.kind = Member::Union;
5854
break;
59-
case LF_CLASS:
60-
case LF_STRUCTURE:
61-
m_cvr.cr.Options = ClassOptions::None;
62-
llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
63-
m_layout.bit_size = m_cvr.cr.getSize() * 8;
55+
case CVTagRecord::Class:
56+
case CVTagRecord::Struct:
57+
m_layout.bit_size = m_cv_tag_record.asClass().getSize() * 8;
6458
m_record.record.kind = Member::Struct;
6559
break;
66-
default:
67-
llvm_unreachable("unreachable!");
6860
}
6961
}
7062

@@ -168,7 +160,11 @@ Error UdtRecordCompleter::visitKnownMember(
168160
// Static constant members may be a const[expr] declaration.
169161
// Query the symbol's value as the variable initializer if valid.
170162
if (member_ct.IsConst() && member_ct.IsCompleteType()) {
171-
std::string qual_name = decl->getQualifiedNameAsString();
163+
// Reconstruct the full name for the static member. Use the names as given
164+
// in the PDB. This ensures we match the compiler's style of names (e.g.
165+
// "A<B<int> >::Foo" vs "A<B<int>>::Foo").
166+
std::string qual_name =
167+
(m_cv_tag_record.name() + "::" + static_data_member.Name).str();
172168

173169
auto results =
174170
m_index.globals().findRecordsByName(qual_name, m_index.symrecords());

lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "PdbAstBuilder.h"
1313
#include "PdbSymUid.h"
14+
#include "PdbUtil.h"
1415
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
1516
#include "llvm/DebugInfo/CodeView/CVRecord.h"
1617
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
@@ -41,13 +42,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks {
4142
using IndexedBase =
4243
std::pair<uint64_t, std::unique_ptr<clang::CXXBaseSpecifier>>;
4344

44-
union UdtTagRecord {
45-
UdtTagRecord() {}
46-
llvm::codeview::UnionRecord ur;
47-
llvm::codeview::ClassRecord cr;
48-
llvm::codeview::EnumRecord er;
49-
} m_cvr;
50-
45+
CVTagRecord m_cv_tag_record;
5146
PdbTypeSymId m_id;
5247
CompilerType &m_derived_ct;
5348
clang::TagDecl &m_tag_decl;

lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ target variable ADE
1919
target variable AnonInt
2020
target variable AnonABCVoid
2121
target variable AnonABCVoidD
22+
target variable AnonABCVoidU
2223

2324
target variable mp1 mp2 mp3 mp4 mp5 mp6 mp7 mp8 mp9
2425

lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,14 @@ namespace {
5656
int AnonymousMember;
5757
// And a nested class within an anonymous namespace
5858
struct D {
59+
static constexpr int StaticMember = 1;
5960
int AnonymousDMember;
6061
};
62+
63+
union U {
64+
static constexpr int StaticMember = 2;
65+
int AnonymousUMember;
66+
};
6167
};
6268
}
6369

@@ -85,6 +91,7 @@ A::D::E ADE;
8591
Anonymous<int> AnonInt;
8692
Anonymous<A::B::C<void>> AnonABCVoid;
8793
Anonymous<A::B::C<void>>::D AnonABCVoidD;
94+
Anonymous<A::B::C<void>>::U AnonABCVoidU;
8895

8996
// The following tests that MSInheritanceAttr are set for record decls.
9097
class SI { int si; };
@@ -131,6 +138,7 @@ int SI::*mp9 = nullptr;
131138
// CHECK: (Anonymous<int>) AnonInt = (AnonymousMember = 0)
132139
// CHECK: (Anonymous<A::B::C<void>>) AnonABCVoid = (AnonymousMember = 0)
133140
// CHECK: (Anonymous<A::B::C<void>>::D) AnonABCVoidD = (AnonymousDMember = 0)
141+
// CHECK: (Anonymous<A::B::C<void>>::U) AnonABCVoidU = (AnonymousUMember = 0)
134142
// CHECK: (void (SI::*)()) mp1 = 0x0000000000000000
135143
// CHECK: (void (MI::*)()) mp2 = 0x0000000000000000
136144
// CHECK: (void (MI2::*)()) mp3 = 0x0000000000000000
@@ -176,13 +184,21 @@ int SI::*mp9 = nullptr;
176184
// CHECK: | | `-FieldDecl {{.*}} AnonymousMember 'int'
177185
// CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition
178186
// CHECK: | |-FieldDecl {{.*}} AnonymousMember 'int'
179-
// CHECK: | `-CXXRecordDecl {{.*}} struct D definition
180-
// CHECK: | `-FieldDecl {{.*}} AnonymousDMember 'int'
187+
// CHECK: | |-CXXRecordDecl {{.*}} struct D definition
188+
// CHECK: | | |-VarDecl {{.*}} StaticMember 'const int' static cinit
189+
// CHECK: | | | `-IntegerLiteral {{.*}} 'int' 1
190+
// CHECK: | | `-FieldDecl {{.*}} AnonymousDMember 'int'
191+
// CHECK: | `-CXXRecordDecl {{.*}} union U definition
192+
// CHECK: | |-VarDecl {{.*}} StaticMember 'const int' static
193+
// CHECK: | | `-IntegerLiteral {{.*}} 'int' 2
194+
// CHECK: | `-FieldDecl {{.*}} AnonymousUMember 'int'
195+
181196

182197
int main(int argc, char **argv) {
183198
AnonInt.AnonymousMember = 1;
184199
AnonABCVoid.AnonymousMember = 2;
185200
AnonABCVoidD.AnonymousDMember = 3;
201+
AnonABCVoidU.AnonymousUMember = 4;
186202

187-
return 0;
203+
return AnonABCVoidD.StaticMember + AnonABCVoidU.StaticMember;
188204
}

0 commit comments

Comments
 (0)