OSDN Git Service

* lib/libio.exp (test_libio): Use additional_flags, not
[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
41
42 #define my_assert( e ) \
43     if (! (e)) { \
44         GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
45                     __LINE__ ); \
46         exit( 1 ); }
47
48
49 class A {public:
50     /* An uncollectable class. */
51
52     A( int iArg ): i( iArg ) {}
53     void Test( int iArg ) {
54         my_assert( i == iArg );} 
55     int i;};
56
57
58 class B: public gc, public A {public:
59     /* A collectable class. */
60
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;};
67
68 int B::deleting = 0;
69
70
71 class C: public gc_cleanup, public A {public:
72     /* A collectable class with cleanup and virtual multiple inheritance. */
73
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 );}
91
92     static int nFreed;
93     static int nAllocated;
94     int level;
95     C* left;
96     C* right;};
97
98 int C::nFreed = 0;
99 int C::nAllocated = 0;
100
101
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. */
105
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 );}
114        
115     int i;
116     static int nFreed;
117     static int nAllocated;};
118
119 int D::nFreed = 0;
120 int D::nAllocated = 0;
121
122
123 class E: public gc_cleanup {public:
124     /* A collectable class with clean-up for use by F. */
125
126     E() {
127         nAllocated++;}
128     ~E() {
129         nFreed++;}
130
131     static int nFreed;
132     static int nAllocated;};
133     
134 int E::nFreed = 0;
135 int E::nAllocated = 0;
136    
137
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. */
141
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 );}
149        
150     E e;
151     static int nFreed;
152     static int nAllocated;};
153     
154 int F::nFreed = 0;
155 int F::nAllocated = 0;
156    
157
158 long Disguise( void* p ) {
159     return ~ (long) p;}
160
161 void* Undisguise( long i ) {
162     return (void*) ~ i;}
163
164
165 #ifdef MSWIN32
166 int APIENTRY WinMain(
167     HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) 
168 {
169     int argc;
170     char* argv[ 3 ];
171
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;}
175
176 #else
177 # ifdef MACOS
178     int main() {
179 # else
180     int main( int argc, char* argv[] ) {
181 # endif
182 #endif
183
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));
192
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 );}
199         
200     for (iters = 1; iters <= n; iters++) {
201         GC_printf1( "Starting iteration %d\n", iters );
202
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 ) );}
211
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;}
220
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
235             }
236
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
250
251             }
252
253             /* Make sure most of the finalizable Cs, Ds, and Fs have
254             gone away. */
255         C::Test();
256         D::Test();
257         F::Test();}
258
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 );}
264     
265