1 //===---------------------------- test_vector.cpp -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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 );
22 void my_dealloc2 ( void *p ) {
23 // std::printf ( "Freeing %lx\n", (unsigned long) p );
27 void my_dealloc3 ( void *p, size_t sz ) {
28 // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
32 void my_construct ( void *p ) {
33 // std::printf ( "Constructing %lx\n", (unsigned long) p );
36 void my_destruct ( void *p ) {
37 // std::printf ( "Destructing %lx\n", (unsigned long) p );
41 void count_construct ( void *p ) { ++gCounter; }
42 void count_destruct ( void *p ) { --gCounter; }
45 int gConstructorCounter;
46 int gConstructorThrowTarget;
47 int gDestructorCounter;
48 int gDestructorThrowTarget;
49 void throw_construct ( void *p ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; }
50 void throw_destruct ( void *p ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; }
52 #if __cplusplus >= 201103L
53 # define CAN_THROW noexcept(false)
60 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
61 ~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
64 // Test calls with empty constructors and destructors
66 void *one, *two, *three;
68 // Try with no padding and no con/destructors
69 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL );
70 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 );
71 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 );
73 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL );
74 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 );
75 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 );
77 // Try with no padding
78 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );
79 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );
80 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 );
82 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, my_destruct );
83 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 );
84 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 );
86 // Padding and no con/destructors
87 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );
88 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );
89 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );
91 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, NULL );
92 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 );
93 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 );
95 // Padding with con/destructors
96 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );
97 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );
98 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );
100 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, my_destruct );
101 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, my_destruct, my_dealloc2 );
102 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 );
107 // Make sure the constructors and destructors are matched
108 int test_counted ( ) {
110 void *one, *two, *three;
112 // Try with no padding
114 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );
115 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );
116 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );
118 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct );
119 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 );
120 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 );
122 // Since there was no padding, the # of elements in the array are not stored
123 // and the destructors are not called.
124 if ( gCounter != 30 ) {
125 std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl;
126 std::cerr << " Expected 30, got " << gCounter << std::endl;
131 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );
132 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );
133 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );
135 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, count_destruct );
136 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, count_destruct, my_dealloc2 );
137 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 );
139 if ( gCounter != 0 ) {
140 std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl;
141 std::cerr << " Expected 0, got " << gCounter << std::endl;
148 // Make sure the constructors and destructors are matched
149 int test_exception_in_constructor ( ) {
151 void *one, *two, *three;
153 // Try with no padding
154 gConstructorCounter = gDestructorCounter = 0;
155 gConstructorThrowTarget = 15;
156 gDestructorThrowTarget = -1;
158 one = two = three = NULL;
159 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );
160 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
161 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
165 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct );
166 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 );
167 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 );
169 // Since there was no padding, the # of elements in the array are not stored
170 // and the destructors are not called.
171 // Since we threw after 15 calls to the constructor, we should see 5 calls to
172 // the destructor from the partially constructed array.
173 if ( gConstructorCounter - gDestructorCounter != 10 ) {
174 std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl;
175 std::cerr << gConstructorCounter << " constructors, but " <<
176 gDestructorCounter << " destructors" << std::endl;
180 gConstructorCounter = gDestructorCounter = 0;
181 gConstructorThrowTarget = 15;
182 gDestructorThrowTarget = -1;
184 one = two = three = NULL;
185 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
186 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
187 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
191 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
192 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
193 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
195 if ( gConstructorCounter != gDestructorCounter ) {
196 std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl;
197 std::cerr << gConstructorCounter << " constructors, but " <<
198 gDestructorCounter << " destructors" << std::endl;
205 // Make sure the constructors and destructors are matched
206 int test_exception_in_destructor ( ) {
208 void *one, *two, *three;
210 // Throw from within a destructor
211 gConstructorCounter = gDestructorCounter = 0;
212 gConstructorThrowTarget = -1;
213 gDestructorThrowTarget = 15;
215 one = two = three = NULL;
216 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
217 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
218 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
223 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
224 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
225 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
229 // We should have thrown in the middle of cleaning up "two", which means that
230 // there should be 20 calls to the destructor, and "three" was not cleaned up.
231 if ( gConstructorCounter != 30 || gDestructorCounter != 20 ) {
232 std::cerr << "Unexpected Constructor/Destructor calls (1D)" << std::endl;
233 std::cerr << "Expected (30, 20), but got (" << gConstructorCounter << ", " <<
234 gDestructorCounter << ")" << std::endl;
238 // Try throwing from a destructor - should be fine.
239 gConstructorCounter = gDestructorCounter = 0;
240 gConstructorThrowTarget = -1;
241 gDestructorThrowTarget = 5;
242 try { vec_on_stack v; }
245 if ( gConstructorCounter != gDestructorCounter ) {
246 std::cerr << "Mismatched Constructor/Destructor calls (2D)" << std::endl;
247 std::cerr << gConstructorCounter << " constructors, but " <<
248 gDestructorCounter << " destructors" << std::endl;
255 int main ( int argc, char *argv [] ) {
257 retVal += test_empty ();
258 retVal += test_counted ();
259 retVal += test_exception_in_constructor ();
260 retVal += test_exception_in_destructor ();