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