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-LABEL: 0 | struct A{{$}} 33 // CHECK-NEXT: 0 | (A vftable pointer) 34 // CHECK-NEXT: 4 | (A vbtable pointer) 35 // CHECK-NEXT: 8 | int a 36 // CHECK-NEXT: 16 | (vtordisp for vbase B0) 37 // CHECK-NEXT: 20 | struct B0 (virtual base) 38 // CHECK-NEXT: 20 | (B0 vftable pointer) 39 // CHECK-NEXT: 24 | int a 40 // CHECK-NEXT: 44 | (vtordisp for vbase B1) 41 // CHECK-NEXT: 48 | struct B1 (virtual base) 42 // CHECK-NEXT: 48 | (B1 vftable pointer) 43 // CHECK-NEXT: 52 | int a 44 // CHECK-NEXT: | [sizeof=64, align=16 45 // CHECK-NEXT: | nvsize=12, nvalign=16] 46 // CHECK-X64-LABEL: 0 | struct A{{$}} 47 // CHECK-X64-NEXT: 0 | (A vftable pointer) 48 // CHECK-X64-NEXT: 8 | (A vbtable pointer) 49 // CHECK-X64-NEXT: 16 | int a 50 // CHECK-X64-NEXT: 36 | (vtordisp for vbase B0) 51 // CHECK-X64-NEXT: 40 | struct B0 (virtual base) 52 // CHECK-X64-NEXT: 40 | (B0 vftable pointer) 53 // CHECK-X64-NEXT: 48 | int a 54 // CHECK-X64-NEXT: 76 | (vtordisp for vbase B1) 55 // CHECK-X64-NEXT: 80 | struct B1 (virtual base) 56 // CHECK-X64-NEXT: 80 | (B1 vftable pointer) 57 // CHECK-X64-NEXT: 88 | int a 58 // CHECK-X64-NEXT: | [sizeof=96, align=16 59 // CHECK-X64-NEXT: | nvsize=24, nvalign=16] 60 61 struct C : virtual B0, virtual B1, VAlign32 { 62 int a; 63 C() : a(0xf000000C) {} 64 virtual void f() { printf("C"); } 65 virtual void g() { printf("C"); } 66 }; 67 68 // CHECK-LABEL: 0 | struct C{{$}} 69 // CHECK-NEXT: 0 | (C vftable pointer) 70 // CHECK-NEXT: 32 | struct VAlign32 (base) 71 // CHECK-NEXT: 32 | (VAlign32 vbtable pointer) 72 // CHECK-NEXT: 36 | int a 73 // CHECK-NEXT: 64 | (vtordisp for vbase B0) 74 // CHECK-NEXT: 68 | struct B0 (virtual base) 75 // CHECK-NEXT: 68 | (B0 vftable pointer) 76 // CHECK-NEXT: 72 | int a 77 // CHECK-NEXT: 108 | (vtordisp for vbase B1) 78 // CHECK-NEXT: 112 | struct B1 (virtual base) 79 // CHECK-NEXT: 112 | (B1 vftable pointer) 80 // CHECK-NEXT: 116 | int a 81 // CHECK-NEXT: 128 | struct Align32 (virtual base) (empty) 82 // CHECK-NEXT: | [sizeof=128, align=32 83 // CHECK-NEXT: | nvsize=64, nvalign=32] 84 // CHECK-X64-LABEL: 0 | struct C{{$}} 85 // CHECK-X64-NEXT: 0 | (C vftable pointer) 86 // CHECK-X64-NEXT: 32 | struct VAlign32 (base) 87 // CHECK-X64-NEXT: 32 | (VAlign32 vbtable pointer) 88 // CHECK-X64-NEXT: 40 | int a 89 // CHECK-X64-NEXT: 68 | (vtordisp for vbase B0) 90 // CHECK-X64-NEXT: 72 | struct B0 (virtual base) 91 // CHECK-X64-NEXT: 72 | (B0 vftable pointer) 92 // CHECK-X64-NEXT: 80 | int a 93 // CHECK-X64-NEXT: 108 | (vtordisp for vbase B1) 94 // CHECK-X64-NEXT: 112 | struct B1 (virtual base) 95 // CHECK-X64-NEXT: 112 | (B1 vftable pointer) 96 // CHECK-X64-NEXT: 120 | int a 97 // CHECK-X64-NEXT: 128 | struct Align32 (virtual base) (empty) 98 // CHECK-X64-NEXT: | [sizeof=128, align=32 99 // CHECK-X64-NEXT: | nvsize=64, nvalign=32] 100 101 struct __declspec(align(32)) D : virtual B0, virtual B1 { 102 int a; 103 D() : a(0xf000000D) {} 104 virtual void f() { printf("D"); } 105 virtual void g() { printf("D"); } 106 }; 107 108 // CHECK-LABEL: 0 | struct D{{$}} 109 // CHECK-NEXT: 0 | (D vftable pointer) 110 // CHECK-NEXT: 4 | (D vbtable pointer) 111 // CHECK-NEXT: 8 | int a 112 // CHECK-NEXT: 32 | (vtordisp for vbase B0) 113 // CHECK-NEXT: 36 | struct B0 (virtual base) 114 // CHECK-NEXT: 36 | (B0 vftable pointer) 115 // CHECK-NEXT: 40 | int a 116 // CHECK-NEXT: 76 | (vtordisp for vbase B1) 117 // CHECK-NEXT: 80 | struct B1 (virtual base) 118 // CHECK-NEXT: 80 | (B1 vftable pointer) 119 // CHECK-NEXT: 84 | int a 120 // CHECK-NEXT: | [sizeof=96, align=32 121 // CHECK-NEXT: | nvsize=12, nvalign=32] 122 // CHECK-X64-LABEL: 0 | struct D{{$}} 123 // CHECK-X64-NEXT: 0 | (D vftable pointer) 124 // CHECK-X64-NEXT: 8 | (D vbtable pointer) 125 // CHECK-X64-NEXT: 16 | int a 126 // CHECK-X64-NEXT: 36 | (vtordisp for vbase B0) 127 // CHECK-X64-NEXT: 40 | struct B0 (virtual base) 128 // CHECK-X64-NEXT: 40 | (B0 vftable pointer) 129 // CHECK-X64-NEXT: 48 | int a 130 // CHECK-X64-NEXT: 76 | (vtordisp for vbase B1) 131 // CHECK-X64-NEXT: 80 | struct B1 (virtual base) 132 // CHECK-X64-NEXT: 80 | (B1 vftable pointer) 133 // CHECK-X64-NEXT: 88 | int a 134 // CHECK-X64-NEXT: | [sizeof=96, align=32 135 // CHECK-X64-NEXT: | nvsize=24, nvalign=32] 136 137 struct AT { 138 virtual ~AT(){} 139 }; 140 struct CT : virtual AT { 141 virtual ~CT(); 142 }; 143 CT::~CT(){} 144 145 // CHECK-LABEL: 0 | struct CT{{$}} 146 // CHECK-NEXT: 0 | (CT vbtable pointer) 147 // CHECK-NEXT: 4 | struct AT (virtual base) 148 // CHECK-NEXT: 4 | (AT vftable pointer) 149 // CHECK-NEXT: | [sizeof=8, align=4 150 // CHECK-NEXT: | nvsize=4, nvalign=4] 151 // CHECK-X64-LABEL: 0 | struct CT{{$}} 152 // CHECK-X64-NEXT: 0 | (CT vbtable pointer) 153 // CHECK-X64-NEXT: 8 | struct AT (virtual base) 154 // CHECK-X64-NEXT: 8 | (AT vftable pointer) 155 // CHECK-X64-NEXT: | [sizeof=16, align=8 156 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] 157 158 struct XA { 159 XA() { printf("XA"); } 160 long long ll; 161 }; 162 struct XB : XA { 163 XB() { printf("XB"); } 164 virtual void foo() {} 165 int b; 166 }; 167 struct XC : virtual XB { 168 XC() { printf("XC"); } 169 virtual void foo() {} 170 }; 171 172 // CHECK-LABEL: 0 | struct XC{{$}} 173 // CHECK-NEXT: 0 | (XC vbtable pointer) 174 // CHECK-NEXT: 4 | (vtordisp for vbase XB) 175 // CHECK-NEXT: 8 | struct XB (virtual base) 176 // CHECK-NEXT: 8 | (XB vftable pointer) 177 // CHECK-NEXT: 16 | struct XA (base) 178 // CHECK-NEXT: 16 | long long ll 179 // CHECK-NEXT: 24 | int b 180 // CHECK-NEXT: | [sizeof=32, align=8 181 // CHECK-NEXT: | nvsize=4, nvalign=8] 182 // CHECK-X64-LABEL: 0 | struct XC{{$}} 183 // CHECK-X64-NEXT: 0 | (XC vbtable pointer) 184 // CHECK-X64-NEXT: 12 | (vtordisp for vbase XB) 185 // CHECK-X64-NEXT: 16 | struct XB (virtual base) 186 // CHECK-X64-NEXT: 16 | (XB vftable pointer) 187 // CHECK-X64-NEXT: 24 | struct XA (base) 188 // CHECK-X64-NEXT: 24 | long long ll 189 // CHECK-X64-NEXT: 32 | int b 190 // CHECK-X64-NEXT: | [sizeof=40, align=8 191 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] 192 193 namespace pragma_test1 { 194 // No overrides means no vtordisps by default. 195 struct A { virtual ~A(); virtual void foo(); int a; }; 196 struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 197 struct C : virtual B { int c; }; 198 // CHECK-LABEL: 0 | struct pragma_test1::C{{$}} 199 // CHECK-NEXT: 0 | (C vbtable pointer) 200 // CHECK-NEXT: 4 | int c 201 // CHECK-NEXT: 8 | struct pragma_test1::A (virtual base) 202 // CHECK-NEXT: 8 | (A vftable pointer) 203 // CHECK-NEXT: 12 | int a 204 // CHECK-NEXT: 16 | struct pragma_test1::B (virtual base) 205 // CHECK-NEXT: 16 | (B vftable pointer) 206 // CHECK-NEXT: 20 | (B vbtable pointer) 207 // CHECK-NEXT: 24 | int b 208 // CHECK-NEXT: | [sizeof=28, align=4 209 // CHECK-NEXT: | nvsize=8, nvalign=4] 210 } 211 212 namespace pragma_test2 { 213 struct A { virtual ~A(); virtual void foo(); int a; }; 214 #pragma vtordisp(push,2) 215 struct B : virtual A { virtual ~B(); virtual void bar(); int b; }; 216 struct C : virtual B { int c; }; 217 #pragma vtordisp(pop) 218 // CHECK-LABEL: 0 | struct pragma_test2::C{{$}} 219 // CHECK-NEXT: 0 | (C vbtable pointer) 220 // CHECK-NEXT: 4 | int c 221 // CHECK-NEXT: 8 | (vtordisp for vbase A) 222 // CHECK-NEXT: 12 | struct pragma_test2::A (virtual base) 223 // CHECK-NEXT: 12 | (A vftable pointer) 224 // CHECK-NEXT: 16 | int a 225 // By adding a virtual method and vftable to B, now we need a vtordisp. 226 // CHECK-NEXT: 20 | (vtordisp for vbase B) 227 // CHECK-NEXT: 24 | struct pragma_test2::B (virtual base) 228 // CHECK-NEXT: 24 | (B vftable pointer) 229 // CHECK-NEXT: 28 | (B vbtable pointer) 230 // CHECK-NEXT: 32 | int b 231 // CHECK-NEXT: | [sizeof=36, align=4 232 // CHECK-NEXT: | nvsize=8, nvalign=4] 233 } 234 235 namespace pragma_test3 { 236 struct A { virtual ~A(); virtual void foo(); int a; }; 237 #pragma vtordisp(push,2) 238 struct B : virtual A { virtual ~B(); virtual void foo(); int b; }; 239 struct C : virtual B { int c; }; 240 #pragma vtordisp(pop) 241 // CHECK-LABEL: 0 | struct pragma_test3::C{{$}} 242 // CHECK-NEXT: 0 | (C vbtable pointer) 243 // CHECK-NEXT: 4 | int c 244 // CHECK-NEXT: 8 | (vtordisp for vbase A) 245 // CHECK-NEXT: 12 | struct pragma_test3::A (virtual base) 246 // CHECK-NEXT: 12 | (A vftable pointer) 247 // CHECK-NEXT: 16 | int a 248 // No vtordisp before B! It doesn't have its own vftable. 249 // CHECK-NEXT: 20 | struct pragma_test3::B (virtual base) 250 // CHECK-NEXT: 20 | (B vbtable pointer) 251 // CHECK-NEXT: 24 | int b 252 // CHECK-NEXT: | [sizeof=28, align=4 253 // CHECK-NEXT: | nvsize=8, nvalign=4] 254 } 255 256 namespace pragma_test4 { 257 struct A { 258 A(); 259 virtual void foo(); 260 int a; 261 }; 262 263 // Make sure the pragma applies to class template decls before they've been 264 // instantiated. 265 #pragma vtordisp(push,2) 266 template <typename T> 267 struct B : virtual A { 268 B(); 269 virtual ~B(); 270 virtual void bar(); 271 T b; 272 }; 273 #pragma vtordisp(pop) 274 275 struct C : virtual B<int> { int c; }; 276 // CHECK-LABEL: 0 | struct pragma_test4::C{{$}} 277 // CHECK-NEXT: 0 | (C vbtable pointer) 278 // CHECK-NEXT: 4 | int c 279 // Pragma applies to B, which has vbase A. 280 // CHECK-NEXT: 8 | (vtordisp for vbase A) 281 // CHECK-NEXT: 12 | struct pragma_test4::A (virtual base) 282 // CHECK-NEXT: 12 | (A vftable pointer) 283 // CHECK-NEXT: 16 | int a 284 // Pragma does not apply to C, and B doesn't usually need a vtordisp in C. 285 // CHECK-NEXT: 20 | struct pragma_test4::B<int> (virtual base) 286 // CHECK-NEXT: 20 | (B vftable pointer) 287 // CHECK-NEXT: 24 | (B vbtable pointer) 288 // CHECK-NEXT: 28 | int b 289 // CHECK-NEXT: | [sizeof=32, align=4 290 // CHECK-NEXT: | nvsize=8, nvalign=4] 291 } 292 293 struct GA { 294 virtual void fun() {} 295 }; 296 struct GB: public GA {}; 297 struct GC: public virtual GA { 298 virtual void fun() {} 299 GC() {} 300 }; 301 struct GD: public virtual GC, public virtual GB {}; 302 303 // CHECK-LABEL: 0 | struct GD{{$}} 304 // CHECK-NEXT: 0 | (GD vbtable pointer) 305 // CHECK-NEXT: 4 | (vtordisp for vbase GA) 306 // CHECK-NEXT: 8 | struct GA (virtual base) 307 // CHECK-NEXT: 8 | (GA vftable pointer) 308 // CHECK-NEXT: 12 | struct GC (virtual base) 309 // CHECK-NEXT: 12 | (GC vbtable pointer) 310 // CHECK-NEXT: 16 | struct GB (virtual base) 311 // CHECK-NEXT: 16 | struct GA (primary base) 312 // CHECK-NEXT: 16 | (GA vftable pointer) 313 // CHECK-NEXT: | [sizeof=20, align=4 314 // CHECK-NEXT: | nvsize=4, nvalign=4] 315 // CHECK-X64-LABEL: 0 | struct GD{{$}} 316 // CHECK-X64-NEXT: 0 | (GD vbtable pointer) 317 // CHECK-X64-NEXT: 12 | (vtordisp for vbase GA) 318 // CHECK-X64-NEXT: 16 | struct GA (virtual base) 319 // CHECK-X64-NEXT: 16 | (GA vftable pointer) 320 // CHECK-X64-NEXT: 24 | struct GC (virtual base) 321 // CHECK-X64-NEXT: 24 | (GC vbtable pointer) 322 // CHECK-X64-NEXT: 32 | struct GB (virtual base) 323 // CHECK-X64-NEXT: 32 | struct GA (primary base) 324 // CHECK-X64-NEXT: 32 | (GA vftable pointer) 325 // CHECK-X64-NEXT: | [sizeof=40, align=8 326 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] 327 328 struct HA { 329 virtual void fun() {} 330 }; 331 #pragma vtordisp(push, 2) 332 struct HB : virtual HA {}; 333 #pragma vtordisp(pop) 334 #pragma vtordisp(push, 0) 335 struct HC : virtual HB {}; 336 #pragma vtordisp(pop) 337 338 // CHECK-LABEL: 0 | struct HC{{$}} 339 // CHECK-NEXT: 0 | (HC vbtable pointer) 340 // CHECK-NEXT: 4 | (vtordisp for vbase HA) 341 // CHECK-NEXT: 8 | struct HA (virtual base) 342 // CHECK-NEXT: 8 | (HA vftable pointer) 343 // CHECK-NEXT: 12 | struct HB (virtual base) 344 // CHECK-NEXT: 12 | (HB vbtable pointer) 345 // CHECK-NEXT: | [sizeof=16, align=4 346 // CHECK-NEXT: | nvsize=4, nvalign=4] 347 // CHECK-X64-LABEL: 0 | struct HC{{$}} 348 // CHECK-X64-NEXT: 0 | (HC vbtable pointer) 349 // CHECK-X64-NEXT: 12 | (vtordisp for vbase HA) 350 // CHECK-X64-NEXT: 16 | struct HA (virtual base) 351 // CHECK-X64-NEXT: 16 | (HA vftable pointer) 352 // CHECK-X64-NEXT: 24 | struct HB (virtual base) 353 // CHECK-X64-NEXT: 24 | (HB vbtable pointer) 354 // CHECK-X64-NEXT: | [sizeof=32, align=8 355 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] 356 357 struct IA { 358 virtual void f(); 359 }; 360 struct __declspec(dllexport) IB : virtual IA { 361 virtual void f() = 0; 362 IB() {} 363 }; 364 365 // CHECK-LABEL: 0 | struct IB{{$}} 366 // CHECK-NEXT: 0 | (IB vbtable pointer) 367 // CHECK-NEXT: 4 | struct IA (virtual base) 368 // CHECK-NEXT: 4 | (IA vftable pointer) 369 // CHECK-NEXT: | [sizeof=8, align=4 370 // CHECK-NEXT: | nvsize=4, nvalign=4] 371 // CHECK-X64-LABEL: 0 | struct IB{{$}} 372 // CHECK-X64-NEXT: 0 | (IB vbtable pointer) 373 // CHECK-X64-NEXT: 8 | struct IA (virtual base) 374 // CHECK-X64-NEXT: 8 | (IA vftable pointer) 375 // CHECK-X64-NEXT: | [sizeof=16, align=8 376 // CHECK-X64-NEXT: | nvsize=8, nvalign=8] 377 378 int a[ 379 sizeof(A)+ 380 sizeof(C)+ 381 sizeof(D)+ 382 sizeof(CT)+ 383 sizeof(XC)+ 384 sizeof(pragma_test1::C)+ 385 sizeof(pragma_test2::C)+ 386 sizeof(pragma_test3::C)+ 387 sizeof(pragma_test4::C)+ 388 sizeof(GD)+ 389 sizeof(HC)+ 390 sizeof(IB)+ 391 0]; 392