2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / boehm-gc / tests / test_cpp.cc
blob6661e411927fba49ccc3d45dac85756ad4ad2d21
1 /****************************************************************************
2 Copyright (c) 1994 by Xerox Corporation. All rights reserved.
4 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
7 Permission is hereby granted to use or copy this program for any
8 purpose, provided the above notices are retained on all copies.
9 Permission to modify the code and to distribute modified code is
10 granted, provided the above notices are retained, and a notice that
11 the code was modified is included with the above copyright notice.
12 ****************************************************************************
13 Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
14 modified on December 20, 1994 7:27 pm PST by boehm
16 usage: test_cpp number-of-iterations
18 This program tries to test the specific C++ functionality provided by
19 gc_c++.h that isn't tested by the more general test routines of the
20 collector.
22 A recommended value for number-of-iterations is 10, which will take a
23 few minutes to complete.
25 ***************************************************************************/
27 #include "gc_cpp.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #define USE_STD_ALLOCATOR
32 #ifdef USE_STD_ALLOCATOR
33 # include "gc_allocator.h"
34 #elif __GNUC__
35 # include "new_gc_alloc.h"
36 #else
37 # include "gc_alloc.h"
38 #endif
39 extern "C" {
40 #include "private/gc_priv.h"
42 #ifdef MSWIN32
43 # include <windows.h>
44 #endif
45 #ifdef GC_NAME_CONFLICT
46 # define USE_GC UseGC
47 struct foo * GC;
48 #else
49 # define USE_GC GC
50 #endif
53 #define my_assert( e ) \
54 if (! (e)) { \
55 GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
56 __LINE__ ); \
57 exit( 1 ); }
60 class A {public:
61 /* An uncollectable class. */
63 A( int iArg ): i( iArg ) {}
64 void Test( int iArg ) {
65 my_assert( i == iArg );}
66 int i;};
69 class B: public gc, public A {public:
70 /* A collectable class. */
72 B( int j ): A( j ) {}
73 ~B() {
74 my_assert( deleting );}
75 static void Deleting( int on ) {
76 deleting = on;}
77 static int deleting;};
79 int B::deleting = 0;
82 class C: public gc_cleanup, public A {public:
83 /* A collectable class with cleanup and virtual multiple inheritance. */
85 C( int levelArg ): A( levelArg ), level( levelArg ) {
86 nAllocated++;
87 if (level > 0) {
88 left = new C( level - 1 );
89 right = new C( level - 1 );}
90 else {
91 left = right = 0;}}
92 ~C() {
93 this->A::Test( level );
94 nFreed++;
95 my_assert( level == 0 ?
96 left == 0 && right == 0 :
97 level == left->level + 1 && level == right->level + 1 );
98 left = right = 0;
99 level = -123456;}
100 static void Test() {
101 my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
103 static int nFreed;
104 static int nAllocated;
105 int level;
106 C* left;
107 C* right;};
109 int C::nFreed = 0;
110 int C::nAllocated = 0;
113 class D: public gc {public:
114 /* A collectable class with a static member function to be used as
115 an explicit clean-up function supplied to ::new. */
117 D( int iArg ): i( iArg ) {
118 nAllocated++;}
119 static void CleanUp( void* obj, void* data ) {
120 D* self = (D*) obj;
121 nFreed++;
122 my_assert( self->i == (int) (long) data );}
123 static void Test() {
124 my_assert( nFreed >= .8 * nAllocated );}
126 int i;
127 static int nFreed;
128 static int nAllocated;};
130 int D::nFreed = 0;
131 int D::nAllocated = 0;
134 class E: public gc_cleanup {public:
135 /* A collectable class with clean-up for use by F. */
137 E() {
138 nAllocated++;}
139 ~E() {
140 nFreed++;}
142 static int nFreed;
143 static int nAllocated;};
145 int E::nFreed = 0;
146 int E::nAllocated = 0;
149 class F: public E {public:
150 /* A collectable class with clean-up, a base with clean-up, and a
151 member with clean-up. */
153 F() {
154 nAllocated++;}
155 ~F() {
156 nFreed++;}
157 static void Test() {
158 my_assert( nFreed >= .8 * nAllocated );
159 my_assert( 2 * nFreed == E::nFreed );}
161 E e;
162 static int nFreed;
163 static int nAllocated;};
165 int F::nFreed = 0;
166 int F::nAllocated = 0;
169 long Disguise( void* p ) {
170 return ~ (long) p;}
172 void* Undisguise( long i ) {
173 return (void*) ~ i;}
176 #ifdef MSWIN32
177 int APIENTRY WinMain(
178 HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
180 int argc;
181 char* argv[ 3 ];
183 for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
184 argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
185 if (0 == argv[ argc ]) break;}
187 #else
188 # ifdef MACOS
189 int main() {
190 # else
191 int main( int argc, char* argv[] ) {
192 # endif
193 #endif
195 GC_INIT();
197 # if defined(MACOS) // MacOS
198 char* argv_[] = {"test_cpp", "10"}; // doesn't
199 argv = argv_; // have a
200 argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
201 # endif
202 int i, iters, n;
203 # ifdef USE_STD_ALLOCATOR
204 int *x = gc_allocator<int>().allocate(1);
205 int **xptr = traceable_allocator<int *>().allocate(1);
206 # else
207 # ifdef __GNUC__
208 int *x = (int *)gc_alloc::allocate(sizeof(int));
209 # else
210 int *x = (int *)alloc::allocate(sizeof(int));
211 # endif
212 # endif
213 *x = 29;
214 # ifdef USE_STD_ALLOCATOR
215 *xptr = x;
216 x = 0;
217 # endif
218 if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
219 GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
220 n = 10;}
222 for (iters = 1; iters <= n; iters++) {
223 GC_printf1( "Starting iteration %d\n", iters );
225 /* Allocate some uncollectable As and disguise their pointers.
226 Later we'll check to see if the objects are still there. We're
227 checking to make sure these objects really are uncollectable. */
228 long as[ 1000 ];
229 long bs[ 1000 ];
230 for (i = 0; i < 1000; i++) {
231 as[ i ] = Disguise( new (NoGC) A( i ) );
232 bs[ i ] = Disguise( new (NoGC) B( i ) );}
234 /* Allocate a fair number of finalizable Cs, Ds, and Fs.
235 Later we'll check to make sure they've gone away. */
236 for (i = 0; i < 1000; i++) {
237 C* c = new C( 2 );
238 C c1( 2 ); /* stack allocation should work too */
239 D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
240 F* f = new F;
241 if (0 == i % 10) delete c;}
243 /* Allocate a very large number of collectable As and Bs and
244 drop the references to them immediately, forcing many
245 collections. */
246 for (i = 0; i < 1000000; i++) {
247 A* a = new (USE_GC) A( i );
248 B* b = new B( i );
249 b = new (USE_GC) B( i );
250 if (0 == i % 10) {
251 B::Deleting( 1 );
252 delete b;
253 B::Deleting( 0 );}
254 # ifdef FINALIZE_ON_DEMAND
255 GC_invoke_finalizers();
256 # endif
259 /* Make sure the uncollectable As and Bs are still there. */
260 for (i = 0; i < 1000; i++) {
261 A* a = (A*) Undisguise( as[ i ] );
262 B* b = (B*) Undisguise( bs[ i ] );
263 a->Test( i );
264 delete a;
265 b->Test( i );
266 B::Deleting( 1 );
267 delete b;
268 B::Deleting( 0 );
269 # ifdef FINALIZE_ON_DEMAND
270 GC_invoke_finalizers();
271 # endif
275 /* Make sure most of the finalizable Cs, Ds, and Fs have
276 gone away. */
277 C::Test();
278 D::Test();
279 F::Test();}
281 # ifdef USE_STD_ALLOCATOR
282 x = *xptr;
283 # endif
284 my_assert (29 == x[0]);
285 GC_printf0( "The test appears to have succeeded.\n" );
286 return( 0 );}