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