1 // { dg-do run  }
2 // Test __cxa_vec routines
3 // Copyright (C) 2000 Free Software Foundation, Inc.
4 // Contributed by Nathan Sidwell 7 Apr 2000 <nathan@nathan@codesourcery.com>
5 
6 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
7 #include <cxxabi.h>
8 #include <stdio.h>
9 #include <new>
10 #include <stdlib.h>
11 #include <setjmp.h>
12 
13 static int ctor_count = 0;
14 static int dtor_count = 0;
15 static bool dtor_repeat = false;
16 
17 // our pseudo ctors and dtors
ctor(void *)18 static void ctor (void *)
19 {
20   if (!ctor_count)
21     throw 1;
22   ctor_count--;
23 }
24 
dtor(void *)25 static void dtor (void *)
26 {
27   if (!dtor_count)
28     {
29       if (!dtor_repeat)
30         dtor_count--;
31       throw 1;
32     }
33   dtor_count--;
34 }
35 
36 // track new and delete
37 static int blocks = 0;
throw(std::bad_alloc)38 void *operator new[] (std::size_t size) throw (std::bad_alloc)
39 {
40   void *ptr = malloc (size);
41 
42   if (!ptr)
43     throw std::bad_alloc ();
44   blocks++;
45   return ptr;
46 }
47 
throw()48 void operator delete[] (void *ptr) throw ()
49 {
50   if (ptr)
51     {
52       free (ptr);
53       blocks--;
54     }
55 }
56 static jmp_buf jump;
57 
58 // allocate and delete an array with no problems
test0()59 void test0 ()
60 {
61   static bool started = false;
62 
63   if (!started)
64     {
65       started = true;
66       std::set_terminate (test0);
67 
68       ctor_count = dtor_count = 5;
69       dtor_repeat = false;
70       blocks = 0;
71 
72       try
73         {
74           void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, dtor);
75           abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
76           if (ctor_count || dtor_count || blocks)
77             longjmp (jump, 1);
78         }
79       catch (...)
80         {
81           longjmp (jump, 2);
82         }
83     }
84   else
85     {
86       longjmp (jump, 3);
87     }
88   return;
89 }
90 
91 // allocate and delete an array with exception on ctor
test1()92 void test1 ()
93 {
94   static bool started = false;
95 
96   if (!started)
97     {
98       started = true;
99       std::set_terminate (test1);
100 
101       ctor_count = dtor_count = 5;
102       dtor_repeat = false;
103       blocks = 0;
104 
105       ctor_count = 4;
106       try
107         {
108           void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, dtor);
109           longjmp (jump, 1);
110         }
111       catch (...)
112         {
113           // we expect to get here
114           if (ctor_count || dtor_count != 1 || blocks)
115             longjmp (jump, 2);
116         }
117     }
118   else
119     {
120       longjmp (jump, 3);
121     }
122   return;
123 }
124 
125 // allocate and delete an array with exception on dtor
test2()126 void test2 ()
127 {
128   static bool started = false;
129 
130   if (!started)
131     {
132       started = true;
133       std::set_terminate (test2);
134       ctor_count = dtor_count = 5;
135       dtor_repeat = false;
136       blocks = 0;
137 
138       dtor_count = 3;
139       try
140         {
141           void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, dtor);
142           abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
143           longjmp (jump, 1);
144         }
145       catch (...)
146         {
147           // we expect to get here
148           if (ctor_count || dtor_count != -2u || blocks)
149             longjmp (jump, 2);
150         }
151     }
152   else
153     {
154       longjmp (jump, 3);
155     }
156   return;
157 }
158 
159 // allocate an array with double exception on dtor
test3()160 void test3 ()
161 {
162   static bool started = false;
163 
164   if (!started)
165     {
166       started = true;
167       std::set_terminate (test3);
168 
169       ctor_count = dtor_count = 5;
170       dtor_repeat = false;
171       blocks = 0;
172 
173       dtor_count = 3;
174       dtor_repeat = true;
175       try
176         {
177           void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, dtor);
178           abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
179           longjmp (jump, 1);
180         }
181       catch (...)
182         {
183           // we do not expect to get here
184           longjmp (jump, 2);
185         }
186     }
187   else
188     {
189       // we expect to get here (via terminate)
190       if (ctor_count || dtor_count || blocks != 1)
191         longjmp (jump, 3);
192       longjmp (jump, -1);
193     }
194   return;
195 }
196 
197 // allocate an array with exception on ctor and exception in cleanup
test4()198 void test4 ()
199 {
200   static bool started = false;
201 
202   if (!started)
203     {
204       started = true;
205       std::set_terminate (test4);
206 
207       ctor_count = dtor_count = 5;
208       dtor_repeat = false;
209       blocks = 0;
210 
211       ctor_count = 3;
212       dtor_count = 2;
213       try
214         {
215           void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, dtor);
216           longjmp (jump, 1);
217         }
218       catch (...)
219         {
220           // we do not expect to get here
221           longjmp (jump, 2);
222         }
223     }
224   else
225     {
226       // we expect to get here (via terminate)
227       if (ctor_count || dtor_count != -1u || blocks != 1)
228         longjmp (jump, 3);
229       longjmp (jump, -1);
230     }
231   return;
232 }
233 
234 static void (*tests[])() =
235 {
236   test0,
237   test1,
238   test2,
239   test3,
240   test4,
241   NULL
242 };
243 
main()244 int main ()
245 {
246   int ix;
247   int n;
248   int errors = 0;
249 
250   for (ix = 0; tests[ix]; ix++)
251     {
252       if (n = setjmp (jump))
253         {
254           if (n > 0)
255             {
256               printf ("test %d failed %d\n", ix, n);
257               errors++;
258             }
259         }
260       else
261         tests[ix] ();
262     }
263   return errors;
264 }
265 
266 #else
main()267 int main ()
268 {
269   return 0;
270 }
271 #endif
272