Mercurial > hg > CbC > CbC_llvm
comparison libcxxabi/test/test_vector1.pass.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===---------------------------- test_vector.cpp -------------------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 | |
9 #include "cxxabi.h" | |
10 | |
11 #include <iostream> | |
12 #include <cstdlib> | |
13 #include <cassert> | |
14 | |
15 // Wrapper routines | |
16 void *my_alloc2 ( size_t sz ) { | |
17 void *p = std::malloc ( sz ); | |
18 // std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p ); | |
19 return p; | |
20 } | |
21 | |
22 void my_dealloc2 ( void *p ) { | |
23 // std::printf ( "Freeing %lx\n", (unsigned long) p ); | |
24 std::free ( p ); | |
25 } | |
26 | |
27 void my_dealloc3 ( void *p, size_t ) { | |
28 // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz ); | |
29 std::free ( p ); | |
30 } | |
31 | |
32 void my_construct ( void * ) { | |
33 // std::printf ( "Constructing %lx\n", (unsigned long) p ); | |
34 } | |
35 | |
36 void my_destruct ( void * ) { | |
37 // std::printf ( "Destructing %lx\n", (unsigned long) p ); | |
38 } | |
39 | |
40 int gCounter; | |
41 void count_construct ( void * ) { ++gCounter; } | |
42 void count_destruct ( void * ) { --gCounter; } | |
43 | |
44 | |
45 int gConstructorCounter; | |
46 int gConstructorThrowTarget; | |
47 int gDestructorCounter; | |
48 int gDestructorThrowTarget; | |
49 void throw_construct ( void * ) { | |
50 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS | |
51 if ( gConstructorCounter == gConstructorThrowTarget ) | |
52 throw 1; | |
53 ++gConstructorCounter; | |
54 #endif | |
55 } | |
56 void throw_destruct ( void * ) { | |
57 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS | |
58 if ( ++gDestructorCounter == gDestructorThrowTarget ) | |
59 throw 2; | |
60 #endif | |
61 } | |
62 | |
63 #if __cplusplus >= 201103L | |
64 # define CAN_THROW noexcept(false) | |
65 #else | |
66 # define CAN_THROW | |
67 #endif | |
68 | |
69 struct vec_on_stack { | |
70 void *storage; | |
71 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {} | |
72 ~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); } | |
73 }; | |
74 | |
75 // Test calls with empty constructors and destructors | |
76 int test_empty ( ) { | |
77 void *one, *two, *three; | |
78 | |
79 // Try with no padding and no con/destructors | |
80 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL ); | |
81 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 ); | |
82 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 ); | |
83 | |
84 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL ); | |
85 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 ); | |
86 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 ); | |
87 | |
88 // Try with no padding | |
89 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct ); | |
90 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 ); | |
91 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 ); | |
92 | |
93 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, my_destruct ); | |
94 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 ); | |
95 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 ); | |
96 | |
97 // Padding and no con/destructors | |
98 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL ); | |
99 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 ); | |
100 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 ); | |
101 | |
102 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, NULL ); | |
103 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 ); | |
104 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 ); | |
105 | |
106 // Padding with con/destructors | |
107 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct ); | |
108 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 ); | |
109 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 ); | |
110 | |
111 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, my_destruct ); | |
112 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, my_destruct, my_dealloc2 ); | |
113 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 ); | |
114 | |
115 return 0; | |
116 } | |
117 | |
118 // Make sure the constructors and destructors are matched | |
119 int test_counted ( ) { | |
120 int retVal = 0; | |
121 void *one, *two, *three; | |
122 | |
123 // Try with no padding | |
124 gCounter = 0; | |
125 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct ); | |
126 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 ); | |
127 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 ); | |
128 | |
129 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct ); | |
130 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 ); | |
131 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 ); | |
132 | |
133 // Since there was no padding, the # of elements in the array are not stored | |
134 // and the destructors are not called. | |
135 if ( gCounter != 30 ) { | |
136 std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl; | |
137 std::cerr << " Expected 30, got " << gCounter << std::endl; | |
138 retVal = 1; | |
139 } | |
140 | |
141 gCounter = 0; | |
142 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct ); | |
143 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 ); | |
144 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 ); | |
145 | |
146 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, count_destruct ); | |
147 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, count_destruct, my_dealloc2 ); | |
148 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 ); | |
149 | |
150 if ( gCounter != 0 ) { | |
151 std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl; | |
152 std::cerr << " Expected 0, got " << gCounter << std::endl; | |
153 retVal = 1; | |
154 } | |
155 | |
156 return retVal; | |
157 } | |
158 | |
159 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS | |
160 // Make sure the constructors and destructors are matched | |
161 int test_exception_in_constructor ( ) { | |
162 int retVal = 0; | |
163 void *one, *two, *three; | |
164 | |
165 // Try with no padding | |
166 gConstructorCounter = gDestructorCounter = 0; | |
167 gConstructorThrowTarget = 15; | |
168 gDestructorThrowTarget = -1; | |
169 try { | |
170 one = two = three = NULL; | |
171 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct ); | |
172 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 ); | |
173 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 ); | |
174 } | |
175 catch ( int i ) {} | |
176 | |
177 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct ); | |
178 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 ); | |
179 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 ); | |
180 | |
181 // Since there was no padding, the # of elements in the array are not stored | |
182 // and the destructors are not called. | |
183 // Since we threw after 15 calls to the constructor, we should see 5 calls to | |
184 // the destructor from the partially constructed array. | |
185 if ( gConstructorCounter - gDestructorCounter != 10 ) { | |
186 std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl; | |
187 std::cerr << gConstructorCounter << " constructors, but " << | |
188 gDestructorCounter << " destructors" << std::endl; | |
189 retVal = 1; | |
190 } | |
191 | |
192 gConstructorCounter = gDestructorCounter = 0; | |
193 gConstructorThrowTarget = 15; | |
194 gDestructorThrowTarget = -1; | |
195 try { | |
196 one = two = three = NULL; | |
197 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct ); | |
198 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 ); | |
199 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 ); | |
200 } | |
201 catch ( int i ) {} | |
202 | |
203 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct ); | |
204 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 ); | |
205 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 ); | |
206 | |
207 if ( gConstructorCounter != gDestructorCounter ) { | |
208 std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl; | |
209 std::cerr << gConstructorCounter << " constructors, but " << | |
210 gDestructorCounter << " destructors" << std::endl; | |
211 retVal = 1; | |
212 } | |
213 | |
214 return retVal; | |
215 } | |
216 #endif | |
217 | |
218 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS | |
219 // Make sure the constructors and destructors are matched | |
220 int test_exception_in_destructor ( ) { | |
221 int retVal = 0; | |
222 void *one, *two, *three; | |
223 one = two = three = NULL; | |
224 | |
225 // Throw from within a destructor | |
226 gConstructorCounter = gDestructorCounter = 0; | |
227 gConstructorThrowTarget = -1; | |
228 gDestructorThrowTarget = 15; | |
229 try { | |
230 one = two = NULL; | |
231 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct ); | |
232 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 ); | |
233 } | |
234 catch ( int i ) {} | |
235 | |
236 try { | |
237 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct ); | |
238 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 ); | |
239 assert(false); | |
240 } | |
241 catch ( int i ) {} | |
242 | |
243 // We should have thrown in the middle of cleaning up "two", which means that | |
244 // there should be 20 calls to the destructor and the try block should exit | |
245 // before the assertion. | |
246 if ( gConstructorCounter != 20 || gDestructorCounter != 20 ) { | |
247 std::cerr << "Unexpected Constructor/Destructor calls (1D)" << std::endl; | |
248 std::cerr << "Expected (20, 20), but got (" << gConstructorCounter << ", " << | |
249 gDestructorCounter << ")" << std::endl; | |
250 retVal = 1; | |
251 } | |
252 | |
253 // Try throwing from a destructor - should be fine. | |
254 gConstructorCounter = gDestructorCounter = 0; | |
255 gConstructorThrowTarget = -1; | |
256 gDestructorThrowTarget = 5; | |
257 try { vec_on_stack v; } | |
258 catch ( int i ) {} | |
259 | |
260 if ( gConstructorCounter != gDestructorCounter ) { | |
261 std::cerr << "Mismatched Constructor/Destructor calls (2D)" << std::endl; | |
262 std::cerr << gConstructorCounter << " constructors, but " << | |
263 gDestructorCounter << " destructors" << std::endl; | |
264 retVal = 1; | |
265 } | |
266 | |
267 return retVal; | |
268 } | |
269 #endif | |
270 | |
271 int main () { | |
272 int retVal = 0; | |
273 retVal += test_empty (); | |
274 retVal += test_counted (); | |
275 #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS | |
276 retVal += test_exception_in_constructor (); | |
277 retVal += test_exception_in_destructor (); | |
278 #endif | |
279 return retVal; | |
280 } |