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