1 ; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s 2 ; 3 ; Verify CodeView emission does not emit forward references for unnamed 4 ; structs/unions. If a forward reference is emitted for an unnamed composite 5 ; type then Visual Studio will not be able to display the value. 6 ; 7 ; Previous values displayed by Visual Studio: 8 ; local.unnamed_struct {...} 9 ; local.unnamed_union {...} 10 ; 11 ; New values displayed by Visual Studio: 12 ; local.unnamed_struct {m3=66 'B' } 13 ; local.unnamed_union {m1=65 m2=65 'A' } 14 ; 15 ; The reproducer: 16 ; $ cat unnamed.c 17 ; struct named_struct { 18 ; int id; 19 ; union { 20 ; int m1; 21 ; char m2; 22 ; } unnamed_union; 23 ; struct { 24 ; char m3; 25 ; } unnamed_struct; 26 ; }; 27 ; 28 ; int main() 29 ; { 30 ; struct named_struct local; 31 ; 32 ; local.id = 1; 33 ; local.unnamed_union.m1 = 65; 34 ; local.unnamed_struct.m3 = 'B'; 35 ; 36 ; return 0; 37 ; } 38 ; 39 ; To regenerate the IR below: 40 ; $ clang unnamed.c -S -emit-llvm -g -gcodeview 41 ; 42 ; CHECK: FieldList ([[UnnamedUnionFieldList:.*]]) { 43 ; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) 44 ; CHECK-NEXT: DataMember { 45 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 46 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 47 ; CHECK-NEXT: Type: int (0x74) 48 ; CHECK-NEXT: FieldOffset: 0x0 49 ; CHECK-NEXT: Name: m1 50 ; CHECK-NEXT: } 51 ; CHECK-NEXT: DataMember { 52 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 53 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 54 ; CHECK-NEXT: Type: char (0x70) 55 ; CHECK-NEXT: FieldOffset: 0x0 56 ; CHECK-NEXT: Name: m2 57 ; CHECK-NEXT: } 58 ; CHECK-NEXT: } 59 ; CHECK: Union ([[UnnamedUnion:.*]]) { 60 ; CHECK-NEXT: TypeLeafKind: LF_UNION (0x1506) 61 ; CHECK-NEXT: MemberCount: 2 62 ; CHECK-NEXT: Properties [ (0x408) 63 ; CHECK-NEXT: Nested (0x8) 64 ; CHECK-NEXT: Sealed (0x400) 65 ; CHECK-NEXT: ] 66 ; CHECK-NEXT: FieldList: <field list> ([[UnnamedUnionFieldList]]) 67 ; CHECK-NEXT: SizeOf: 4 68 ; CHECK-NEXT: Name: named_struct::<unnamed-tag> 69 ; CHECK-NEXT: } 70 ; CHECK: FieldList ([[UnnamedStructFieldList:.*]]) { 71 ; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) 72 ; CHECK-NEXT: DataMember { 73 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 74 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 75 ; CHECK-NEXT: Type: char (0x70) 76 ; CHECK-NEXT: FieldOffset: 0x0 77 ; CHECK-NEXT: Name: m3 78 ; CHECK-NEXT: } 79 ; CHECK-NEXT: } 80 ; CHECK: Struct ([[UnnamedStruct:.*]]) { 81 ; CHECK-NEXT: TypeLeafKind: LF_STRUCTURE (0x1505) 82 ; CHECK-NEXT: MemberCount: 1 83 ; CHECK-NEXT: Properties [ (0x8) 84 ; CHECK-NEXT: Nested (0x8) 85 ; CHECK-NEXT: ] 86 ; CHECK-NEXT: FieldList: <field list> ([[UnnamedStructFieldList]]) 87 ; CHECK-NEXT: DerivedFrom: 0x0 88 ; CHECK-NEXT: VShape: 0x0 89 ; CHECK-NEXT: SizeOf: 1 90 ; CHECK-NEXT: Name: named_struct::<unnamed-tag> 91 ; CHECK-NEXT: } 92 ; CHECK: FieldList ([[NamedStructFieldList:.*]]) { 93 ; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) 94 ; CHECK-NEXT: DataMember { 95 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 96 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 97 ; CHECK-NEXT: Type: int (0x74) 98 ; CHECK-NEXT: FieldOffset: 0x0 99 ; CHECK-NEXT: Name: id 100 ; CHECK-NEXT: } 101 ; CHECK-NEXT: DataMember { 102 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 103 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 104 ; CHECK-NEXT: Type: named_struct::<unnamed-tag> ([[UnnamedUnion]]) 105 ; CHECK-NEXT: FieldOffset: 0x4 106 ; CHECK-NEXT: Name: unnamed_union 107 ; CHECK-NEXT: } 108 ; CHECK-NEXT: DataMember { 109 ; CHECK-NEXT: TypeLeafKind: LF_MEMBER (0x150D) 110 ; CHECK-NEXT: AccessSpecifier: Public (0x3) 111 ; CHECK-NEXT: Type: named_struct::<unnamed-tag> ([[UnnamedStruct]]) 112 ; CHECK-NEXT: FieldOffset: 0x8 113 ; CHECK-NEXT: Name: unnamed_struct 114 ; CHECK-NEXT: } 115 ; CHECK-NEXT: } 116 ; CHECK: Struct ({{.*}}) { 117 ; CHECK-NEXT: TypeLeafKind: LF_STRUCTURE (0x1505) 118 ; CHECK-NEXT: MemberCount: 3 119 ; CHECK-NEXT: Properties [ (0x0) 120 ; CHECK-NEXT: ] 121 ; CHECK-NEXT: FieldList: <field list> ([[NamedStructFieldList]]) 122 ; CHECK-NEXT: DerivedFrom: 0x0 123 ; CHECK-NEXT: VShape: 0x0 124 ; CHECK-NEXT: SizeOf: 12 125 ; CHECK-NEXT: Name: named_struct 126 ; CHECK-NEXT: } 127 128 ; ModuleID = 'unnamed.c' 129 source_filename = "unnamed.c" 130 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" 131 target triple = "x86_64-pc-windows-msvc19.0.24210" 132 133 %struct.named_struct = type { i32, %union.anon, %struct.anon } 134 %union.anon = type { i32 } 135 %struct.anon = type { i8 } 136 137 ; Function Attrs: noinline nounwind uwtable 138 define i32 @main() #0 !dbg !7 { 139 entry: 140 %retval = alloca i32, align 4 141 %local = alloca %struct.named_struct, align 4 142 store i32 0, i32* %retval, align 4 143 call void @llvm.dbg.declare(metadata %struct.named_struct* %local, metadata !11, metadata !25), !dbg !26 144 %id = getelementptr inbounds %struct.named_struct, %struct.named_struct* %local, i32 0, i32 0, !dbg !27 145 store i32 1, i32* %id, align 4, !dbg !28 146 %unnamed_union = getelementptr inbounds %struct.named_struct, %struct.named_struct* %local, i32 0, i32 1, !dbg !29 147 %m1 = bitcast %union.anon* %unnamed_union to i32*, !dbg !30 148 store i32 65, i32* %m1, align 4, !dbg !31 149 %unnamed_struct = getelementptr inbounds %struct.named_struct, %struct.named_struct* %local, i32 0, i32 2, !dbg !32 150 %m3 = getelementptr inbounds %struct.anon, %struct.anon* %unnamed_struct, i32 0, i32 0, !dbg !33 151 store i8 66, i8* %m3, align 4, !dbg !34 152 ret i32 0, !dbg !35 153 } 154 155 ; Function Attrs: nounwind readnone 156 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 157 158 attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } 159 attributes #1 = { nounwind readnone } 160 161 !llvm.dbg.cu = !{!0} 162 !llvm.module.flags = !{!3, !4, !5} 163 !llvm.ident = !{!6} 164 165 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (trunk)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) 166 !1 = !DIFile(filename: "unnamed.c", directory: "C:\5Cpath\5Cto\5Cdirectory", checksumkind: CSK_MD5, checksum: "a1874da39665a126d6949d929fbd4818") 167 !2 = !{} 168 !3 = !{i32 2, !"CodeView", i32 1} 169 !4 = !{i32 2, !"Debug Info Version", i32 3} 170 !5 = !{i32 1, !"PIC Level", i32 2} 171 !6 = !{!"clang version 5.0.0 (trunk)"} 172 !7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 12, type: !8, isLocal: false, isDefinition: true, scopeLine: 13, isOptimized: false, unit: !0, retainedNodes: !2) 173 !8 = !DISubroutineType(types: !9) 174 !9 = !{!10} 175 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 176 !11 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 14, type: !12) 177 !12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "named_struct", file: !1, line: 1, size: 96, elements: !13) 178 !13 = !{!14, !15, !21} 179 !14 = !DIDerivedType(tag: DW_TAG_member, name: "id", scope: !12, file: !1, line: 2, baseType: !10, size: 32) 180 !15 = !DIDerivedType(tag: DW_TAG_member, name: "unnamed_union", scope: !12, file: !1, line: 6, baseType: !16, size: 32, offset: 32) 181 !16 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !12, file: !1, line: 3, size: 32, elements: !17) 182 !17 = !{!18, !19} 183 !18 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !16, file: !1, line: 4, baseType: !10, size: 32) 184 !19 = !DIDerivedType(tag: DW_TAG_member, name: "m2", scope: !16, file: !1, line: 5, baseType: !20, size: 8) 185 !20 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) 186 !21 = !DIDerivedType(tag: DW_TAG_member, name: "unnamed_struct", scope: !12, file: !1, line: 9, baseType: !22, size: 8, offset: 64) 187 !22 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !12, file: !1, line: 7, size: 8, elements: !23) 188 !23 = !{!24} 189 !24 = !DIDerivedType(tag: DW_TAG_member, name: "m3", scope: !22, file: !1, line: 8, baseType: !20, size: 8) 190 !25 = !DIExpression() 191 !26 = !DILocation(line: 14, column: 23, scope: !7) 192 !27 = !DILocation(line: 16, column: 9, scope: !7) 193 !28 = !DILocation(line: 16, column: 12, scope: !7) 194 !29 = !DILocation(line: 17, column: 9, scope: !7) 195 !30 = !DILocation(line: 17, column: 23, scope: !7) 196 !31 = !DILocation(line: 17, column: 26, scope: !7) 197 !32 = !DILocation(line: 18, column: 9, scope: !7) 198 !33 = !DILocation(line: 18, column: 24, scope: !7) 199 !34 = !DILocation(line: 18, column: 27, scope: !7) 200 !35 = !DILocation(line: 20, column: 3, scope: !7) 201