| // This test fails on VxWorks in kernel mode because it depends on the |
| // library version of "::operator new[]" calling the "::operator new" |
| // defined in this module. This doesn't work because the library version |
| // of "::operator new[]" is built into the kernel itself; library relocations |
| // are resolved when the kernel is linked. |
| // { dg-do run { xfail { powerpc-ibm-aix* || vxworks_kernel } } } |
| // { dg-options "-flat_namespace" { target *-*-darwin[67]* } } |
| // Avoid use of non-overridable new/delete operators in shared |
| // { dg-options "-static" { target *-*-mingw* } } |
| // Test __cxa_vec routines |
| // Copyright (C) 2000, 2005 Free Software Foundation, Inc. |
| // Contributed by Nathan Sidwell 7 Apr 2000 <nathan@nathan@codesourcery.com> |
| |
| #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 |
| #include <cxxabi.h> |
| #include <stdio.h> |
| #include <new> |
| #include <exception> |
| #include <stdlib.h> |
| #include <setjmp.h> |
| |
| static int ctor_count = 0; |
| static int dtor_count = 0; |
| static bool dtor_repeat = false; |
| |
| // Allocate enough padding to hold an array cookie. |
| #ifdef __ARM_EABI__ |
| #define padding 8 |
| #else |
| #define padding (sizeof (std::size_t)) |
| #endif |
| |
| // our pseudo ctors and dtors |
| static abi::__cxa_cdtor_return_type ctor (void *x) |
| { |
| if (!ctor_count) |
| throw 1; |
| ctor_count--; |
| #ifdef __ARM_EABI__ |
| return x; |
| #endif |
| } |
| |
| static abi::__cxa_cdtor_return_type dtor (void *x) |
| { |
| if (!dtor_count) |
| { |
| if (!dtor_repeat) |
| dtor_count--; |
| throw 1; |
| } |
| dtor_count--; |
| #ifdef __ARM_EABI__ |
| return x; |
| #endif |
| } |
| |
| // track new and delete |
| static int blocks = 0; |
| void *operator new[] (std::size_t size) |
| #if __cplusplus <= 199711L |
| throw (std::bad_alloc) |
| #endif |
| { |
| void *ptr = malloc (size); |
| |
| if (!ptr) |
| throw std::bad_alloc (); |
| blocks++; |
| return ptr; |
| } |
| |
| void operator delete[] (void *ptr) throw () |
| { |
| if (ptr) |
| { |
| free (ptr); |
| blocks--; |
| } |
| } |
| static jmp_buf jump; |
| |
| // allocate and delete an array with no problems |
| void test0 () |
| { |
| static bool started = false; |
| |
| if (!started) |
| { |
| started = true; |
| std::set_terminate (test0); |
| |
| ctor_count = dtor_count = 5; |
| dtor_repeat = false; |
| blocks = 0; |
| |
| try |
| { |
| void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor); |
| abi::__cxa_vec_delete (ary, 1, padding, dtor); |
| if (ctor_count || dtor_count || blocks) |
| longjmp (jump, 1); |
| } |
| catch (...) |
| { |
| longjmp (jump, 2); |
| } |
| } |
| else |
| { |
| longjmp (jump, 3); |
| } |
| return; |
| } |
| |
| // allocate and delete an array with exception on ctor |
| void test1 () |
| { |
| static bool started = false; |
| |
| if (!started) |
| { |
| started = true; |
| std::set_terminate (test1); |
| |
| ctor_count = dtor_count = 5; |
| dtor_repeat = false; |
| blocks = 0; |
| |
| ctor_count = 4; |
| try |
| { |
| void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor); |
| longjmp (jump, 1); |
| } |
| catch (...) |
| { |
| // we expect to get here |
| if (ctor_count || dtor_count != 1 || blocks) |
| longjmp (jump, 2); |
| } |
| } |
| else |
| { |
| longjmp (jump, 3); |
| } |
| return; |
| } |
| |
| // allocate and delete an array with exception on dtor |
| void test2 () |
| { |
| static bool started = false; |
| |
| if (!started) |
| { |
| started = true; |
| std::set_terminate (test2); |
| ctor_count = dtor_count = 5; |
| dtor_repeat = false; |
| blocks = 0; |
| |
| dtor_count = 3; |
| try |
| { |
| void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor); |
| abi::__cxa_vec_delete (ary, 1, padding, dtor); |
| longjmp (jump, 1); |
| } |
| catch (...) |
| { |
| // we expect to get here |
| if (ctor_count || dtor_count != -2u || blocks) |
| longjmp (jump, 2); |
| } |
| } |
| else |
| { |
| longjmp (jump, 3); |
| } |
| return; |
| } |
| |
| // allocate an array with double exception on dtor |
| void test3 () |
| { |
| static bool started = false; |
| |
| if (!started) |
| { |
| started = true; |
| std::set_terminate (test3); |
| |
| ctor_count = dtor_count = 5; |
| dtor_repeat = false; |
| blocks = 0; |
| |
| dtor_count = 3; |
| dtor_repeat = true; |
| try |
| { |
| void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor); |
| abi::__cxa_vec_delete (ary, 1, padding, dtor); |
| longjmp (jump, 1); |
| } |
| catch (...) |
| { |
| // we do not expect to get here |
| longjmp (jump, 2); |
| } |
| } |
| else |
| { |
| // we expect to get here (via terminate) |
| if (ctor_count || dtor_count || blocks != 1) |
| longjmp (jump, 3); |
| longjmp (jump, -1); |
| } |
| return; |
| } |
| |
| // allocate an array with exception on ctor and exception in cleanup |
| void test4 () |
| { |
| static bool started = false; |
| |
| if (!started) |
| { |
| started = true; |
| std::set_terminate (test4); |
| |
| ctor_count = dtor_count = 5; |
| dtor_repeat = false; |
| blocks = 0; |
| |
| ctor_count = 3; |
| dtor_count = 2; |
| try |
| { |
| void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor); |
| longjmp (jump, 1); |
| } |
| catch (...) |
| { |
| // we do not expect to get here |
| longjmp (jump, 2); |
| } |
| } |
| else |
| { |
| // we expect to get here (via terminate) |
| if (ctor_count || dtor_count != -1u || blocks != 1) |
| longjmp (jump, 3); |
| longjmp (jump, -1); |
| } |
| return; |
| } |
| |
| static void (*tests[])() = |
| { |
| test0, |
| test1, |
| test2, |
| test3, |
| test4, |
| NULL |
| }; |
| |
| int main () |
| { |
| int ix; |
| int n; |
| int errors = 0; |
| |
| for (ix = 0; tests[ix]; ix++) |
| { |
| if (n = setjmp (jump)) |
| { |
| if (n > 0) |
| { |
| printf ("test %d failed %d\n", ix, n); |
| errors++; |
| } |
| } |
| else |
| tests[ix] (); |
| } |
| return errors; |
| } |
| |
| #else |
| int main () |
| { |
| return 0; |
| } |
| #endif |