1// RUN: %clang_cc1 -fno-rtti -fms-extensions -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 \ 2// RUN: | FileCheck %s 3// RUN: %clang_cc1 -fno-rtti -fms-extensions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>/dev/null \ 4// RUN: | FileCheck %s -check-prefix CHECK-X64 5 6extern "C" int printf(const char *fmt, ...); 7 8struct B0 { 9 int a; 10 B0() : a(0xf00000B0) {} 11 virtual void f() { printf("B0"); } 12}; 13 14struct __declspec(align(16)) B1 { 15 int a; 16 B1() : a(0xf00000B1) {} 17 virtual void f() { printf("B1"); } 18}; 19 20struct __declspec(align(16)) Align16 {}; 21struct __declspec(align(32)) Align32 {}; 22struct VAlign16 : virtual Align16 {}; 23struct VAlign32 : virtual Align32 {}; 24 25struct A : virtual B0, virtual B1 { 26 int a; 27 A() : a(0xf000000A) {} 28 virtual void f() { printf("A"); } 29 virtual void g() { printf("A"); } 30}; 31 32// CHECK: *** Dumping AST Record Layout 33// CHECK: *** Dumping AST Record Layout 34// CHECK: *** Dumping AST Record Layout 35// CHECK-NEXT: 0 | struct A 36// CHECK-NEXT: 0 | (A vftable pointer) 37// CHECK-NEXT: 4 | (A vbtable pointer) 38// CHECK-NEXT: 8 | int a 39// CHECK-NEXT: 16 | (vtordisp for vbase B0) 40// CHECK-NEXT: 20 | struct B0 (virtual base) 41// CHECK-NEXT: 20 | (B0 vftable pointer) 42// CHECK-NEXT: 24 | int a 43// CHECK-NEXT: 44 | (vtordisp for vbase B1) 44// CHECK-NEXT: 48 | struct B1 (virtual base) 45// CHECK-NEXT: 48 | (B1 vftable pointer) 46// CHECK-NEXT: 52 | int a 47// CHECK-NEXT: | [sizeof=64, align=16 48// CHECK-NEXT: | nvsize=12, nvalign=16] 49// CHECK-X64: *** Dumping AST Record Layout 50// CHECK-X64: *** Dumping AST Record Layout 51// CHECK-X64: *** Dumping AST Record Layout 52// CHECK-X64-NEXT: 0 | struct A 53// CHECK-X64-NEXT: 0 | (A vftable pointer) 54// CHECK-X64-NEXT: 8 | (A vbtable pointer) 55// CHECK-X64-NEXT: 16 | int a 56// CHECK-X64-NEXT: 36 | (vtordisp for vbase B0) 57// CHECK-X64-NEXT: 40 | struct B0 (virtual base) 58// CHECK-X64-NEXT: 40 | (B0 vftable pointer) 59// CHECK-X64-NEXT: 48 | int a 60// CHECK-X64-NEXT: 76 | (vtordisp for vbase B1) 61// CHECK-X64-NEXT: 80 | struct B1 (virtual base) 62// CHECK-X64-NEXT: 80 | (B1 vftable pointer) 63// CHECK-X64-NEXT: 88 | int a 64// CHECK-X64-NEXT: | [sizeof=96, align=16 65// CHECK-X64-NEXT: | nvsize=24, nvalign=16] 66 67struct C : virtual B0, virtual B1, VAlign32 { 68 int a; 69 C() : a(0xf000000C) {} 70 virtual void f() { printf("C"); } 71 virtual void g() { printf("C"); } 72}; 73 74// CHECK: *** Dumping AST Record Layout 75// CHECK: *** Dumping AST Record Layout 76// CHECK: *** Dumping AST Record Layout 77// CHECK-NEXT: 0 | struct C 78// CHECK-NEXT: 0 | (C vftable pointer) 79// CHECK-NEXT: 32 | struct VAlign32 (base) 80// CHECK-NEXT: 32 | (VAlign32 vbtable pointer) 81// CHECK-NEXT: 36 | int a 82// CHECK-NEXT: 64 | (vtordisp for vbase B0) 83// CHECK-NEXT: 68 | struct B0 (virtual base) 84// CHECK-NEXT: 68 | (B0 vftable pointer) 85// CHECK-NEXT: 72 | int a 86// CHECK-NEXT: 108 | (vtordisp for vbase B1) 87// CHECK-NEXT: 112 | struct B1 (virtual base) 88// CHECK-NEXT: 112 | (B1 vftable pointer) 89// CHECK-NEXT: 116 | int a 90// CHECK-NEXT: 128 | struct Align32 (virtual base) (empty) 91// CHECK-NEXT: | [sizeof=128, align=32 92// CHECK-NEXT: | nvsize=64, nvalign=32] 93// CHECK-X64: *** Dumping AST Record Layout 94// CHECK-X64: *** Dumping AST Record Layout 95// CHECK-X64: *** Dumping AST Record Layout 96// CHECK-X64-NEXT: 0 | struct C 97// CHECK-X64-NEXT: 0 | (C vftable pointer) 98// CHECK-X64-NEXT: 32 | struct VAlign32 (base) 99// CHECK-X64-NEXT: 32 | (VAlign32 vbtable pointer) 100// CHECK-X64-NEXT: 40 | int a 101// CHECK-X64-NEXT: 68 | (vtordisp for vbase B0) 102// CHECK-X64-NEXT: 72 | struct B0 (virtual base) 103// CHECK-X64-NEXT: 72 | (B0 vftable pointer) 104// CHECK-X64-NEXT: 80 | int a 105// CHECK-X64-NEXT: 108 | (vtordisp for vbase B1) 106// CHECK-X64-NEXT: 112 | struct B1 (virtual base) 107// CHECK-X64-NEXT: 112 | (B1 vftable pointer) 108// CHECK-X64-NEXT: 120 | int a 109// CHECK-X64-NEXT: 128 | struct Align32 (virtual base) (empty) 110// CHECK-X64-NEXT: | [sizeof=128, align=32 111// CHECK-X64-NEXT: | nvsize=64, nvalign=32] 112 113struct __declspec(align(32)) D : virtual B0, virtual B1 { 114 int a; 115 D() : a(0xf000000D) {} 116 virtual void f() { printf("D"); } 117 virtual void g() { printf("D"); } 118}; 119 120// CHECK: *** Dumping AST Record Layout 121// CHECK-NEXT: 0 | struct D 122// CHECK-NEXT: 0 | (D vftable pointer) 123// CHECK-NEXT: 4 | (D vbtable pointer) 124// CHECK-NEXT: 8 | int a 125// CHECK-NEXT: 32 | (vtordisp for vbase B0) 126// CHECK-NEXT: 36 | struct B0 (virtual base) 127// CHECK-NEXT: 36 | (B0 vftable pointer) 128// CHECK-NEXT: 40 | int a 129// CHECK-NEXT: 76 | (vtordisp for vbase B1) 130// CHECK-NEXT: 80 | struct B1 (virtual base) 131// CHECK-NEXT: 80 | (B1 vftable pointer) 132// CHECK-NEXT: 84 | int a 133// CHECK-NEXT: | [sizeof=96, align=32 134// CHECK-NEXT: | nvsize=12, nvalign=32] 135// CHECK-X64: *** Dumping AST Record Layout 136// CHECK-X64-NEXT: 0 | struct D 137// CHECK-X64-NEXT: 0 | (D vftable pointer) 138// CHECK-X64-NEXT: 8 | (D vbtable pointer) 139// CHECK-X64-NEXT: 16 | int a 140// CHECK-X64-NEXT: 36 | (vtordisp for vbase B0) 141// CHECK-X64-NEXT: 40 | struct B0 (virtual base) 142// CHECK-X64-NEXT: 40 | (B0 vftable pointer) 143// CHECK-X64-NEXT: 48 | int a 144// CHECK-X64-NEXT: 76 | (vtordisp for vbase B1) 145// CHECK-X64-NEXT: 80 | struct B1 (virtual base) 146// CHECK-X64-NEXT: 80 | (B1 vftable pointer) 147// CHECK-X64-NEXT: 88 | int a 148// CHECK-X64-NEXT: | [sizeof=96, align=32 149// CHECK-X64-NEXT: | nvsize=24, nvalign=32] 150 151struct AT { 152 virtual ~AT(){} 153}; 154struct CT : virtual AT { 155 virtual ~CT(); 156}; 157CT::~CT(){} 158 159// CHECK: *** Dumping AST Record Layout 160// CHECK: *** Dumping AST Record Layout 161// CHECK-NEXT: 0 | struct CT 162// CHECK-NEXT: 0 | (CT vbtable pointer) 163// CHECK-NEXT: 4 | struct AT (virtual base) 164// CHECK-NEXT: 4 | (AT vftable pointer) 165// CHECK-NEXT: | [sizeof=8, align=4 166// CHECK-NEXT: | nvsize=4, nvalign=4] 167// CHECK-X64: *** Dumping AST Record Layout 168// CHECK-X64: *** Dumping AST Record Layout 169// CHECK-X64-NEXT: 0 | struct CT 170// CHECK-X64-NEXT: 0 | (CT vbtable pointer) 171// CHECK-X64-NEXT: 8 | struct AT (virtual base) 172// CHECK-X64-NEXT: 8 | (AT vftable pointer) 173// CHECK-X64-NEXT: | [sizeof=16, align=8 174// CHECK-X64-NEXT: | nvsize=8, nvalign=8] 175 176struct XA { 177 XA() { printf("XA"); } 178 long long ll; 179}; 180struct XB : XA { 181 XB() { printf("XB"); } 182 virtual void foo() {} 183 int b; 184}; 185struct XC : virtual XB { 186 XC() { printf("XC"); } 187 virtual void foo() {} 188}; 189 190// CHECK: *** Dumping AST Record Layout 191// CHECK: *** Dumping AST Record Layout 192// CHECK: *** Dumping AST Record Layout 193// CHECK-NEXT: 0 | struct XC 194// CHECK-NEXT: 0 | (XC vbtable pointer) 195// CHECK-NEXT: 4 | (vtordisp for vbase XB) 196// CHECK-NEXT: 8 | struct XB (virtual base) 197// CHECK-NEXT: 8 | (XB vftable pointer) 198// CHECK-NEXT: 16 | struct XA (base) 199// CHECK-NEXT: 16 | long long ll 200// CHECK-NEXT: 24 | int b 201// CHECK-NEXT: | [sizeof=32, align=8 202// CHECK-NEXT: | nvsize=4, nvalign=8] 203// CHECK-X64: *** Dumping AST Record Layout 204// CHECK-X64: *** Dumping AST Record Layout 205// CHECK-X64: *** Dumping AST Record Layout 206// CHECK-X64-NEXT: 0 | struct XC 207// CHECK-X64-NEXT: 0 | (XC vbtable pointer) 208// CHECK-X64-NEXT: 12 | (vtordisp for vbase XB) 209// CHECK-X64-NEXT: 16 | struct XB (virtual base) 210// CHECK-X64-NEXT: 16 | (XB vftable pointer) 211// CHECK-X64-NEXT: 24 | struct XA (base) 212// CHECK-X64-NEXT: 24 | long long ll 213// CHECK-X64-NEXT: 32 | int b 214// CHECK-X64-NEXT: | [sizeof=40, align=8 215// CHECK-X64-NEXT: | nvsize=8, nvalign=8] 216 217namespace pragma_test1 { 218// No overrides means no vtordisps by default. 219struct A { virtual ~A(); virtual void foo(); int a; }; 220struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 221struct C : virtual B { int c; }; 222// CHECK: *** Dumping AST Record Layout 223// CHECK: *** Dumping AST Record Layout 224// CHECK: *** Dumping AST Record Layout 225// CHECK-NEXT: 0 | struct pragma_test1::C 226// CHECK-NEXT: 0 | (C vbtable pointer) 227// CHECK-NEXT: 4 | int c 228// CHECK-NEXT: 8 | struct pragma_test1::A (virtual base) 229// CHECK-NEXT: 8 | (A vftable pointer) 230// CHECK-NEXT: 12 | int a 231// CHECK-NEXT: 16 | struct pragma_test1::B (virtual base) 232// CHECK-NEXT: 16 | (B vftable pointer) 233// CHECK-NEXT: 20 | (B vbtable pointer) 234// CHECK-NEXT: 24 | int b 235// CHECK-NEXT: | [sizeof=28, align=4 236// CHECK-NEXT: | nvsize=8, nvalign=4] 237// CHECK-X64: *** Dumping AST Record Layout 238// CHECK-X64: *** Dumping AST Record Layout 239// CHECK-X64: *** Dumping AST Record Layout 240} 241 242namespace pragma_test2 { 243struct A { virtual ~A(); virtual void foo(); int a; }; 244#pragma vtordisp(push,2) 245struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 246struct C : virtual B { int c; }; 247#pragma vtordisp(pop) 248// CHECK: *** Dumping AST Record Layout 249// CHECK: *** Dumping AST Record Layout 250// CHECK: *** Dumping AST Record Layout 251// CHECK-NEXT: 0 | struct pragma_test2::C 252// CHECK-NEXT: 0 | (C vbtable pointer) 253// CHECK-NEXT: 4 | int c 254// CHECK-NEXT: 8 | (vtordisp for vbase A) 255// CHECK-NEXT: 12 | struct pragma_test2::A (virtual base) 256// CHECK-NEXT: 12 | (A vftable pointer) 257// CHECK-NEXT: 16 | int a 258// By adding a virtual method and vftable to B, now we need a vtordisp. 259// CHECK-NEXT: 20 | (vtordisp for vbase B) 260// CHECK-NEXT: 24 | struct pragma_test2::B (virtual base) 261// CHECK-NEXT: 24 | (B vftable pointer) 262// CHECK-NEXT: 28 | (B vbtable pointer) 263// CHECK-NEXT: 32 | int b 264// CHECK-NEXT: | [sizeof=36, align=4 265// CHECK-NEXT: | nvsize=8, nvalign=4] 266// CHECK-X64: *** Dumping AST Record Layout 267// CHECK-X64: *** Dumping AST Record Layout 268// CHECK-X64: *** Dumping AST Record Layout 269} 270 271namespace pragma_test3 { 272struct A { virtual ~A(); virtual void foo(); int a; }; 273#pragma vtordisp(push,2) 274struct B : virtual A { virtual ~B(); virtual void foo(); int b; }; 275struct C : virtual B { int c; }; 276#pragma vtordisp(pop) 277// CHECK: *** Dumping AST Record Layout 278// CHECK: *** Dumping AST Record Layout 279// CHECK: *** Dumping AST Record Layout 280// CHECK-NEXT: 0 | struct pragma_test3::C 281// CHECK-NEXT: 0 | (C vbtable pointer) 282// CHECK-NEXT: 4 | int c 283// CHECK-NEXT: 8 | (vtordisp for vbase A) 284// CHECK-NEXT: 12 | struct pragma_test3::A (virtual base) 285// CHECK-NEXT: 12 | (A vftable pointer) 286// CHECK-NEXT: 16 | int a 287// No vtordisp before B! It doesn't have its own vftable. 288// CHECK-NEXT: 20 | struct pragma_test3::B (virtual base) 289// CHECK-NEXT: 20 | (B vbtable pointer) 290// CHECK-NEXT: 24 | int b 291// CHECK-NEXT: | [sizeof=28, align=4 292// CHECK-NEXT: | nvsize=8, nvalign=4] 293// CHECK-X64: *** Dumping AST Record Layout 294// CHECK-X64: *** Dumping AST Record Layout 295// CHECK-X64: *** Dumping AST Record Layout 296} 297 298namespace pragma_test4 { 299struct A { 300 A(); 301 virtual void foo(); 302 int a; 303}; 304 305// Make sure the pragma applies to class template decls before they've been 306// instantiated. 307#pragma vtordisp(push,2) 308template <typename T> 309struct B : virtual A { 310 B(); 311 virtual ~B(); 312 virtual void bar(); 313 T b; 314}; 315#pragma vtordisp(pop) 316 317struct C : virtual B<int> { int c; }; 318// CHECK: *** Dumping AST Record Layout 319// CHECK: *** Dumping AST Record Layout 320// CHECK: *** Dumping AST Record Layout 321// CHECK-NEXT: 0 | struct pragma_test4::C 322// CHECK-NEXT: 0 | (C vbtable pointer) 323// CHECK-NEXT: 4 | int c 324// Pragma applies to B, which has vbase A. 325// CHECK-NEXT: 8 | (vtordisp for vbase A) 326// CHECK-NEXT: 12 | struct pragma_test4::A (virtual base) 327// CHECK-NEXT: 12 | (A vftable pointer) 328// CHECK-NEXT: 16 | int a 329// Pragma does not apply to C, and B doesn't usually need a vtordisp in C. 330// CHECK-NEXT: 20 | struct pragma_test4::B<int> (virtual base) 331// CHECK-NEXT: 20 | (B vftable pointer) 332// CHECK-NEXT: 24 | (B vbtable pointer) 333// CHECK-NEXT: 28 | int b 334// CHECK-NEXT: | [sizeof=32, align=4 335// CHECK-NEXT: | nvsize=8, nvalign=4] 336// CHECK-X64: *** Dumping AST Record Layout 337// CHECK-X64: *** Dumping AST Record Layout 338// CHECK-X64: *** Dumping AST Record Layout 339} 340 341struct GA { 342 virtual void fun() {} 343}; 344struct GB: public GA {}; 345struct GC: public virtual GA { 346 virtual void fun() {} 347 GC() {} 348}; 349struct GD: public virtual GC, public virtual GB {}; 350 351// CHECK: *** Dumping AST Record Layout 352// CHECK: *** Dumping AST Record Layout 353// CHECK: *** Dumping AST Record Layout 354// CHECK: *** Dumping AST Record Layout 355// CHECK-NEXT: 0 | struct GD 356// CHECK-NEXT: 0 | (GD vbtable pointer) 357// CHECK-NEXT: 4 | (vtordisp for vbase GA) 358// CHECK-NEXT: 8 | struct GA (virtual base) 359// CHECK-NEXT: 8 | (GA vftable pointer) 360// CHECK-NEXT: 12 | struct GC (virtual base) 361// CHECK-NEXT: 12 | (GC vbtable pointer) 362// CHECK-NEXT: 16 | struct GB (virtual base) 363// CHECK-NEXT: 16 | struct GA (primary base) 364// CHECK-NEXT: 16 | (GA vftable pointer) 365// CHECK-NEXT: | [sizeof=20, align=4 366// CHECK-NEXT: | nvsize=4, nvalign=4] 367// CHECK-X64: *** Dumping AST Record Layout 368// CHECK-X64: *** Dumping AST Record Layout 369// CHECK-X64: *** Dumping AST Record Layout 370// CHECK-X64: *** Dumping AST Record Layout 371// CHECK-X64-NEXT: 0 | struct GD 372// CHECK-X64-NEXT: 0 | (GD vbtable pointer) 373// CHECK-X64-NEXT: 12 | (vtordisp for vbase GA) 374// CHECK-X64-NEXT: 16 | struct GA (virtual base) 375// CHECK-X64-NEXT: 16 | (GA vftable pointer) 376// CHECK-X64-NEXT: 24 | struct GC (virtual base) 377// CHECK-X64-NEXT: 24 | (GC vbtable pointer) 378// CHECK-X64-NEXT: 32 | struct GB (virtual base) 379// CHECK-X64-NEXT: 32 | struct GA (primary base) 380// CHECK-X64-NEXT: 32 | (GA vftable pointer) 381// CHECK-X64-NEXT: | [sizeof=40, align=8 382// CHECK-X64-NEXT: | nvsize=8, nvalign=8] 383 384struct HA { 385 virtual void fun() {} 386}; 387#pragma vtordisp(push, 2) 388struct HB : virtual HA {}; 389#pragma vtordisp(pop) 390#pragma vtordisp(push, 0) 391struct HC : virtual HB {}; 392#pragma vtordisp(pop) 393 394// CHECK: *** Dumping AST Record Layout 395// CHECK: *** Dumping AST Record Layout 396// CHECK: *** Dumping AST Record Layout 397// CHECK-NEXT: 0 | struct HC 398// CHECK-NEXT: 0 | (HC vbtable pointer) 399// CHECK-NEXT: 4 | (vtordisp for vbase HA) 400// CHECK-NEXT: 8 | struct HA (virtual base) 401// CHECK-NEXT: 8 | (HA vftable pointer) 402// CHECK-NEXT: 12 | struct HB (virtual base) 403// CHECK-NEXT: 12 | (HB vbtable pointer) 404// CHECK-NEXT: | [sizeof=16, align=4 405// CHECK-NEXT: | nvsize=4, nvalign=4] 406// CHECK-X64: *** Dumping AST Record Layout 407// CHECK-X64: *** Dumping AST Record Layout 408// CHECK-X64: *** Dumping AST Record Layout 409// CHECK-X64-NEXT: 0 | struct HC 410// CHECK-X64-NEXT: 0 | (HC vbtable pointer) 411// CHECK-X64-NEXT: 12 | (vtordisp for vbase HA) 412// CHECK-X64-NEXT: 16 | struct HA (virtual base) 413// CHECK-X64-NEXT: 16 | (HA vftable pointer) 414// CHECK-X64-NEXT: 24 | struct HB (virtual base) 415// CHECK-X64-NEXT: 24 | (HB vbtable pointer) 416// CHECK-X64-NEXT: | [sizeof=32, align=8 417// CHECK-X64-NEXT: | nvsize=8, nvalign=8] 418 419struct IA { 420 virtual void f(); 421}; 422struct __declspec(dllexport) IB : virtual IA { 423 virtual void f() = 0; 424 IB() {} 425}; 426 427// CHECK: *** Dumping AST Record Layout 428// CHECK: *** Dumping AST Record Layout 429// CHECK-NEXT: 0 | struct IB 430// CHECK-NEXT: 0 | (IB vbtable pointer) 431// CHECK-NEXT: 4 | struct IA (virtual base) 432// CHECK-NEXT: 4 | (IA vftable pointer) 433// CHECK-NEXT: | [sizeof=8, align=4 434// CHECK-NEXT: | nvsize=4, nvalign=4] 435// CHECK-X64: *** Dumping AST Record Layout 436// CHECK-X64: *** Dumping AST Record Layout 437// CHECK-X64-NEXT: 0 | struct IB 438// CHECK-X64-NEXT: 0 | (IB vbtable pointer) 439// CHECK-X64-NEXT: 8 | struct IA (virtual base) 440// CHECK-X64-NEXT: 8 | (IA vftable pointer) 441// CHECK-X64-NEXT: | [sizeof=16, align=8 442// CHECK-X64-NEXT: | nvsize=8, nvalign=8] 443 444int a[ 445sizeof(A)+ 446sizeof(C)+ 447sizeof(D)+ 448sizeof(CT)+ 449sizeof(XC)+ 450sizeof(pragma_test1::C)+ 451sizeof(pragma_test2::C)+ 452sizeof(pragma_test3::C)+ 453sizeof(pragma_test4::C)+ 454sizeof(GD)+ 455sizeof(HC)+ 456sizeof(IB)+ 4570]; 458