OSDN Git Service

* Makefile.in (local-distclean): Remove leftover built files.
[pf3gnuchains/gcc-fork.git] / boehm-gc / test_cpp.cc
1 /****************************************************************************
2 Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
3  
4 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  
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
15
16 usage: test_cpp number-of-iterations
17
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.
21
22 A recommended value for number-of-iterations is 10, which will take a
23 few minutes to complete.
24
25 ***************************************************************************/
26
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"
36 }
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
46
47
48 #define my_assert( e ) \
49     if (! (e)) { \
50         GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
51                     __LINE__ ); \
52         exit( 1 ); }
53
54
55 class A {public:
56     /* An uncollectable class. */
57
58     A( int iArg ): i( iArg ) {}
59     void Test( int iArg ) {
60         my_assert( i == iArg );} 
61     int i;};
62
63
64 class B: public gc, public A {public:
65     /* A collectable class. */
66
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;};
73
74 int B::deleting = 0;
75
76
77 class C: public gc_cleanup, public A {public:
78     /* A collectable class with cleanup and virtual multiple inheritance. */
79
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 );}
97
98     static int nFreed;
99     static int nAllocated;
100     int level;
101     C* left;
102     C* right;};
103
104 int C::nFreed = 0;
105 int C::nAllocated = 0;
106
107
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. */
111
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 );}
120        
121     int i;
122     static int nFreed;
123     static int nAllocated;};
124
125 int D::nFreed = 0;
126 int D::nAllocated = 0;
127
128
129 class E: public gc_cleanup {public:
130     /* A collectable class with clean-up for use by F. */
131
132     E() {
133         nAllocated++;}
134     ~E() {
135         nFreed++;}
136
137     static int nFreed;
138     static int nAllocated;};
139     
140 int E::nFreed = 0;
141 int E::nAllocated = 0;
142    
143
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. */
147
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 );}
155        
156     E e;
157     static int nFreed;
158     static int nAllocated;};
159     
160 int F::nFreed = 0;
161 int F::nAllocated = 0;
162    
163
164 long Disguise( void* p ) {
165     return ~ (long) p;}
166
167 void* Undisguise( long i ) {
168     return (void*) ~ i;}
169
170
171 #ifdef MSWIN32
172 int APIENTRY WinMain(
173     HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) 
174 {
175     int argc;
176     char* argv[ 3 ];
177
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;}
181
182 #else
183 # ifdef MACOS
184     int main() {
185 # else
186     int main( int argc, char* argv[] ) {
187 # endif
188 #endif
189
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));
198
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 );}
205         
206     for (iters = 1; iters <= n; iters++) {
207         GC_printf1( "Starting iteration %d\n", iters );
208
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 ) );}
217
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;}
226
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
241             }
242
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
256
257             }
258
259             /* Make sure most of the finalizable Cs, Ds, and Fs have
260             gone away. */
261         C::Test();
262         D::Test();
263         F::Test();}
264
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 );}
270     
271