1*67e74705SXin Li // RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li struct Base {
~BaseBase4*67e74705SXin Li virtual ~Base() {}
BaseFuncBase5*67e74705SXin Li virtual void BaseFunc() {}
6*67e74705SXin Li };
7*67e74705SXin Li
8*67e74705SXin Li #pragma vtordisp(0)
9*67e74705SXin Li
10*67e74705SXin Li struct Container {
fContainer11*67e74705SXin Li static void f() try {
12*67e74705SXin Li #pragma vtordisp(2)
13*67e74705SXin Li struct HasVtorDisp : virtual Base {
14*67e74705SXin Li virtual ~HasVtorDisp() {}
15*67e74705SXin Li virtual void Func() {}
16*67e74705SXin Li };
17*67e74705SXin Li
18*67e74705SXin Li int x[sizeof(HasVtorDisp)];
19*67e74705SXin Li
20*67e74705SXin Li // HasVtorDisp: vtordisp because of pragma right before it.
21*67e74705SXin Li //
22*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
23*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
24*67e74705SXin Li // CHECK-NEXT: 0 | struct HasVtorDisp
25*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp vftable pointer)
26*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp vbtable pointer)
27*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
28*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
29*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
30*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
31*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
32*67e74705SXin Li } catch (...) {
33*67e74705SXin Li }
34*67e74705SXin Li };
35*67e74705SXin Li
36*67e74705SXin Li struct NoVtorDisp1 : virtual Base {
~NoVtorDisp1NoVtorDisp137*67e74705SXin Li virtual ~NoVtorDisp1() {}
FuncNoVtorDisp138*67e74705SXin Li virtual void Func() {}
39*67e74705SXin Li };
40*67e74705SXin Li
41*67e74705SXin Li int x1[sizeof(NoVtorDisp1)];
42*67e74705SXin Li
43*67e74705SXin Li // NoVtroDisp1: no vtordisp because of pragma disabling it.
44*67e74705SXin Li //
45*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
46*67e74705SXin Li // CHECK-NEXT: 0 | struct NoVtorDisp1
47*67e74705SXin Li // CHECK-NEXT: 0 | (NoVtorDisp1 vftable pointer)
48*67e74705SXin Li // CHECK-NEXT: 8 | (NoVtorDisp1 vbtable pointer)
49*67e74705SXin Li // CHECK-NEXT: 16 | struct Base (virtual base)
50*67e74705SXin Li // CHECK-NEXT: 16 | (Base vftable pointer)
51*67e74705SXin Li // CHECK-NEXT: | [sizeof=24, align=8,
52*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
53*67e74705SXin Li
54*67e74705SXin Li struct Container2 {
f1Container255*67e74705SXin Li static void f1() {
56*67e74705SXin Li // Local pragma #1 - must be disabled on exit from f1().
57*67e74705SXin Li #pragma vtordisp(push, 2)
58*67e74705SXin Li struct HasVtorDisp1 : virtual Base {
59*67e74705SXin Li virtual ~HasVtorDisp1() {}
60*67e74705SXin Li virtual void Func() {}
61*67e74705SXin Li };
62*67e74705SXin Li
63*67e74705SXin Li int x2[sizeof(HasVtorDisp1)];
64*67e74705SXin Li
65*67e74705SXin Li // HasVtorDisp1: vtordisp because of pragma right before it.
66*67e74705SXin Li //
67*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
68*67e74705SXin Li // CHECK-NEXT: 0 | struct HasVtorDisp1
69*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp1 vftable pointer)
70*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp1 vbtable pointer)
71*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
72*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
73*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
74*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
75*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
76*67e74705SXin Li
77*67e74705SXin Li struct InnerContainer {
78*67e74705SXin Li static void g1() {
79*67e74705SXin Li struct HasVtorDisp2 : virtual Base {
80*67e74705SXin Li virtual ~HasVtorDisp2() {}
81*67e74705SXin Li virtual void Func() {}
82*67e74705SXin Li };
83*67e74705SXin Li
84*67e74705SXin Li int x3[sizeof(HasVtorDisp2)];
85*67e74705SXin Li
86*67e74705SXin Li // HasVtorDisp2: vtordisp because of vtordisp(2) in f1().
87*67e74705SXin Li //
88*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
89*67e74705SXin Li // CHECK-NEXT: 0 | struct HasVtorDisp2
90*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp2 vftable pointer)
91*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp2 vbtable pointer)
92*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
93*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
94*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
95*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
96*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
97*67e74705SXin Li
98*67e74705SXin Li // Local pragma #2 - must be disabled on exit from g1().
99*67e74705SXin Li #pragma vtordisp(push, 0)
100*67e74705SXin Li struct NoVtorDisp2 : virtual Base {
101*67e74705SXin Li virtual ~NoVtorDisp2() {}
102*67e74705SXin Li virtual void Func() {}
103*67e74705SXin Li };
104*67e74705SXin Li
105*67e74705SXin Li int x4[sizeof(NoVtorDisp2)];
106*67e74705SXin Li
107*67e74705SXin Li // NoVtroDisp2: no vtordisp because of vtordisp(0) in g1().
108*67e74705SXin Li //
109*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
110*67e74705SXin Li // CHECK-NEXT: 0 | struct NoVtorDisp2
111*67e74705SXin Li // CHECK-NEXT: 0 | (NoVtorDisp2 vftable pointer)
112*67e74705SXin Li // CHECK-NEXT: 8 | (NoVtorDisp2 vbtable pointer)
113*67e74705SXin Li // CHECK-NEXT: 16 | struct Base (virtual base)
114*67e74705SXin Li // CHECK-NEXT: 16 | (Base vftable pointer)
115*67e74705SXin Li // CHECK-NEXT: | [sizeof=24, align=8,
116*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
117*67e74705SXin Li }
118*67e74705SXin Li
119*67e74705SXin Li static void g2() {
120*67e74705SXin Li struct HasVtorDisp3 : virtual Base {
121*67e74705SXin Li virtual ~HasVtorDisp3() {}
122*67e74705SXin Li virtual void Func() {}
123*67e74705SXin Li };
124*67e74705SXin Li
125*67e74705SXin Li int x5[sizeof(HasVtorDisp3)];
126*67e74705SXin Li
127*67e74705SXin Li // HasVtorDisp3: vtordisp because of vtordisp(2) in f1(),
128*67e74705SXin Li // local vtordisp(0) in g1() is disabled.
129*67e74705SXin Li //
130*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
131*67e74705SXin Li // CHECK-NEXT: 0 | struct HasVtorDisp3
132*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp3 vftable pointer)
133*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp3 vbtable pointer)
134*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
135*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
136*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
137*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
138*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
139*67e74705SXin Li }
140*67e74705SXin Li };
141*67e74705SXin Li
142*67e74705SXin Li struct HasVtorDisp4 : virtual Base {
143*67e74705SXin Li virtual ~HasVtorDisp4() {}
144*67e74705SXin Li virtual void Func() {}
145*67e74705SXin Li };
146*67e74705SXin Li
147*67e74705SXin Li int x6[sizeof(HasVtorDisp4)];
148*67e74705SXin Li
149*67e74705SXin Li // HasVtorDisp4: vtordisp because of vtordisp(2) in f1(),
150*67e74705SXin Li // local vtordisp(0) in g1() is disabled,
151*67e74705SXin Li // g2() has no pragmas - stack is not affected.
152*67e74705SXin Li //
153*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
154*67e74705SXin Li // CHECK-NEXT: 0 | struct HasVtorDisp4
155*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp4 vftable pointer)
156*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp4 vbtable pointer)
157*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
158*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
159*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
160*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
161*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
162*67e74705SXin Li
163*67e74705SXin Li InnerContainer::g1();
164*67e74705SXin Li InnerContainer::g2();
165*67e74705SXin Li }
166*67e74705SXin Li
f2Container2167*67e74705SXin Li static void f2() {
168*67e74705SXin Li struct NoVtorDisp3 : virtual Base {
169*67e74705SXin Li virtual ~NoVtorDisp3() {}
170*67e74705SXin Li virtual void Func() {}
171*67e74705SXin Li };
172*67e74705SXin Li
173*67e74705SXin Li int x7[sizeof(NoVtorDisp3)];
174*67e74705SXin Li
175*67e74705SXin Li // NoVtroDisp3: no vtordisp because of global pragma (0),
176*67e74705SXin Li // local vtordisp(2) is disabled on exit from f1().
177*67e74705SXin Li //
178*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
179*67e74705SXin Li // CHECK-NEXT: 0 | struct NoVtorDisp3
180*67e74705SXin Li // CHECK-NEXT: 0 | (NoVtorDisp3 vftable pointer)
181*67e74705SXin Li // CHECK-NEXT: 8 | (NoVtorDisp3 vbtable pointer)
182*67e74705SXin Li // CHECK-NEXT: 16 | struct Base (virtual base)
183*67e74705SXin Li // CHECK-NEXT: 16 | (Base vftable pointer)
184*67e74705SXin Li // CHECK-NEXT: | [sizeof=24, align=8,
185*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
186*67e74705SXin Li }
187*67e74705SXin Li };
188*67e74705SXin Li
189*67e74705SXin Li struct Container3 {
190*67e74705SXin Li #pragma vtordisp(2)
191*67e74705SXin Li struct HasVtorDisp5 : virtual Base {
~HasVtorDisp5Container3::HasVtorDisp5192*67e74705SXin Li virtual ~HasVtorDisp5() {}
FuncContainer3::HasVtorDisp5193*67e74705SXin Li virtual void Func() {}
194*67e74705SXin Li };
195*67e74705SXin Li
196*67e74705SXin Li int x8[sizeof(HasVtorDisp5)];
197*67e74705SXin Li
198*67e74705SXin Li // HasVtorDisp5: vtordisp because of pragma right before it.
199*67e74705SXin Li //
200*67e74705SXin Li // CHECK: *** Dumping AST Record Layout
201*67e74705SXin Li // CHECK-NEXT: 0 | struct Container3::HasVtorDisp5
202*67e74705SXin Li // CHECK-NEXT: 0 | (HasVtorDisp5 vftable pointer)
203*67e74705SXin Li // CHECK-NEXT: 8 | (HasVtorDisp5 vbtable pointer)
204*67e74705SXin Li // CHECK-NEXT: 20 | (vtordisp for vbase Base)
205*67e74705SXin Li // CHECK-NEXT: 24 | struct Base (virtual base)
206*67e74705SXin Li // CHECK-NEXT: 24 | (Base vftable pointer)
207*67e74705SXin Li // CHECK-NEXT: | [sizeof=32, align=8,
208*67e74705SXin Li // CHECK-NEXT: | nvsize=16, nvalign=8]
209*67e74705SXin Li };
210*67e74705SXin Li
main()211*67e74705SXin Li int main() {
212*67e74705SXin Li Container::f();
213*67e74705SXin Li Container2::f1();
214*67e74705SXin Li Container2::f2();
215*67e74705SXin Li Container3 cont3;
216*67e74705SXin Li return 0;
217*67e74705SXin Li };
218