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