1// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2
3// See Test9 for test description.
4// CHECK: @_ZTTN5Test91BE = linkonce_odr unnamed_addr constant
5namespace Test1 {
6
7// Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial.
8struct A {
9  virtual void f();
10  ~A();
11};
12
13// CHECK-LABEL: define void @_ZN5Test11AD2Ev
14// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2), i8***
15A::~A()
16{
17}
18
19}
20
21namespace Test2 {
22
23// Check that we do initialize the vtable pointer in A::~A() since the destructor body isn't trivial.
24struct A {
25  virtual void f();
26  ~A();
27};
28
29// CHECK-LABEL: define void @_ZN5Test21AD2Ev
30// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2), i8***
31A::~A() {
32  f();
33}
34
35}
36
37namespace Test3 {
38
39// Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial
40// and Field's destructor body is also trivial.
41struct Field {
42  ~Field() { }
43};
44
45struct A {
46  virtual void f();
47  ~A();
48
49  Field field;
50};
51
52// CHECK-LABEL: define void @_ZN5Test31AD2Ev
53// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2), i8***
54A::~A() {
55
56}
57
58}
59
60namespace Test4 {
61
62// Check that we do initialize the vtable pointer in A::~A(), since Field's destructor body
63// isn't trivial.
64
65void f();
66
67struct Field {
68  ~Field() { f(); }
69};
70
71struct A {
72  virtual void f();
73  ~A();
74
75  Field field;
76};
77
78// CHECK-LABEL: define void @_ZN5Test41AD2Ev
79// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2), i8***
80A::~A()
81{
82}
83
84}
85
86namespace Test5 {
87
88// Check that we do initialize the vtable pointer in A::~A(), since Field's destructor isn't
89// available in this translation unit.
90
91struct Field {
92  ~Field();
93};
94
95struct A {
96  virtual void f();
97  ~A();
98
99  Field field;
100};
101
102// CHECK-LABEL: define void @_ZN5Test51AD2Ev
103// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2), i8***
104A::~A()
105{
106}
107
108}
109
110namespace Test6 {
111
112// Check that we do initialize the vtable pointer in A::~A(), since Field has a member
113// variable with a non-trivial destructor body.
114
115struct NonTrivialDestructorBody {
116  ~NonTrivialDestructorBody();
117};
118
119struct Field {
120  NonTrivialDestructorBody nonTrivialDestructorBody;
121};
122
123struct A {
124  virtual void f();
125  ~A();
126
127  Field field;
128};
129
130// CHECK-LABEL: define void @_ZN5Test61AD2Ev
131// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8***
132A::~A()
133{
134}
135
136}
137
138namespace Test7 {
139
140// Check that we do initialize the vtable pointer in A::~A(), since Field has a base
141// class with a non-trivial destructor body.
142
143struct NonTrivialDestructorBody {
144  ~NonTrivialDestructorBody();
145};
146
147struct Field : NonTrivialDestructorBody { };
148
149struct A {
150  virtual void f();
151  ~A();
152
153  Field field;
154};
155
156// CHECK-LABEL: define void @_ZN5Test71AD2Ev
157// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8***
158A::~A()
159{
160}
161
162}
163
164namespace Test8 {
165
166// Check that we do initialize the vtable pointer in A::~A(), since Field has a virtual base
167// class with a non-trivial destructor body.
168
169struct NonTrivialDestructorBody {
170  ~NonTrivialDestructorBody();
171};
172
173struct Field : virtual NonTrivialDestructorBody { };
174
175struct A {
176  virtual void f();
177  ~A();
178
179  Field field;
180};
181
182// CHECK-LABEL: define void @_ZN5Test81AD2Ev
183// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8***
184A::~A()
185{
186}
187
188}
189
190namespace Test9 {
191
192// Check that we emit a VTT for B, even though we don't initialize the vtable pointer in the destructor.
193struct A { virtual ~A () { } };
194struct B : virtual A {};
195struct C : virtual B {
196  virtual ~C();
197};
198C::~C() {}
199
200}
201