Index: llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -22,6 +22,7 @@ OcamlGCPrinter.cpp WinException.cpp CodeViewDebug.cpp + VariableLocation.cpp DEPENDS intrinsics_gen Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -94,6 +94,7 @@ struct LocalVariable { const DILocalVariable *DIVar = nullptr; SmallVector DefRanges; + bool Deref = false; }; struct InlineSite { @@ -259,6 +260,8 @@ codeview::TypeIndex getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef = DITypeRef()); + codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef); + codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP, const DICompositeType *Class); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -13,6 +13,7 @@ #include "CodeViewDebug.h" #include "DwarfExpression.h" +#include "VariableLocation.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -978,54 +979,56 @@ LocalVariable Var; Var.DIVar = DIVar; - // Calculate the definition ranges. + // Because we cannot express DW_OP_deref in CodeView directly, + // we use a trick: we encode the type as a reference to the + // real type. Check if this is necessary. + // TODO(inglorion): Refactor this so we don't need to iterate twice. + for (auto I = Ranges.begin(), E = Ranges.end(); I != E && !Var.Deref; ++I) { + for (const auto &Op : I->first->getDebugExpression()->expr_ops()) + if (Op.getOp() == dwarf::DW_OP_deref) { + Var.Deref = true; + break; + } + } + + // calculate the definition ranges. for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { const InsnRange &Range = *I; const MachineInstr *DVInst = Range.first; assert(DVInst->isDebugValue() && "Invalid History entry"); - const DIExpression *DIExpr = DVInst->getDebugExpression(); - bool InMemory = DVInst->getOperand(1).isImm(); - bool IsSubfield = false; - unsigned StructOffset = 0; - // Recognize a +Offset expression. - int Offset = 0; - DIExpressionCursor Ops(DIExpr); - auto Op = Ops.peek(); - if (Op && Op->getOp() == dwarf::DW_OP_plus_uconst) { - Offset = Op->getArg(0); - Ops.take(); - } - - // Handle fragments. - auto Fragment = Ops.getFragmentInfo(); - if (Fragment) { - IsSubfield = true; - StructOffset = Fragment->OffsetInBits / 8; - } - // Ignore unrecognized exprs. - if (Ops.peek() && Ops.peek()->getOp() != dwarf::DW_OP_LLVM_fragment) - continue; - if (!InMemory && Offset) - continue; - - // Bail if operand 0 is not a valid register. This means the variable is a - // simple constant, or is described by a complex expression. // FIXME: Find a way to represent constant variables, since they are // relatively common. - unsigned Reg = - DVInst->getOperand(0).isReg() ? DVInst->getOperand(0).getReg() : 0; - if (Reg == 0) + VariableLocation Location; + bool Supported = VariableLocation::extractFromMachineInstruction(Location, *DVInst); + + // When we're encoding the type as a reference to the original type, + // we need to remove a level of indirection from incoming locations. + // E.g. [RSP+8] with DW_OP_deref becomes [RSP+8], + // and [RCX+0] without DW_OP_deref becomes RCX. + if (Var.Deref && !Location.Deref) { + if (Location.InMemory) + Location.InMemory = false; + else + Supported = false; + } + + // If we don't know how to handle this range, skip past it. + if (!Supported || (Location.Offset && !Location.InMemory)) continue; // Handle the two cases we can handle: indirect in memory and in register. - unsigned CVReg = TRI->getCodeViewRegNum(Reg); { LocalVarDefRange DR; - DR.CVRegister = CVReg; - DR.InMemory = InMemory; - DR.DataOffset = Offset; - DR.IsSubfield = IsSubfield; - DR.StructOffset = StructOffset; + DR.CVRegister = TRI->getCodeViewRegNum(Location.Register); + DR.InMemory = Location.InMemory; + DR.DataOffset = Location.Offset; + if (Location.FragmentInfo) { + DR.IsSubfield = true; + DR.StructOffset = Location.FragmentInfo->OffsetInBits / 8; + } else { + DR.IsSubfield = false; + DR.StructOffset = 0; + } if (Var.DefRanges.empty() || Var.DefRanges.back().isDifferentLocation(DR)) { @@ -1040,6 +1043,7 @@ // This range is valid until the next overlapping bitpiece. In the // common case, ranges will not be bitpieces, so they will overlap. auto J = std::next(I); + const DIExpression *DIExpr = DVInst->getDebugExpression(); while (J != E && !fragmentsOverlap(DIExpr, J->first->getDebugExpression())) ++J; @@ -1971,6 +1975,16 @@ return recordTypeIndexForDINode(Ty, TI, ClassTy); } +TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) { + DIType *Ty = TypeRef.resolve(); + PointerRecord PR(getTypeIndex(Ty), + getPointerSizeInBytes() == 8 ? PointerKind::Near64 + : PointerKind::Near32, + PointerMode::LValueReference, PointerOptions::None, + Ty->getSizeInBits() / 8); + return TypeTable.writeKnownType(PR); +} + TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { const DIType *Ty = TypeRef.resolve(); @@ -2078,7 +2092,8 @@ Flags |= LocalSymFlags::IsOptimizedOut; OS.AddComment("TypeIndex"); - TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType()); + TypeIndex TI = Var.Deref ? getTypeIndexForReferenceTo(Var.DIVar->getType()) + : getCompleteTypeIndex(Var.DIVar->getType()); OS.EmitIntValue(TI.getIndex(), 4); OS.AddComment("Flags"); OS.EmitIntValue(static_cast(Flags), 2); Index: llvm/lib/CodeGen/AsmPrinter/VariableLocation.h =================================================================== --- /dev/null +++ llvm/lib/CodeGen/AsmPrinter/VariableLocation.h @@ -0,0 +1,49 @@ +//===- llvm/lib/CodeGen/AsmPrinter/VariableLocation.h -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_VARIABLELOCATION_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_VARIABLELOCATION_H + +#include +#include + +namespace llvm { +class MachineInstr; + +/// Represents the location at which a variable is stored. +struct VariableLocation { + /// Offset relative to base register. + int64_t Offset; + + /// Base register. + unsigned Register; + + /// If false, Register is the location. If true, + /// Register+Offset point at the location. + int InMemory : 1; + + /// If false, the location holds the variable's value. + /// If true, the location holds the variable's address. + int Deref : 1; + + /// Present if the location is part of a larger variable. + llvm::Optional FragmentInfo; + + /// Extract a VariableLocation from a MachineInstr. The struct passed in as + /// Location is populated. The MachineInstr must be a debug value + /// instruction. + /// @return true if successful and false if not. + static bool extractFromMachineInstruction( + VariableLocation &Location, + const MachineInstr &Instruction); +}; + +} // end namespace llvm + +#endif // LLVM_LIB_CODEGEN_ASMPRINTER_VARIABLELOCATION_H Index: llvm/lib/CodeGen/AsmPrinter/VariableLocation.cpp =================================================================== --- /dev/null +++ llvm/lib/CodeGen/AsmPrinter/VariableLocation.cpp @@ -0,0 +1,67 @@ +//===- llvm/lib/CodeGen/AsmPrinter/VariableLocation.cpp ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "VariableLocation.h" +#include "llvm/CodeGen/MachineInstr.h" + +namespace llvm { + +bool VariableLocation::extractFromMachineInstruction( + VariableLocation &Location, + const MachineInstr &Instruction) { + if (!Instruction.isDebugValue()) + return false; + if (!Instruction.getOperand(0).isReg()) + return false; + Location.Register = Instruction.getOperand(0).getReg(); + Location.InMemory = Instruction.getOperand(1).isImm(); + Location.Deref = false; + Location.FragmentInfo.reset(); + // We only handle expressions generated by DIExpression::appendOffset, + // which doesn't require a full stack machine. + int64_t Offset = 0; + const DIExpression *DIExpr = Instruction.getDebugExpression(); + auto Op = DIExpr->expr_op_begin(); + while (Op != DIExpr->expr_op_end()) { + switch (Op->getOp()) { + case dwarf::DW_OP_constu: { + int Value = Op->getArg(0); + ++Op; + if (Op != DIExpr->expr_op_end()) { + switch (Op->getOp()) { + case dwarf::DW_OP_minus: + Offset -= Value; + break; + case dwarf::DW_OP_plus: + Offset += Value; + default: + continue; + } + } + } break; + case dwarf::DW_OP_plus_uconst: + Offset += Op->getArg(0); + break; + case dwarf::DW_OP_LLVM_fragment: + Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)}; + break; + case dwarf::DW_OP_deref: + Location.Deref = true; + break; + default: + return false; + } + ++Op; + } + + Location.Offset = Offset; + return true; +} + +} // end namespace llvm Index: llvm/test/CodeGen/MIR/X86/diexpr-win32.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/MIR/X86/diexpr-win32.mir @@ -0,0 +1,254 @@ +# RUN: llc -filetype=obj -O0 %s -o - | llvm-readobj -codeview | FileCheck %s +# +# (DW_OP_plus_uconst 12) +# CHECK: LocalSym { +# CHECK-NEXT: Kind: S_LOCAL (0x113E) +# CHECK-NEXT: Type: string* (0x +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: VarName: Str +# CHECK-NEXT: } +# CHECK-NEXT: DefRangeRegisterRelSym { +# CHECK-NEXT: Kind: S_DEFRANGE_REGISTER_REL (0x1145) +# CHECK-NEXT: BaseRegister: +# CHECK-NEXT: HasSpilledUDTMember: No +# CHECK-NEXT: OffsetInParent: 0 +# CHECK-NEXT: BasePointerOffset: 12 +# CHECK-NEXT: LocalVariableAddrRange { +# CHECK-NEXT: OffsetStart: +# CHECK-NEXT: ISectStart: +# CHECK-NEXT: Range: +# CHECK-NEXT: } +# CHECK-NEXT: } +# (DW_OP_plus_uconst, 8, DW_OP_deref) +# CHECK: LocalSym { +# CHECK-NEXT: Kind: S_LOCAL (0x113E) +# CHECK-NEXT: Type: string& (0x +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: VarName: Result +# CHECK-NEXT: } +# CHECK-NEXT: DefRangeRegisterRelSym { +# CHECK-NEXT: Kind: S_DEFRANGE_REGISTER_REL (0x1145) +# CHECK-NEXT: BaseRegister: +# CHECK-NEXT: HasSpilledUDTMember: No +# CHECK-NEXT: OffsetInParent: 0 +# CHECK-NEXT: BasePointerOffset: 8 +# CHECK-NEXT: LocalVariableAddrRange { +# CHECK-NEXT: OffsetStart: +# CHECK-NEXT: ISectStart: +# CHECK-NEXT: Range: +# CHECK-NEXT: } +# CHECK-NEXT: } +# (DW_OP_constu, 4, DW_OP_minus) +# CHECK: LocalSym { +# CHECK-NEXT: Kind: S_LOCAL (0x113E) +# CHECK-NEXT: Type: long (0x12) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: VarName: Bytes +# CHECK-NEXT: } +# CHECK-NEXT: DefRangeRegisterRelSym { +# CHECK-NEXT: Kind: S_DEFRANGE_REGISTER_REL (0x1145) +# CHECK-NEXT: BaseRegister: +# CHECK-NEXT: HasSpilledUDTMember: No +# CHECK-NEXT: OffsetInParent: 0 +# CHECK-NEXT: BasePointerOffset: -4 +# CHECK-NEXT: LocalVariableAddrRange { +# CHECK-NEXT: OffsetStart: +# CHECK-NEXT: ISectStart: +# CHECK-NEXT: Range: +# CHECK-NEXT: } +# CHECK-NEXT: } +--- | + ; ModuleID = '' + source_filename = "" + target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" + target triple = "i386-pc-windows-msvc19.0.24215" + + %struct.string = type { i32, i32, i8* } + + define void @fun(%struct.string* noalias sret %agg.result, %struct.string* noalias %str) !dbg !12 { + entry: + call void @llvm.dbg.value(metadata %struct.string* %agg.result, metadata !23, metadata !24), !dbg !25 + call void @llvm.dbg.value(metadata %struct.string* %str, metadata !26, metadata !28), !dbg !25 + %call = call dereferenceable(12) %struct.string* @getString(), !dbg !29 + %0 = bitcast %struct.string* %agg.result to i8*, !dbg !29 + %1 = bitcast %struct.string* %call to i8*, !dbg !29 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 12, i32 4, i1 false), !dbg !29 + ret void, !dbg !30 + } + + define i32 @len(%struct.string* %s, i32 %acc) !dbg !31 { + entry: + %0 = bitcast %struct.string* %s to i32* + %bytes = load i32, i32* %0, !dbg !34 + call void @llvm.dbg.declare(metadata i32 %bytes, metadata !35, metadata !28), !dbg !34 + %1 = add i32 %bytes, %acc, !dbg !36 + ret i32 %1, !dbg !36 + } + + ; Function Attrs: nounwind readnone speculatable + declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 + + ; Function Attrs: nounwind readnone speculatable + declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + + declare dereferenceable(12) %struct.string* @getString() + + ; Function Attrs: argmemonly nounwind + declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i32, i1) #1 + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #2 + + attributes #0 = { nounwind readnone speculatable } + attributes #1 = { argmemonly nounwind } + attributes #2 = { nounwind } + + !llvm.dbg.cu = !{!0} + !llvm.linker.options = !{!3, !4} + !llvm.module.flags = !{!5, !6, !7, !8} + !llvm.ident = !{!9} + !llvm.dbg.mir = !{!10, !11} + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "diexpr.ll", directory: "C:\5Csrc", checksumkind: CSK_MD5, checksum: "c547c362c610fa79e7abaddc76e1efe7") + !2 = !{} + !3 = !{!"/DEFAULTLIB:libcmt.lib"} + !4 = !{!"/DEFAULTLIB:oldnames.lib"} + !5 = !{i32 1, !"NumRegisterParameters", i32 0} + !6 = !{i32 2, !"CodeView", i32 1} + !7 = !{i32 2, !"Debug Info Version", i32 3} + !8 = !{i32 1, !"wchar_size", i32 2} + !9 = !{!"clang version 6.0.0 "} + !10 = !DIExpression(DW_OP_plus_uconst, 12) + !11 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref) + !12 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope: !1, file: !1, line: 9, type: !13, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) + !13 = !DISubroutineType(types: !14) + !14 = !{!15} + !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 1, size: 96, elements: !16, identifier: ".?AUstring@@") + !16 = !{!17, !19, !20} + !17 = !DIDerivedType(tag: DW_TAG_member, name: "length", scope: !15, file: !1, line: 2, baseType: !18, size: 32) + !18 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed) + !19 = !DIDerivedType(tag: DW_TAG_member, name: "size", scope: !15, file: !1, line: 3, baseType: !18, size: 32, offset: 32) + !20 = !DIDerivedType(tag: DW_TAG_member, name: "data", scope: !15, file: !1, line: 4, baseType: !21, size: 32, offset: 64) + !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 32) + !22 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) + !23 = !DILocalVariable(name: "Result", scope: !12, file: !1, line: 10, type: !15) + !24 = !DIExpression(DW_OP_deref) + !25 = !DILocation(line: 10, scope: !12) + !26 = !DILocalVariable(name: "Str", scope: !12, file: !1, line: 10, type: !27) + !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 32) + !28 = !DIExpression(DW_OP_constu, 4, DW_OP_minus) + !29 = !DILocation(line: 11, scope: !12) + !30 = !DILocation(line: 12, scope: !12) + !31 = distinct !DISubprogram(name: "len", linkageName: "len", scope: !1, file: !1, line: 14, type: !32, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) + !32 = !DISubroutineType(types: !33) + !33 = !{!18} + !34 = !DILocation(line: 15, scope: !31) + !35 = !DILocalVariable(name: "Bytes", scope: !31, file: !1, line: 15, type: !18) + !36 = !DILocation(line: 16, scope: !31) + +... +--- +name: fun +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: +liveins: +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 4 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + stackProtector: '' + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: + - { id: 0, type: spill-slot, offset: -8, size: 4, alignment: 4, stack-id: 0, + callee-saved-register: '%esi' } + - { id: 1, type: default, offset: 4, size: 4, alignment: 4, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '' } + - { id: 2, type: default, offset: 0, size: 4, alignment: 4, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '' } +stack: +constants: +body: | + bb.0.entry: + liveins: %esi + + frame-setup PUSH32r killed %esi, implicit-def %esp, implicit %esp + CFI_INSTRUCTION def_cfa_offset 8 + CFI_INSTRUCTION offset %esi, -8 + %esi = MOV32rm %esp, 1, _, 8, _ :: (load 4 from %fixed-stack.2) + DBG_VALUE %esp, 0, !26, !10, debug-location !25 + DBG_VALUE %esp, 0, !23, !11, debug-location !25 + CALLpcrel32 @getString, csr_32, implicit %esp, implicit-def %esp, implicit-def %eax, debug-location !29 + %ecx = MOV32rm %eax, 1, _, 0, _, debug-location !29 :: (dereferenceable load 4 from %ir.1) + %edx = MOV32rm %eax, 1, _, 4, _, debug-location !29 :: (dereferenceable load 4 from %ir.1 + 4) + MOV32mr %esi, 1, _, 0, _, killed %ecx, debug-location !29 :: (store 4 into %ir.0) + MOV32mr %esi, 1, _, 4, _, killed %edx, debug-location !29 :: (store 4 into %ir.0 + 4) + %eax = MOV32rm killed %eax, 1, _, 8, _, debug-location !29 :: (dereferenceable load 4 from %ir.1 + 8) + MOV32mr %esi, 1, _, 8, _, killed %eax, debug-location !29 :: (store 4 into %ir.0 + 8) + %eax = COPY killed %esi, debug-location !30 + %esi = POP32r implicit-def %esp, implicit %esp, debug-location !30 + RET 0, %eax, debug-location !30 + +... +--- +name: len +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: +liveins: +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: + - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '' } + - { id: 1, type: default, offset: 0, size: 4, alignment: 4, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '' } +stack: +constants: +body: | + bb.0.entry: + %eax = MOV32rm %esp, 1, _, 4, _ :: (load 4 from %fixed-stack.1) + %eax = MOV32rm killed %eax, 1, _, 0, _, debug-location !34 :: (load 4 from %ir.0) + DBG_VALUE debug-use %eax, 0, !35, !28, debug-location !34 + %eax = ADD32rm killed %eax, %esp, 1, _, 8, _, implicit-def dead %eflags, debug-location !36 :: (load 4 from %fixed-stack.0) + RET 0, %eax, debug-location !36 + +... Index: llvm/test/DebugInfo/COFF/types-array-advanced.ll =================================================================== --- llvm/test/DebugInfo/COFF/types-array-advanced.ll +++ llvm/test/DebugInfo/COFF/types-array-advanced.ll @@ -50,28 +50,40 @@ ; CHECK: SizeOf: 4 ; CHECK: Name: ; CHECK: } -; CHECK: Array (0x1004) { +; CHECK: Pointer (0x1004) { +; CHECK: TypeLeafKind: LF_POINTER (0x1002) +; CHECK: PointeeType: 0x1003 +; CHECK: PointerAttributes: 0x2A +; CHECK: PtrType: Near32 (0xA) +; CHECK: PtrMode: LValueReference (0x1) +; CHECK: IsFlat: 0 +; CHECK: IsConst: 0 +; CHECK: IsVolatile: 0 +; CHECK: IsUnaligned: 0 +; CHECK: SizeOf: 0 +; CHECK: } +; CHECK: Array (0x1005) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) ; CHECK: ElementType: char (0x70) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 7 ; CHECK: Name: ; CHECK: } -; CHECK: Array (0x1005) { +; CHECK: Array (0x1006) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: 0x1004 +; CHECK: ElementType: 0x1005 ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 35 ; CHECK: Name: ; CHECK: } -; CHECK: Array (0x1006) { +; CHECK: Array (0x1007) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: 0x1005 +; CHECK: ElementType: 0x1006 ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 70 ; CHECK: Name: ; CHECK: } -; CHECK: Struct (0x1007) { +; CHECK: Struct (0x1008) { ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) ; CHECK: MemberCount: 0 ; CHECK: Properties [ (0x280) @@ -85,16 +97,16 @@ ; CHECK: Name: incomplete_struct ; CHECK: LinkageName: .?AUincomplete_struct@@ ; CHECK: } -; CHECK: Array (0x1008) { +; CHECK: Array (0x1009) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: incomplete_struct (0x1007) +; CHECK: ElementType: incomplete_struct (0x1008) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 12 ; CHECK: Name: ; CHECK: } -; CHECK: Pointer (0x1009) { +; CHECK: Pointer (0x100A) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: 0x1008 +; CHECK: PointeeType: 0x1009 ; CHECK: PointerAttributes: 0x800A ; CHECK: PtrType: Near32 (0xA) ; CHECK: PtrMode: Pointer (0x0) @@ -104,8 +116,41 @@ ; CHECK: IsUnaligned: 0 ; CHECK: SizeOf: 4 ; CHECK: } -; -; CHECK: Modifier (0x100E) { +; CHECK: FieldList (0x100B) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: TypeLeafKind: LF_MEMBER (0x150D) +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: int (0x74) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: s1 +; CHECK: } +; CHECK: } +; CHECK: Struct (0x100C) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 1 +; CHECK: Properties [ (0x200) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: (0x100B) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 4 +; CHECK: Name: incomplete_struct +; CHECK: LinkageName: .?AUincomplete_struct@@ +; CHECK: } +; CHECK: StringId (0x100D) { +; CHECK: TypeLeafKind: LF_STRING_ID (0x1605) +; CHECK: Id: 0x0 +; CHECK: StringData: \t.cpp +; CHECK: } +; CHECK: UdtSourceLine (0x100E) { +; CHECK: TypeLeafKind: LF_UDT_SRC_LINE (0x1606) +; CHECK: UDT: incomplete_struct (0x100C) +; CHECK: SourceFile: \t.cpp (0x100D) +; CHECK: LineNumber: 4 +; CHECK: } +; CHECK: Modifier (0x100F) { ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) ; CHECK: ModifiedType: int (0x74) ; CHECK: Modifiers [ (0x3) @@ -113,12 +158,12 @@ ; CHECK: Volatile (0x2) ; CHECK: ] ; CHECK: } -; CHECK: Array (0x100F) { +; CHECK: Array (0x1010) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: const volatile int (0x100E) +; CHECK: ElementType: const volatile int (0x100F) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 16 -; CHECK: Name: +; CHECK: Name: ; CHECK: } ; CHECK: ]