blob: 2a539d4d4a3704edca2fd350b96aac03e898dc38 [file] [log] [blame]
Marshall Clow280ddee2011-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>
14
15// Wrapper routines
16void *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
22void my_dealloc2 ( void *p ) {
23// std::printf ( "Freeing %lx\n", (unsigned long) p );
24 std::free ( p );
25 }
26
27void my_dealloc3 ( void *p, size_t sz ) {
28// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
29 std::free ( p );
30 }
31
32void my_construct ( void *p ) {
33// std::printf ( "Constructing %lx\n", (unsigned long) p );
34 }
35
36void my_destruct ( void *p ) {
37// std::printf ( "Destructing %lx\n", (unsigned long) p );
38 }
39
40int gCounter;
41void count_construct ( void *p ) { ++gCounter; }
42void count_destruct ( void *p ) { --gCounter; }
43
44
45int gConstructorCounter;
46int gConstructorThrowTarget;
47int gDestructorCounter;
48int gDestructorThrowTarget;
49void throw_construct ( void *p ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; }
50void throw_destruct ( void *p ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; }
51
52struct vec_on_stack {
53 void *storage;
54 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
55 ~vec_on_stack () { __cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
56 };
57
58// Test calls with empty constructors and destructors
59int test_empty ( ) {
60 void *one, *two, *three;
61
62// Try with no padding and no con/destructors
63 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL );
64 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 );
65 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 );
66
67 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL );
68 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 );
69 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 );
70
71// Try with no padding
72 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );
73 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );
74 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 );
75
76 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, my_destruct );
77 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 );
78 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 );
79
80// Padding and no con/destructors
81 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );
82 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );
83 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );
84
85 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, NULL );
86 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 );
87 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 );
88
89// Padding with con/destructors
90 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );
91 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );
92 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );
93
94 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, my_destruct );
95 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, my_destruct, my_dealloc2 );
96 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 );
97
98 return 0;
99 }
100
101// Make sure the constructors and destructors are matched
102int test_counted ( ) {
103 int retVal = 0;
104 void *one, *two, *three;
105
106// Try with no padding
107 gCounter = 0;
108 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );
109 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );
110 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );
111
112 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct );
113 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 );
114 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 );
115
116// Since there was no padding, the # of elements in the array are not stored
117// and the destructors are not called.
118 if ( gCounter != 30 ) {
119 std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl;
120 std::cerr << " Expected 30, got " << gCounter << std::endl;
121 retVal = 1;
122 }
123
124 gCounter = 0;
125 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );
126 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );
127 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );
128
129 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, count_destruct );
130 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, count_destruct, my_dealloc2 );
131 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 );
132
133 if ( gCounter != 0 ) {
134 std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl;
135 std::cerr << " Expected 0, got " << gCounter << std::endl;
136 retVal = 1;
137 }
138
139 return retVal;
140 }
141
142// Make sure the constructors and destructors are matched
143int test_exception_in_constructor ( ) {
144 int retVal = 0;
145 void *one, *two, *three;
146
147// Try with no padding
148 gConstructorCounter = gDestructorCounter = 0;
149 gConstructorThrowTarget = 15;
150 gDestructorThrowTarget = -1;
151 try {
152 one = two = three = NULL;
153 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );
154 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
155 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
156 }
157 catch ( int i ) {}
158
159 __cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct );
160 __cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 );
161 __cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 );
162
163// Since there was no padding, the # of elements in the array are not stored
164// and the destructors are not called.
165// Since we threw after 15 calls to the constructor, we should see 5 calls to
166// the destructor from the partially constructed array.
167 if ( gConstructorCounter - gDestructorCounter != 10 ) {
168 std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl;
169 std::cerr << gConstructorCounter << " constructors, but " <<
170 gDestructorCounter << " destructors" << std::endl;
171 retVal = 1;
172 }
173
174 gConstructorCounter = gDestructorCounter = 0;
175 gConstructorThrowTarget = 15;
176 gDestructorThrowTarget = -1;
177 try {
178 one = two = three = NULL;
179 one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
180 two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
181 three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
182 }
183 catch ( int i ) {}
184
185 __cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
186 __cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
187 __cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
188
189 if ( gConstructorCounter != gDestructorCounter ) {
190 std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl;
191 std::cerr << gConstructorCounter << " constructors, but " <<
192 gDestructorCounter << " destructors" << std::endl;
193 retVal = 1;
194 }
195
196 return retVal;
197 }
198
199void my_terminate () { exit ( 0 ); }
200
201int main ( int argc, char *argv [] ) {
202 int retVal = 0;
203 retVal += test_empty ();
204 retVal += test_counted ();
205 retVal += test_exception_in_constructor ();
206 return retVal;
207 }