diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -666,9 +666,21 @@ cvt = m_index.tpi().getType(best_ti.index); lldbassert(IsTagRecord(cvt)); + CompilerType ct = ToCompilerType(tag_qt); if (IsForwardRefUdt(cvt)) { // If we can't find a full decl for this forward ref anywhere in the debug - // info, then we have no way to complete it. + // info, then we have no way to complete it, just forcefully marking it as + // completed. Otherwise, clang will crash due to missing DefinitionData when + // trying to import AST. + if (!ct.GetCompleteType()) { + bool started = TypeSystemClang::StartTagDeclarationDefinition(ct); + lldbassert(started && "Unable to start a class type definition."); + TypeSystemClang::CompleteTagDeclarationDefinition(ct); + if (TypeSystemClang::IsCXXClassType(ct)) { + auto &ts = llvm::cast(*ct.GetTypeSystem()); + ts.GetMetadata(&tag)->SetIsForcefullyCompleted(); + } + } return false; } @@ -683,7 +695,6 @@ // Visit all members of this class, then perform any finalization necessary // to complete the class. - CompilerType ct = ToCompilerType(tag_qt); UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index, m_cxx_record_map); llvm::Error error = diff --git a/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s b/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s --- a/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s +++ b/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s @@ -1,14 +1,18 @@ # clang-format off # REQUIRES: lld, x86 -# Test when type index is missing in FieldList. +# Test when class type is incomplete or type index is missing in FieldList. # RUN: llvm-mc -triple=x86_64-windows-msvc --filetype=obj %s > %t.obj -# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe /base:0x140000000 -# RUN: lldb-test symbols --find=type --name=S %t.exe | FileCheck %s +# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe +# RUN: lldb-test symbols --find=type --name=S %t.exe | FileCheck %s --check-prefix=MISSING-DATA-TYPE +# RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -o "expr a" -o "exit" \ +# RUN: | FileCheck %s --check-prefix=IMCOMPLETE-CLASS -# CHECK: name = "S", size = 4, compiler_type = {{.*}} struct S { -# CHECK-NEXT: } +# MISSING-DATA-TYPE: name = "S", size = 4, compiler_type = {{.*}} struct S { +# MISSING-DATA-TYPE-NEXT: } +# IMCOMPLETE-CLASS: (lldb) expr a +# IMCOMPLETE-CLASS-NEXT: (A) $0 = {} .text @@ -43,10 +47,54 @@ .Lfunc_end0: .seh_endproc # -- End function - .section .drectve,"yn" -.Ltmp25: + .bss + .globl "?a@@3VA@@A" # @"?a@@3VA@@A" + .p2align 2, 0x0 +"?a@@3VA@@A": + .zero 4 + .section .debug$S,"dr" + .p2align 2, 0x0 + .long 4 # Debug section magic + .long 241 + .long .Ltmp3-.Ltmp2 # Subsection size +.Ltmp2: + .short .Ltmp3-.Ltmp6 # Record length +.Ltmp6: + .short 4412 # Record kind: S_COMPILE3 + .long 1 # Flags and language + .short 208 # CPUType + .short 16 # Frontend version + .short 0 + .short 0 + .short 0 + .short 16000 # Backend version + .short 0 + .short 0 + .short 0 + .asciz "clang version 16.0.0" # Null-terminated compiler version string + .p2align 2, 0x0 +.Ltmp3: + .p2align 2, 0x0 + .long 241 # Symbol subsection for main + .long 0 + .p2align 2, 0x0 + .cv_linetable 0, main, .Lfunc_end0 + .long 241 # Symbol subsection for globals + .long .Ltmp19-.Ltmp14 # Subsection size +.Ltmp14: + .short .Ltmp19-.Ltmp16 # Record length +.Ltmp16: + .short 4365 # Record kind: S_GDATA32 + .long 4103 # Type + .secrel32 "?a@@3VA@@A" # DataOffset + .secidx "?a@@3VA@@A" # Segment + .asciz "a" # Name + .p2align 2, 0x0 + +.Ltmp19: + .p2align 2, 0x0 .section .debug$T,"dr" - .p2align 2 + .p2align 2, 0x0 .long 4 # Debug section magic # Pointer (0x1000) .short 0xa # Record length @@ -87,6 +135,7 @@ .short 0x0 # SizeOf .asciz "S" # Name .asciz ".?AUS@@" # LinkageName + # Test when a class member has missing type info. # FieldList (0x1005) .short 0xe # Record length .short 0x1203 # Record kind: LF_FIELDLIST @@ -106,3 +155,15 @@ .short 0x4 # SizeOf .asciz "S" # Name .asciz ".?AUS@@" # LinkageName + # Test when class doesn't have full type info (forward reference to itself). + # Class (0x1007) + .short 0x1e # Record length + .short 0x1504 # Record kind: LF_CLASS + .short 0x1 # MemberCount + .short 0x280 # Properties ( ForwardReference (0x80) | HasUniqueName (0x200) ) + .long 0x0 # FieldList: + .long 0x0 # DerivedFrom + .long 0x0 # VShape + .short 0x0 # SizeOf + .asciz "A" # Name + .asciz ".?AVA@@" # LinkageName