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