blob: 0f3acd2f382af68adcee5c218d12822b8f20bd98 [file] [log] [blame]
Marshall Clowe52bde42011-06-10 03:40:19 +00001//===---------------------------- test_vector.cpp -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "cxxabi.h"
11
12#include <iostream>
13#include <cstdlib>
Eric Fiselier6e50cba2014-11-21 01:53:51 +000014#include <cassert>
Marshall Clowe52bde42011-06-10 03:40:19 +000015
16// Wrapper routines
17void *my_alloc2 ( size_t sz ) {
18 void *p = std::malloc ( sz );
19// std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
20 return p;
21 }
22
23void my_dealloc2 ( void *p ) {
24// std::printf ( "Freeing %lx\n", (unsigned long) p );
25 std::free ( p );
26 }
27
Eric Fiselier08bf03c2016-12-24 00:37:13 +000028void my_dealloc3 ( void *p, size_t ) {
Marshall Clowe52bde42011-06-10 03:40:19 +000029// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
30 std::free ( p );
31 }
32
Eric Fiselier08bf03c2016-12-24 00:37:13 +000033void my_construct ( void * ) {
Marshall Clowe52bde42011-06-10 03:40:19 +000034// std::printf ( "Constructing %lx\n", (unsigned long) p );
35 }
36
Eric Fiselier08bf03c2016-12-24 00:37:13 +000037void my_destruct ( void * ) {
Marshall Clowe52bde42011-06-10 03:40:19 +000038// std::printf ( "Destructing %lx\n", (unsigned long) p );
39 }
40
41int gCounter;
Eric Fiselier08bf03c2016-12-24 00:37:13 +000042void count_construct ( void * ) { ++gCounter; }
43void count_destruct ( void * ) { --gCounter; }
Marshall Clowe52bde42011-06-10 03:40:19 +000044
45
46int gConstructorCounter;
47int gConstructorThrowTarget;
48int gDestructorCounter;
49int gDestructorThrowTarget;
Eric Fiselier08bf03c2016-12-24 00:37:13 +000050void throw_construct ( void * ) {
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000051#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
52 if ( gConstructorCounter == gConstructorThrowTarget )
53 throw 1;
54 ++gConstructorCounter;
55#endif
56}
Eric Fiselier08bf03c2016-12-24 00:37:13 +000057void throw_destruct ( void * ) {
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000058#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
59 if ( ++gDestructorCounter == gDestructorThrowTarget )
60 throw 2;
61#endif
62}
Marshall Clowe52bde42011-06-10 03:40:19 +000063
Logan Chien4856a672014-05-10 00:40:54 +000064#if __cplusplus >= 201103L
Howard Hinnant9fb57092012-01-31 20:10:33 +000065# define CAN_THROW noexcept(false)
66#else
67# define CAN_THROW
68#endif
69
Marshall Clowe52bde42011-06-10 03:40:19 +000070struct vec_on_stack {
71 void *storage;
72 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
Howard Hinnant9fb57092012-01-31 20:10:33 +000073 ~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
Marshall Clowe52bde42011-06-10 03:40:19 +000074 };
75
76// Test calls with empty constructors and destructors
77int test_empty ( ) {
78 void *one, *two, *three;
79
80// Try with no padding and no con/destructors
81 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL );
82 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 );
83 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 );
84
85 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL );
86 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 );
87 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 );
88
89// Try with no padding
90 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );
91 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );
92 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 );
93
94 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, my_destruct );
95 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 );
96 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 );
97
98// Padding and no con/destructors
99 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );
100 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );
101 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );
102
103 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, NULL );
104 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 );
105 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 );
106
107// Padding with con/destructors
108 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );
109 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );
110 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );
111
112 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, my_destruct );
113 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, my_destruct, my_dealloc2 );
114 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 );
115
116 return 0;
117 }
118
119// Make sure the constructors and destructors are matched
120int test_counted ( ) {
121 int retVal = 0;
122 void *one, *two, *three;
123
124// Try with no padding
125 gCounter = 0;
126 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );
127 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );
128 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );
129
130 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct );
131 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 );
132 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 );
133
134// Since there was no padding, the # of elements in the array are not stored
135// and the destructors are not called.
136 if ( gCounter != 30 ) {
137 std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl;
138 std::cerr << " Expected 30, got " << gCounter << std::endl;
139 retVal = 1;
140 }
141
142 gCounter = 0;
143 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );
144 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );
145 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );
146
147 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, count_destruct );
148 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, count_destruct, my_dealloc2 );
149 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 );
150
151 if ( gCounter != 0 ) {
152 std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl;
153 std::cerr << " Expected 0, got " << gCounter << std::endl;
154 retVal = 1;
155 }
156
157 return retVal;
158 }
159
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000160#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
Marshall Clowe52bde42011-06-10 03:40:19 +0000161// Make sure the constructors and destructors are matched
162int test_exception_in_constructor ( ) {
163 int retVal = 0;
164 void *one, *two, *three;
165
166// Try with no padding
167 gConstructorCounter = gDestructorCounter = 0;
168 gConstructorThrowTarget = 15;
169 gDestructorThrowTarget = -1;
170 try {
171 one = two = three = NULL;
172 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );
173 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
174 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
175 }
176 catch ( int i ) {}
177
178 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct );
179 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 );
180 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 );
181
182// Since there was no padding, the # of elements in the array are not stored
183// and the destructors are not called.
184// Since we threw after 15 calls to the constructor, we should see 5 calls to
185// the destructor from the partially constructed array.
186 if ( gConstructorCounter - gDestructorCounter != 10 ) {
187 std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl;
188 std::cerr << gConstructorCounter << " constructors, but " <<
189 gDestructorCounter << " destructors" << std::endl;
190 retVal = 1;
191 }
192
193 gConstructorCounter = gDestructorCounter = 0;
194 gConstructorThrowTarget = 15;
195 gDestructorThrowTarget = -1;
196 try {
197 one = two = three = NULL;
198 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
199 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
200 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
201 }
202 catch ( int i ) {}
203
204 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
205 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
206 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
207
208 if ( gConstructorCounter != gDestructorCounter ) {
209 std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl;
210 std::cerr << gConstructorCounter << " constructors, but " <<
211 gDestructorCounter << " destructors" << std::endl;
212 retVal = 1;
213 }
214
215 return retVal;
216 }
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000217#endif
Marshall Clowe52bde42011-06-10 03:40:19 +0000218
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000219#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
Marshall Clow3050a5b2011-06-13 17:57:10 +0000220// Make sure the constructors and destructors are matched
221int test_exception_in_destructor ( ) {
222 int retVal = 0;
223 void *one, *two, *three;
Eric Fiselier6e50cba2014-11-21 01:53:51 +0000224 one = two = three = NULL;
Marshall Clow3050a5b2011-06-13 17:57:10 +0000225
226// Throw from within a destructor
227 gConstructorCounter = gDestructorCounter = 0;
228 gConstructorThrowTarget = -1;
229 gDestructorThrowTarget = 15;
230 try {
Eric Fiselier6e50cba2014-11-21 01:53:51 +0000231 one = two = NULL;
Marshall Clow3050a5b2011-06-13 17:57:10 +0000232 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
233 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
Marshall Clow3050a5b2011-06-13 17:57:10 +0000234 }
235 catch ( int i ) {}
236
237 try {
238 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
239 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
Eric Fiselier6e50cba2014-11-21 01:53:51 +0000240 assert(false);
Marshall Clow3050a5b2011-06-13 17:57:10 +0000241 }
242 catch ( int i ) {}
243
244// We should have thrown in the middle of cleaning up "two", which means that
Eric Fiselier6e50cba2014-11-21 01:53:51 +0000245// there should be 20 calls to the destructor and the try block should exit
246// before the assertion.
247 if ( gConstructorCounter != 20 || gDestructorCounter != 20 ) {
Marshall Clow3050a5b2011-06-13 17:57:10 +0000248 std::cerr << "Unexpected Constructor/Destructor calls (1D)" << std::endl;
Eric Fiselier6e50cba2014-11-21 01:53:51 +0000249 std::cerr << "Expected (20, 20), but got (" << gConstructorCounter << ", " <<
Marshall Clow3050a5b2011-06-13 17:57:10 +0000250 gDestructorCounter << ")" << std::endl;
251 retVal = 1;
252 }
253
254// Try throwing from a destructor - should be fine.
255 gConstructorCounter = gDestructorCounter = 0;
256 gConstructorThrowTarget = -1;
257 gDestructorThrowTarget = 5;
258 try { vec_on_stack v; }
259 catch ( int i ) {}
260
261 if ( gConstructorCounter != gDestructorCounter ) {
262 std::cerr << "Mismatched Constructor/Destructor calls (2D)" << std::endl;
263 std::cerr << gConstructorCounter << " constructors, but " <<
264 gDestructorCounter << " destructors" << std::endl;
265 retVal = 1;
266 }
267
268 return retVal;
269 }
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000270#endif
Marshall Clowe52bde42011-06-10 03:40:19 +0000271
Eric Fiselier08bf03c2016-12-24 00:37:13 +0000272int main () {
Marshall Clowe52bde42011-06-10 03:40:19 +0000273 int retVal = 0;
274 retVal += test_empty ();
275 retVal += test_counted ();
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000276#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
Marshall Clowe52bde42011-06-10 03:40:19 +0000277 retVal += test_exception_in_constructor ();
Marshall Clow3050a5b2011-06-13 17:57:10 +0000278 retVal += test_exception_in_destructor ();
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +0000279#endif
Marshall Clowe52bde42011-06-10 03:40:19 +0000280 return retVal;
281 }