* Makefile.in (PREPROCESSOR_DEFINES): New macro.
[official-gcc.git] / boehm-gc / test_cpp.cc
blob3160b0984bb340b923f7108580907c0ae99c8c87
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
42 #define my_assert( e ) \
43 if (! (e)) { \
44 GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
45 __LINE__ ); \
46 exit( 1 ); }
49 class A {public:
50 /* An uncollectable class. */
52 A( int iArg ): i( iArg ) {}
53 void Test( int iArg ) {
54 my_assert( i == iArg );}
55 int i;};
58 class B: public gc, public A {public:
59 /* A collectable class. */
61 B( int j ): A( j ) {}
62 ~B() {
63 my_assert( deleting );}
64 static void Deleting( int on ) {
65 deleting = on;}
66 static int deleting;};
68 int B::deleting = 0;
71 class C: public gc_cleanup, public A {public:
72 /* A collectable class with cleanup and virtual multiple inheritance. */
74 C( int levelArg ): A( levelArg ), level( levelArg ) {
75 nAllocated++;
76 if (level > 0) {
77 left = new C( level - 1 );
78 right = new C( level - 1 );}
79 else {
80 left = right = 0;}}
81 ~C() {
82 this->A::Test( level );
83 nFreed++;
84 my_assert( level == 0 ?
85 left == 0 && right == 0 :
86 level == left->level + 1 && level == right->level + 1 );
87 left = right = 0;
88 level = -123456;}
89 static void Test() {
90 my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
92 static int nFreed;
93 static int nAllocated;
94 int level;
95 C* left;
96 C* right;};
98 int C::nFreed = 0;
99 int C::nAllocated = 0;
102 class D: public gc {public:
103 /* A collectable class with a static member function to be used as
104 an explicit clean-up function supplied to ::new. */
106 D( int iArg ): i( iArg ) {
107 nAllocated++;}
108 static void CleanUp( void* obj, void* data ) {
109 D* self = (D*) obj;
110 nFreed++;
111 my_assert( self->i == (int) (long) data );}
112 static void Test() {
113 my_assert( nFreed >= .8 * nAllocated );}
115 int i;
116 static int nFreed;
117 static int nAllocated;};
119 int D::nFreed = 0;
120 int D::nAllocated = 0;
123 class E: public gc_cleanup {public:
124 /* A collectable class with clean-up for use by F. */
126 E() {
127 nAllocated++;}
128 ~E() {
129 nFreed++;}
131 static int nFreed;
132 static int nAllocated;};
134 int E::nFreed = 0;
135 int E::nAllocated = 0;
138 class F: public E {public:
139 /* A collectable class with clean-up, a base with clean-up, and a
140 member with clean-up. */
142 F() {
143 nAllocated++;}
144 ~F() {
145 nFreed++;}
146 static void Test() {
147 my_assert( nFreed >= .8 * nAllocated );
148 my_assert( 2 * nFreed == E::nFreed );}
150 E e;
151 static int nFreed;
152 static int nAllocated;};
154 int F::nFreed = 0;
155 int F::nAllocated = 0;
158 long Disguise( void* p ) {
159 return ~ (long) p;}
161 void* Undisguise( long i ) {
162 return (void*) ~ i;}
165 #ifdef MSWIN32
166 int APIENTRY WinMain(
167 HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
169 int argc;
170 char* argv[ 3 ];
172 for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
173 argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
174 if (0 == argv[ argc ]) break;}
176 #else
177 # ifdef MACOS
178 int main() {
179 # else
180 int main( int argc, char* argv[] ) {
181 # endif
182 #endif
184 # if defined(MACOS) // MacOS
185 char* argv_[] = {"test_cpp", "10"}; // doesn't
186 argv = argv_; // have a
187 argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
188 # endif
189 int i, iters, n;
190 # if !defined(__GNUC__) && !defined(MACOS)
191 int *x = (int *)alloc::allocate(sizeof(int));
193 *x = 29;
194 x -= 3;
195 # endif
196 if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
197 GC_printf0( "usage: test_cpp number-of-iterations\n" );
198 exit( 1 );}
200 for (iters = 1; iters <= n; iters++) {
201 GC_printf1( "Starting iteration %d\n", iters );
203 /* Allocate some uncollectable As and disguise their pointers.
204 Later we'll check to see if the objects are still there. We're
205 checking to make sure these objects really are uncollectable. */
206 long as[ 1000 ];
207 long bs[ 1000 ];
208 for (i = 0; i < 1000; i++) {
209 as[ i ] = Disguise( new (NoGC) A( i ) );
210 bs[ i ] = Disguise( new (NoGC) B( i ) );}
212 /* Allocate a fair number of finalizable Cs, Ds, and Fs.
213 Later we'll check to make sure they've gone away. */
214 for (i = 0; i < 1000; i++) {
215 C* c = new C( 2 );
216 C c1( 2 ); /* stack allocation should work too */
217 D* d = ::new (GC, D::CleanUp, (void*) i) D( i );
218 F* f = new F;
219 if (0 == i % 10) delete c;}
221 /* Allocate a very large number of collectable As and Bs and
222 drop the references to them immediately, forcing many
223 collections. */
224 for (i = 0; i < 1000000; i++) {
225 A* a = new (GC) A( i );
226 B* b = new B( i );
227 b = new (GC) B( i );
228 if (0 == i % 10) {
229 B::Deleting( 1 );
230 delete b;
231 B::Deleting( 0 );}
232 # ifdef FINALIZE_ON_DEMAND
233 GC_invoke_finalizers();
234 # endif
237 /* Make sure the uncollectable As and Bs are still there. */
238 for (i = 0; i < 1000; i++) {
239 A* a = (A*) Undisguise( as[ i ] );
240 B* b = (B*) Undisguise( bs[ i ] );
241 a->Test( i );
242 delete a;
243 b->Test( i );
244 B::Deleting( 1 );
245 delete b;
246 B::Deleting( 0 );
247 # ifdef FINALIZE_ON_DEMAND
248 GC_invoke_finalizers();
249 # endif
253 /* Make sure most of the finalizable Cs, Ds, and Fs have
254 gone away. */
255 C::Test();
256 D::Test();
257 F::Test();}
259 # if !defined(__GNUC__) && !defined(MACOS)
260 my_assert (29 == x[3]);
261 # endif
262 GC_printf0( "The test appears to have succeeded.\n" );
263 return( 0 );}