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 6 extern "C" int printf(const char *fmt, ...); 7 8 struct B0 { 9 int a; 10 B0() : a(0xf00000B0) {} 11 virtual void f() { printf("B0"); } 12 }; 13 14 struct __declspec(align(16)) B1 { 15 int a; 16 B1() : a(0xf00000B1) {} 17 virtual void f() { printf("B1"); } 18 }; 19 20 struct __declspec(align(16)) Align16 {}; 21 struct __declspec(align(32)) Align32 {}; 22 struct VAlign16 : virtual Align16 {}; 23 struct VAlign32 : virtual Align32 {}; 24 25 struct 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 67 struct 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 113 struct __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 151 struct AT { 152 virtual ~AT(){} 153 }; 154 struct CT : virtual AT { 155 virtual ~CT(); 156 }; 157 CT::~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 176 struct XA { 177 XA() { printf("XA"); } 178 long long ll; 179 }; 180 struct XB : XA { 181 XB() { printf("XB"); } 182 virtual void foo() {} 183 int b; 184 }; 185 struct 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 217 namespace pragma_test1 { 218 // No overrides means no vtordisps by default. 219 struct A { virtual ~A(); virtual void foo(); int a; }; 220 struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 221 struct 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 242 namespace pragma_test2 { 243 struct A { virtual ~A(); virtual void foo(); int a; }; 244 #pragma vtordisp(push,2) 245 struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 246 struct 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 271 namespace pragma_test3 { 272 struct A { virtual ~A(); virtual void foo(); int a; }; 273 #pragma vtordisp(push,2) 274 struct B : virtual A { virtual ~B(); virtual void foo(); int b; }; 275 struct 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 298 namespace pragma_test4 { 299 struct 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) 308 template <typename T> 309 struct B : virtual A { 310 B(); 311 virtual ~B(); 312 virtual void bar(); 313 T b; 314 }; 315 #pragma vtordisp(pop) 316 317 struct 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 341 struct GA { 342 virtual void fun() {} 343 }; 344 struct GB: public GA {}; 345 struct GC: public virtual GA { 346 virtual void fun() {} 347 GC() {} 348 }; 349 struct 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 384 struct HA { 385 virtual void fun() {} 386 }; 387 #pragma vtordisp(push, 2) 388 struct HB : virtual HA {}; 389 #pragma vtordisp(pop) 390 #pragma vtordisp(push, 0) 391 struct 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 419 int a[ 420 sizeof(A)+ 421 sizeof(C)+ 422 sizeof(D)+ 423 sizeof(CT)+ 424 sizeof(XC)+ 425 sizeof(pragma_test1::C)+ 426 sizeof(pragma_test2::C)+ 427 sizeof(pragma_test3::C)+ 428 sizeof(pragma_test4::C)+ 429 sizeof(GD)+ 430 sizeof(HC)+ 431 0]; 432