* texi2pod.pl: Add copyright and GPL notices.
[official-gcc.git] / boehm-gc / test_cpp.cc
blob0d45077658f495a15dfa240162316e5a78a63eb1
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 #ifndef __GNUC__
32 # include "gc_alloc.h"
33 #endif
34 extern "C" {
35 #include "gc_priv.h"
37 #ifdef MSWIN32
38 # include <windows.h>
39 #endif
40 #ifdef GC_NAME_CONFLICT
41 # define USE_GC UseGC
42 struct foo * GC;
43 #else
44 # define USE_GC GC
45 #endif
48 #define my_assert( e ) \
49 if (! (e)) { \
50 GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
51 __LINE__ ); \
52 exit( 1 ); }
55 class A {public:
56 /* An uncollectable class. */
58 A( int iArg ): i( iArg ) {}
59 void Test( int iArg ) {
60 my_assert( i == iArg );}
61 int i;};
64 class B: public gc, public A {public:
65 /* A collectable class. */
67 B( int j ): A( j ) {}
68 ~B() {
69 my_assert( deleting );}
70 static void Deleting( int on ) {
71 deleting = on;}
72 static int deleting;};
74 int B::deleting = 0;
77 class C: public gc_cleanup, public A {public:
78 /* A collectable class with cleanup and virtual multiple inheritance. */
80 C( int levelArg ): A( levelArg ), level( levelArg ) {
81 nAllocated++;
82 if (level > 0) {
83 left = new C( level - 1 );
84 right = new C( level - 1 );}
85 else {
86 left = right = 0;}}
87 ~C() {
88 this->A::Test( level );
89 nFreed++;
90 my_assert( level == 0 ?
91 left == 0 && right == 0 :
92 level == left->level + 1 && level == right->level + 1 );
93 left = right = 0;
94 level = -123456;}
95 static void Test() {
96 my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
98 static int nFreed;
99 static int nAllocated;
100 int level;
101 C* left;
102 C* right;};
104 int C::nFreed = 0;
105 int C::nAllocated = 0;
108 class D: public gc {public:
109 /* A collectable class with a static member function to be used as
110 an explicit clean-up function supplied to ::new. */
112 D( int iArg ): i( iArg ) {
113 nAllocated++;}
114 static void CleanUp( void* obj, void* data ) {
115 D* self = (D*) obj;
116 nFreed++;
117 my_assert( self->i == (int) (long) data );}
118 static void Test() {
119 my_assert( nFreed >= .8 * nAllocated );}
121 int i;
122 static int nFreed;
123 static int nAllocated;};
125 int D::nFreed = 0;
126 int D::nAllocated = 0;
129 class E: public gc_cleanup {public:
130 /* A collectable class with clean-up for use by F. */
132 E() {
133 nAllocated++;}
134 ~E() {
135 nFreed++;}
137 static int nFreed;
138 static int nAllocated;};
140 int E::nFreed = 0;
141 int E::nAllocated = 0;
144 class F: public E {public:
145 /* A collectable class with clean-up, a base with clean-up, and a
146 member with clean-up. */
148 F() {
149 nAllocated++;}
150 ~F() {
151 nFreed++;}
152 static void Test() {
153 my_assert( nFreed >= .8 * nAllocated );
154 my_assert( 2 * nFreed == E::nFreed );}
156 E e;
157 static int nFreed;
158 static int nAllocated;};
160 int F::nFreed = 0;
161 int F::nAllocated = 0;
164 long Disguise( void* p ) {
165 return ~ (long) p;}
167 void* Undisguise( long i ) {
168 return (void*) ~ i;}
171 #ifdef MSWIN32
172 int APIENTRY WinMain(
173 HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
175 int argc;
176 char* argv[ 3 ];
178 for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
179 argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
180 if (0 == argv[ argc ]) break;}
182 #else
183 # ifdef MACOS
184 int main() {
185 # else
186 int main( int argc, char* argv[] ) {
187 # endif
188 #endif
190 # if defined(MACOS) // MacOS
191 char* argv_[] = {"test_cpp", "10"}; // doesn't
192 argv = argv_; // have a
193 argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
194 # endif
195 int i, iters, n;
196 # if !defined(__GNUC__) && !defined(MACOS)
197 int *x = (int *)alloc::allocate(sizeof(int));
199 *x = 29;
200 x -= 3;
201 # endif
202 if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
203 GC_printf0( "usage: test_cpp number-of-iterations\n" );
204 exit( 1 );}
206 for (iters = 1; iters <= n; iters++) {
207 GC_printf1( "Starting iteration %d\n", iters );
209 /* Allocate some uncollectable As and disguise their pointers.
210 Later we'll check to see if the objects are still there. We're
211 checking to make sure these objects really are uncollectable. */
212 long as[ 1000 ];
213 long bs[ 1000 ];
214 for (i = 0; i < 1000; i++) {
215 as[ i ] = Disguise( new (NoGC) A( i ) );
216 bs[ i ] = Disguise( new (NoGC) B( i ) );}
218 /* Allocate a fair number of finalizable Cs, Ds, and Fs.
219 Later we'll check to make sure they've gone away. */
220 for (i = 0; i < 1000; i++) {
221 C* c = new C( 2 );
222 C c1( 2 ); /* stack allocation should work too */
223 D* d = ::new (USE_GC, D::CleanUp, (void*) i) D( i );
224 F* f = new F;
225 if (0 == i % 10) delete c;}
227 /* Allocate a very large number of collectable As and Bs and
228 drop the references to them immediately, forcing many
229 collections. */
230 for (i = 0; i < 1000000; i++) {
231 A* a = new (USE_GC) A( i );
232 B* b = new B( i );
233 b = new (USE_GC) B( i );
234 if (0 == i % 10) {
235 B::Deleting( 1 );
236 delete b;
237 B::Deleting( 0 );}
238 # ifdef FINALIZE_ON_DEMAND
239 GC_invoke_finalizers();
240 # endif
243 /* Make sure the uncollectable As and Bs are still there. */
244 for (i = 0; i < 1000; i++) {
245 A* a = (A*) Undisguise( as[ i ] );
246 B* b = (B*) Undisguise( bs[ i ] );
247 a->Test( i );
248 delete a;
249 b->Test( i );
250 B::Deleting( 1 );
251 delete b;
252 B::Deleting( 0 );
253 # ifdef FINALIZE_ON_DEMAND
254 GC_invoke_finalizers();
255 # endif
259 /* Make sure most of the finalizable Cs, Ds, and Fs have
260 gone away. */
261 C::Test();
262 D::Test();
263 F::Test();}
265 # if !defined(__GNUC__) && !defined(MACOS)
266 my_assert (29 == x[3]);
267 # endif
268 GC_printf0( "The test appears to have succeeded.\n" );
269 return( 0 );}