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