Clang Project

clang_source_code/test/Layout/ms-vtordisp-local.cpp
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
3struct Base {
4  virtual ~Base() {}
5  virtual void BaseFunc() {}
6};
7
8#pragma vtordisp(0)
9
10struct Container {
11  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
36struct NoVtorDisp1 : virtual Base {
37  virtual ~NoVtorDisp1() {}
38  virtual void Func() {}
39};
40
41int 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
54struct Container2 {
55  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
167  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
189struct Container3 {
190  #pragma vtordisp(2)
191  struct HasVtorDisp5 : virtual Base {
192    virtual ~HasVtorDisp5() {}
193    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
211int main() {
212  Container::f();
213  Container2::f1();
214  Container2::f2();
215  Container3 cont3;
216  return 0;
217};
218