Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
6 changes: 3 additions & 3 deletions lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
57 changes: 43 additions & 14 deletions lldb/test/Shell/SymbolFile/NativePDB/nested-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Loading