1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: no-exceptions 10 11 #include "cxxabi.h" 12 13 #include <cassert> 14 #include <cstdlib> 15 #include <exception> 16 17 void my_terminate () { exit ( 0 ); } 18 19 // Wrapper routines 20 void *my_alloc2 ( size_t sz ) { 21 void *p = std::malloc ( sz ); 22 // std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p ); 23 return p; 24 } 25 26 void my_dealloc2 ( void *p ) { 27 // std::printf ( "Freeing %lx\n", (unsigned long) p ); 28 std::free ( p ); 29 } 30 31 void my_dealloc3 ( void *p, size_t ) { 32 // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz ); 33 std::free ( p ); 34 } 35 36 void my_construct ( void *) { 37 // std::printf ( "Constructing %lx\n", (unsigned long) p ); 38 } 39 40 void my_destruct ( void *) { 41 // std::printf ( "Destructing %lx\n", (unsigned long) p ); 42 } 43 44 int gCounter; 45 void count_construct ( void * ) { ++gCounter; } 46 void count_destruct ( void * ) { --gCounter; } 47 48 49 int gConstructorCounter; 50 int gConstructorThrowTarget; 51 int gDestructorCounter; 52 int gDestructorThrowTarget; 53 void throw_construct ( void * ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; } 54 void throw_destruct ( void * ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; } 55 56 struct vec_on_stack { 57 void *storage; 58 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {} 59 ~vec_on_stack () { __cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); } 60 }; 61 62 63 // Make sure the constructors and destructors are matched 64 void test_exception_in_destructor ( ) { 65 66 // Try throwing from a destructor while unwinding the stack -- should abort 67 gConstructorCounter = gDestructorCounter = 0; 68 gConstructorThrowTarget = -1; 69 gDestructorThrowTarget = 5; 70 try { 71 vec_on_stack v; 72 throw 3; 73 } catch ( int i ) { 74 75 } 76 77 assert(false && "should never get here"); 78 } 79 80 81 82 int main () { 83 std::set_terminate ( my_terminate ); 84 test_exception_in_destructor (); 85 return 1; // we failed if we get here 86 } 87