474 lines · cpp
1// RUN: %clang_cc1 -fno-rtti -triple i686-pc-win32 -fms-extensions -fdump-record-layouts -fsyntax-only %s 2>/dev/null \2// RUN: | FileCheck %s --strict-whitespace3// RUN: %clang_cc1 -fno-rtti -triple x86_64-pc-win32 -fms-extensions -fdump-record-layouts -fsyntax-only %s 2>/dev/null \4// RUN: | FileCheck %s -check-prefix CHECK-X64 --strict-whitespace5 6extern "C" int printf(const char *fmt, ...);7__declspec(align(4096)) char buffer[4096];8 9struct AT {};10 11struct V : AT {12 char c;13 V() {14 printf("V - this: %d\n", (int)((char*)this - buffer));15 }16};17 18struct AT0 {19 union { struct { int a; AT t; } y; int b; } x;20 char c;21 AT0() {22 printf("AT0 - this: %d\n", (int)((char*)this - buffer));23 }24};25 26struct AT1 : V {27 int a;28 AT1() {29 printf("AT1 - this: %d\n", (int)((char*)this - buffer));30 }31};32 33struct AT2 {34 AT0 t;35 char AT2FieldName0;36 AT2() {37 printf("AT2 - this: %d\n", (int)((char*)this - buffer));38 printf("AT2 - Fiel: %d\n", (int)((char*)&AT2FieldName0 - buffer));39 }40};41 42struct AT3 : AT2, AT1 {43 AT3() {44 printf("AT3 - this: %d\n", (int)((char*)this - buffer));45 }46};47 48// CHECK-LABEL: 0 | struct AT3{{$}}49// CHECK-NEXT: 0 | struct AT2 (base)50// CHECK-NEXT: 0 | struct AT0 t51// CHECK-NEXT: 0 | union AT0::(unnamed at {{.*}} x52// CHECK-NEXT: 0 | struct AT0::(anonymous union)::(unnamed at {{.*}} y53// CHECK-NEXT: 0 | int a54// CHECK-NEXT: 4 | struct AT t (empty)55// CHECK: 0 | int b56// CHECK: 8 | char c57// CHECK: 12 | char AT2FieldName058// CHECK-NEXT: 20 | struct AT1 (base)59// CHECK-NEXT: 20 | struct V (base)60// CHECK-NEXT: 20 | struct AT (base) (empty)61// CHECK-NEXT: 20 | char c62// CHECK-NEXT: 24 | int a63// CHECK-NEXT: | [sizeof=28, align=464// CHECK-NEXT: | nvsize=28, nvalign=4]65// CHECK-X64-LABEL: 0 | struct AT3{{$}}66// CHECK-X64-NEXT: 0 | struct AT2 (base)67// CHECK-X64-NEXT: 0 | struct AT0 t68// CHECK-X64-NEXT: 0 | union AT0::(unnamed at {{.*}} x69// CHECK-X64-NEXT: 0 | struct AT0::(anonymous union)::(unnamed at {{.*}} y70// CHECK-X64-NEXT: 0 | int a71// CHECK-X64-NEXT: 4 | struct AT t (empty)72// CHECK-X64: 0 | int b73// CHECK-X64: 8 | char c74// CHECK-X64: 12 | char AT2FieldName075// CHECK-X64-NEXT: 20 | struct AT1 (base)76// CHECK-X64-NEXT: 20 | struct V (base)77// CHECK-X64-NEXT: 20 | struct AT (base) (empty)78// CHECK-X64-NEXT: 20 | char c79// CHECK-X64-NEXT: 24 | int a80// CHECK-X64-NEXT: | [sizeof=28, align=481// CHECK-X64-NEXT: | nvsize=28, nvalign=4]82 83struct BT0 {84 BT0() {85 printf("BT0 - this: %d\n", (int)((char*)this - buffer));86 }87};88 89struct BT2 : BT0 {90 char BT2FieldName0;91 BT2() {92 printf("BT2 - this: %d\n", (int)((char*)this - buffer));93 printf("BT2 - Fiel: %d\n", (int)((char*)&BT2FieldName0 - buffer));94 }95};96 97struct BT3 : BT0, BT2 {98 BT3() {99 printf("BT3 - this: %d\n", (int)((char*)this - buffer));100 }101};102 103// CHECK-LABEL: 0 | struct BT3{{$}}104// CHECK-NEXT: 0 | struct BT0 (base) (empty)105// CHECK-NEXT: 1 | struct BT2 (base)106// CHECK-NEXT: 1 | struct BT0 (base) (empty)107// CHECK-NEXT: 1 | char BT2FieldName0108// CHECK-NEXT: | [sizeof=2, align=1109// CHECK-NEXT: | nvsize=2, nvalign=1]110// CHECK-X64-LABEL: 0 | struct BT3{{$}}111// CHECK-X64-NEXT: 0 | struct BT0 (base) (empty)112// CHECK-X64-NEXT: 1 | struct BT2 (base)113// CHECK-X64-NEXT: 1 | struct BT0 (base) (empty)114// CHECK-X64-NEXT: 1 | char BT2FieldName0115// CHECK-X64-NEXT: | [sizeof=2, align=1116// CHECK-X64-NEXT: | nvsize=2, nvalign=1]117 118struct T0 : AT {119 T0() {120 printf("T0 (this) : %d\n", (int)((char*)this - buffer));121 }122};123 124struct T1 : T0 {125 char a;126 T1() {127 printf("T1 (this) : %d\n", (int)((char*)this - buffer));128 printf("T1 (fiel) : %d\n", (int)((char*)&a - buffer));129 }130};131 132struct T2 : AT {133 char a;134 T2() {135 printf("T2 (this) : %d\n", (int)((char*)this - buffer));136 printf("T2 (fiel) : %d\n", (int)((char*)&a - buffer));137 }138};139 140struct __declspec(align(1)) T3 : virtual T1, virtual T2 {141 T3() {142 printf("T3 (this) : %d\n", (int)((char*)this - buffer));143 }144};145 146// CHECK-LABEL: 0 | struct T3{{$}}147// CHECK-NEXT: 0 | (T3 vbtable pointer)148// CHECK-NEXT: 4 | struct T1 (virtual base)149// CHECK-NEXT: 4 | struct T0 (base) (empty)150// CHECK-NEXT: 4 | struct AT (base) (empty)151// CHECK-NEXT: 4 | char a152// CHECK-NEXT: 12 | struct T2 (virtual base)153// CHECK-NEXT: 12 | struct AT (base) (empty)154// CHECK-NEXT: 12 | char a155// CHECK-NEXT: | [sizeof=16, align=4156// CHECK-NEXT: | nvsize=4, nvalign=4]157// CHECK-X64-LABEL: 0 | struct T3{{$}}158// CHECK-X64-NEXT: 0 | (T3 vbtable pointer)159// CHECK-X64-NEXT: 8 | struct T1 (virtual base)160// CHECK-X64-NEXT: 8 | struct T0 (base) (empty)161// CHECK-X64-NEXT: 8 | struct AT (base) (empty)162// CHECK-X64-NEXT: 8 | char a163// CHECK-X64-NEXT: 16 | struct T2 (virtual base)164// CHECK-X64-NEXT: 16 | struct AT (base) (empty)165// CHECK-X64-NEXT: 16 | char a166// CHECK-X64-NEXT: | [sizeof=24, align=8167// CHECK-X64-NEXT: | nvsize=8, nvalign=8]168 169struct B {};170struct C { int a; };171struct D : B, virtual C { B b; };172struct E : D, B {};173// CHECK-LABEL: 0 | struct E{{$}}174// CHECK-NEXT: 0 | struct D (base)175// CHECK-NEXT: 4 | struct B (base) (empty)176// CHECK-NEXT: 0 | (D vbtable pointer)177// CHECK-NEXT: 4 | struct B b (empty)178// CHECK: 8 | struct B (base) (empty)179// CHECK-NEXT: 8 | struct C (virtual base)180// CHECK-NEXT: 8 | int a181// CHECK-NEXT: | [sizeof=12, align=4182// CHECK-NEXT: | nvsize=8, nvalign=4]183// CHECK-X64-LABEL: 0 | struct E{{$}}184// CHECK-X64-NEXT: 0 | struct D (base)185// CHECK-X64-NEXT: 8 | struct B (base) (empty)186// CHECK-X64-NEXT: 0 | (D vbtable pointer)187// CHECK-X64-NEXT: 8 | struct B b (empty)188// CHECK-X64: 16 | struct B (base) (empty)189// CHECK-X64-NEXT: 16 | struct C (virtual base)190// CHECK-X64-NEXT: 16 | int a191// CHECK-X64-NEXT: | [sizeof=24, align=8192// CHECK-X64-NEXT: | nvsize=16, nvalign=8]193 194struct F : virtual D, virtual B {};195// CHECK-LABEL: 0 | struct F{{$}}196// CHECK-NEXT: 0 | (F vbtable pointer)197// CHECK-NEXT: 4 | struct C (virtual base)198// CHECK-NEXT: 4 | int a199// CHECK-NEXT: 8 | struct D (virtual base)200// CHECK-NEXT: 12 | struct B (base) (empty)201// CHECK-NEXT: 8 | (D vbtable pointer)202// CHECK-NEXT: 12 | struct B b (empty)203// CHECK: 16 | struct B (virtual base) (empty)204// CHECK-NEXT: | [sizeof=16, align=4205// CHECK-NEXT: | nvsize=4, nvalign=4]206// CHECK-X64-LABEL: 0 | struct F{{$}}207// CHECK-X64-NEXT: 0 | (F vbtable pointer)208// CHECK-X64-NEXT: 8 | struct C (virtual base)209// CHECK-X64-NEXT: 8 | int a210// CHECK-X64-NEXT: 16 | struct D (virtual base)211// CHECK-X64-NEXT: 24 | struct B (base) (empty)212// CHECK-X64-NEXT: 16 | (D vbtable pointer)213// CHECK-X64-NEXT: 24 | struct B b (empty)214// CHECK-X64: 32 | struct B (virtual base) (empty)215// CHECK-X64-NEXT: | [sizeof=32, align=8216// CHECK-X64-NEXT: | nvsize=8, nvalign=8]217 218struct JC0 {219 JC0() { printf("JC0 : %d\n", (int)((char*)this - buffer)); }220};221struct JC1 : JC0 {222 virtual void f() {}223 JC1() { printf("JC1 : %d\n", (int)((char*)this - buffer)); }224};225struct JC2 : JC1 {226 JC2() { printf("JC2 : %d\n", (int)((char*)this - buffer)); }227};228struct JC4 : JC1, JC2 {229 JC4() { printf("JC4 : %d\n", (int)((char*)this - buffer)); }230};231 232// CHECK-LABEL: 0 | struct JC4{{$}}233// CHECK-NEXT: 0 | struct JC1 (primary base)234// CHECK-NEXT: 0 | (JC1 vftable pointer)235// CHECK-NEXT: 4 | struct JC0 (base) (empty)236// CHECK-NEXT: 8 | struct JC2 (base)237// CHECK-NEXT: 8 | struct JC1 (primary base)238// CHECK-NEXT: 8 | (JC1 vftable pointer)239// CHECK-NEXT: 12 | struct JC0 (base) (empty)240// CHECK-NEXT: | [sizeof=12, align=4241// CHECK-NEXT: | nvsize=12, nvalign=4]242// CHECK-X64-LABEL: 0 | struct JC4{{$}}243// CHECK-X64-NEXT: 0 | struct JC1 (primary base)244// CHECK-X64-NEXT: 0 | (JC1 vftable pointer)245// CHECK-X64-NEXT: 8 | struct JC0 (base) (empty)246// CHECK-X64-NEXT: 16 | struct JC2 (base)247// CHECK-X64-NEXT: 16 | struct JC1 (primary base)248// CHECK-X64-NEXT: 16 | (JC1 vftable pointer)249// CHECK-X64-NEXT: 24 | struct JC0 (base) (empty)250// CHECK-X64-NEXT: | [sizeof=24, align=8251// CHECK-X64-NEXT: | nvsize=24, nvalign=8]252 253struct RA {};254struct RB { char c; };255struct RV {};256struct RW { char c; };257struct RY { RY() { printf("%Id\n", (char*)this - buffer); } };258struct RX0 : RB, RA {};259struct RX1 : RA, RB {};260struct RX2 : RA { char a; };261struct RX3 : RA { RB a; };262struct RX4 { RA a; char b; };263struct RX5 { RA a; RB b; };264struct RX6 : virtual RV { RB a; };265struct RX7 : virtual RW { RA a; };266struct RX8 : RA, virtual RW {};267 268struct RZ0 : RX0, RY {};269// CHECK-LABEL: 0 | struct RZ0{{$}}270// CHECK-NEXT: 0 | struct RX0 (base)271// CHECK-NEXT: 0 | struct RB (base)272// CHECK-NEXT: 0 | char c273// CHECK-NEXT: 1 | struct RA (base) (empty)274// CHECK-NEXT: 2 | struct RY (base) (empty)275// CHECK-NEXT: | [sizeof=2, align=1276// CHECK-NEXT: | nvsize=2, nvalign=1]277// CHECK-X64-LABEL: 0 | struct RZ0{{$}}278// CHECK-X64-NEXT: 0 | struct RX0 (base)279// CHECK-X64-NEXT: 0 | struct RB (base)280// CHECK-X64-NEXT: 0 | char c281// CHECK-X64-NEXT: 1 | struct RA (base) (empty)282// CHECK-X64-NEXT: 2 | struct RY (base) (empty)283// CHECK-X64-NEXT: | [sizeof=2, align=1284// CHECK-X64-NEXT: | nvsize=2, nvalign=1]285 286struct RZ1 : RX1, RY {};287// CHECK-LABEL: 0 | struct RZ1{{$}}288// CHECK-NEXT: 0 | struct RX1 (base)289// CHECK-NEXT: 0 | struct RA (base) (empty)290// CHECK-NEXT: 0 | struct RB (base)291// CHECK-NEXT: 0 | char c292// CHECK-NEXT: 1 | struct RY (base) (empty)293// CHECK-NEXT: | [sizeof=1, align=1294// CHECK-NEXT: | nvsize=1, nvalign=1]295// CHECK-X64-LABEL: 0 | struct RZ1{{$}}296// CHECK-X64-NEXT: 0 | struct RX1 (base)297// CHECK-X64-NEXT: 0 | struct RA (base) (empty)298// CHECK-X64-NEXT: 0 | struct RB (base)299// CHECK-X64-NEXT: 0 | char c300// CHECK-X64-NEXT: 1 | struct RY (base) (empty)301// CHECK-X64-NEXT: | [sizeof=1, align=1302// CHECK-X64-NEXT: | nvsize=1, nvalign=1]303 304struct RZ2 : RX2, RY {};305// CHECK-LABEL: 0 | struct RZ2{{$}}306// CHECK-NEXT: 0 | struct RX2 (base)307// CHECK-NEXT: 0 | struct RA (base) (empty)308// CHECK-NEXT: 0 | char a309// CHECK-NEXT: 2 | struct RY (base) (empty)310// CHECK-NEXT: | [sizeof=2, align=1311// CHECK-NEXT: | nvsize=2, nvalign=1]312// CHECK-X64-LABEL: 0 | struct RZ2{{$}}313// CHECK-X64-NEXT: 0 | struct RX2 (base)314// CHECK-X64-NEXT: 0 | struct RA (base) (empty)315// CHECK-X64-NEXT: 0 | char a316// CHECK-X64-NEXT: 2 | struct RY (base) (empty)317// CHECK-X64-NEXT: | [sizeof=2, align=1318// CHECK-X64-NEXT: | nvsize=2, nvalign=1]319 320struct RZ3 : RX3, RY {};321// CHECK-LABEL: 0 | struct RZ3{{$}}322// CHECK-NEXT: 0 | struct RX3 (base)323// CHECK-NEXT: 0 | struct RA (base) (empty)324// CHECK-NEXT: 0 | struct RB a325// CHECK-NEXT: 0 | char c326// CHECK-NEXT: 1 | struct RY (base) (empty)327// CHECK-NEXT: | [sizeof=1, align=1328// CHECK-NEXT: | nvsize=1, nvalign=1]329// CHECK-X64-LABEL: 0 | struct RZ3{{$}}330// CHECK-X64-NEXT: 0 | struct RX3 (base)331// CHECK-X64-NEXT: 0 | struct RA (base) (empty)332// CHECK-X64-NEXT: 0 | struct RB a333// CHECK-X64-NEXT: 0 | char c334// CHECK-X64-NEXT: 1 | struct RY (base) (empty)335// CHECK-X64-NEXT: | [sizeof=1, align=1336// CHECK-X64-NEXT: | nvsize=1, nvalign=1]337 338struct RZ4 : RX4, RY {};339// CHECK-LABEL: 0 | struct RZ4{{$}}340// CHECK-NEXT: 0 | struct RX4 (base)341// CHECK-NEXT: 0 | struct RA a (empty)342// CHECK-NEXT: 1 | char b343// CHECK-NEXT: 3 | struct RY (base) (empty)344// CHECK-NEXT: | [sizeof=3, align=1345// CHECK-NEXT: | nvsize=3, nvalign=1]346// CHECK-X64-LABEL: 0 | struct RZ4{{$}}347// CHECK-X64-NEXT: 0 | struct RX4 (base)348// CHECK-X64-NEXT: 0 | struct RA a (empty)349// CHECK-X64-NEXT: 1 | char b350// CHECK-X64-NEXT: 3 | struct RY (base) (empty)351// CHECK-X64-NEXT: | [sizeof=3, align=1352// CHECK-X64-NEXT: | nvsize=3, nvalign=1]353 354struct RZ5 : RX5, RY {};355// CHECK-LABEL: 0 | struct RZ5{{$}}356// CHECK-NEXT: 0 | struct RX5 (base)357// CHECK-NEXT: 0 | struct RA a (empty)358// CHECK-NEXT: 1 | struct RB b359// CHECK-NEXT: 1 | char c360// CHECK-NEXT: 2 | struct RY (base) (empty)361// CHECK-NEXT: | [sizeof=2, align=1362// CHECK-NEXT: | nvsize=2, nvalign=1]363// CHECK-X64-LABEL: 0 | struct RZ5{{$}}364// CHECK-X64-NEXT: 0 | struct RX5 (base)365// CHECK-X64-NEXT: 0 | struct RA a (empty)366// CHECK-X64-NEXT: 1 | struct RB b367// CHECK-X64-NEXT: 1 | char c368// CHECK-X64-NEXT: 2 | struct RY (base) (empty)369// CHECK-X64-NEXT: | [sizeof=2, align=1370// CHECK-X64-NEXT: | nvsize=2, nvalign=1]371 372struct RZ6 : RX6, RY {};373// CHECK-LABEL: 0 | struct RZ6{{$}}374// CHECK-NEXT: 0 | struct RX6 (base)375// CHECK-NEXT: 0 | (RX6 vbtable pointer)376// CHECK-NEXT: 4 | struct RB a377// CHECK-NEXT: 4 | char c378// CHECK-NEXT: 9 | struct RY (base) (empty)379// CHECK-NEXT: 12 | struct RV (virtual base) (empty)380// CHECK-NEXT: | [sizeof=12, align=4381// CHECK-NEXT: | nvsize=12, nvalign=4]382// CHECK-X64-LABEL: 0 | struct RZ6{{$}}383// CHECK-X64-NEXT: 0 | struct RX6 (base)384// CHECK-X64-NEXT: 0 | (RX6 vbtable pointer)385// CHECK-X64-NEXT: 8 | struct RB a386// CHECK-X64-NEXT: 8 | char c387// CHECK-X64-NEXT: 17 | struct RY (base) (empty)388// CHECK-X64-NEXT: 24 | struct RV (virtual base) (empty)389// CHECK-X64-NEXT: | [sizeof=24, align=8390// CHECK-X64-NEXT: | nvsize=24, nvalign=8]391 392struct RZ7 : RX7, RY {};393// CHECK-LABEL: 0 | struct RZ7{{$}}394// CHECK-NEXT: 0 | struct RX7 (base)395// CHECK-NEXT: 0 | (RX7 vbtable pointer)396// CHECK-NEXT: 4 | struct RA a (empty)397// CHECK-NEXT: 8 | struct RY (base) (empty)398// CHECK-NEXT: 8 | struct RW (virtual base)399// CHECK-NEXT: 8 | char c400// CHECK-NEXT: | [sizeof=9, align=4401// CHECK-NEXT: | nvsize=8, nvalign=4]402// CHECK-X64-LABEL: 0 | struct RZ7{{$}}403// CHECK-X64-NEXT: 0 | struct RX7 (base)404// CHECK-X64-NEXT: 0 | (RX7 vbtable pointer)405// CHECK-X64-NEXT: 8 | struct RA a (empty)406// CHECK-X64-NEXT: 16 | struct RY (base) (empty)407// CHECK-X64-NEXT: 16 | struct RW (virtual base)408// CHECK-X64-NEXT: 16 | char c409// CHECK-X64-NEXT: | [sizeof=24, align=8410// CHECK-X64-NEXT: | nvsize=16, nvalign=8]411 412struct RZ8 : RX8, RY {};413// CHECK-LABEL: 0 | struct RZ8{{$}}414// CHECK-NEXT: 0 | struct RX8 (base)415// CHECK-NEXT: 4 | struct RA (base) (empty)416// CHECK-NEXT: 0 | (RX8 vbtable pointer)417// CHECK-NEXT: 4 | struct RY (base) (empty)418// CHECK-NEXT: 4 | struct RW (virtual base)419// CHECK-NEXT: 4 | char c420// CHECK-NEXT: | [sizeof=5, align=4421// CHECK-NEXT: | nvsize=4, nvalign=4]422// CHECK-X64-LABEL: 0 | struct RZ8{{$}}423// CHECK-X64-NEXT: 0 | struct RX8 (base)424// CHECK-X64-NEXT: 8 | struct RA (base) (empty)425// CHECK-X64-NEXT: 0 | (RX8 vbtable pointer)426// CHECK-X64-NEXT: 8 | struct RY (base) (empty)427// CHECK-X64-NEXT: 8 | struct RW (virtual base)428// CHECK-X64-NEXT: 8 | char c429// CHECK-X64-NEXT: | [sizeof=16, align=8430// CHECK-X64-NEXT: | nvsize=8, nvalign=8]431 432struct JA {};433struct JB {};434struct JC : JA { virtual void f() {} };435struct JD : virtual JB, virtual JC { virtual void f() {} JD() {} };436 437// CHECK-LABEL: 0 | struct JD{{$}}438// CHECK-NEXT: 0 | (JD vbtable pointer)439// CHECK-NEXT: 4 | struct JB (virtual base) (empty)440// CHECK-NEXT: 4 | (vtordisp for vbase JC)441// CHECK-NEXT: 8 | struct JC (virtual base)442// CHECK-NEXT: 8 | (JC vftable pointer)443// CHECK-NEXT: 12 | struct JA (base) (empty)444// CHECK-NEXT: | [sizeof=12, align=4445// CHECK-NEXT: | nvsize=4, nvalign=4]446// CHECK-X64-LABEL: 0 | struct JD{{$}}447// CHECK-X64-NEXT: 0 | (JD vbtable pointer)448// CHECK-X64-NEXT: 8 | struct JB (virtual base) (empty)449// CHECK-X64-NEXT: 12 | (vtordisp for vbase JC)450// CHECK-X64-NEXT: 16 | struct JC (virtual base)451// CHECK-X64-NEXT: 16 | (JC vftable pointer)452// CHECK-X64-NEXT: 24 | struct JA (base) (empty)453// CHECK-X64-NEXT: | [sizeof=24, align=8454// CHECK-X64-NEXT: | nvsize=8, nvalign=8]455 456int a[457sizeof(AT3) +458sizeof(BT3) +459sizeof(T3) +460sizeof(E) +461sizeof(F) +462sizeof(JC4) +463sizeof(RZ0) +464sizeof(RZ1) +465sizeof(RZ2) +466sizeof(RZ3) +467sizeof(RZ4) +468sizeof(RZ5) +469sizeof(RZ6) +470sizeof(RZ7) +471sizeof(RZ8) +472sizeof(JD) +4730];474