1 //===--------------------------- test_vector2.cpp -------------------------===//
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 <iostream>
14 #include <cstdlib>
15 
16 void my_terminate () { exit ( 0 ); }
17 
18 //  Wrapper routines
19 void *my_alloc2 ( size_t sz ) {
20     void *p = std::malloc ( sz );
21 //  std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
22     return p;
23     }
24 
25 void my_dealloc2 ( void *p ) {
26 //  std::printf ( "Freeing %lx\n", (unsigned long) p );
27     std::free ( p );
28     }
29 
30 void my_dealloc3 ( void *p, size_t ) {
31 //  std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
32     std::free ( p );
33     }
34 
35 void my_construct ( void *) {
36 //  std::printf ( "Constructing %lx\n", (unsigned long) p );
37     }
38 
39 void my_destruct  ( void *) {
40 //  std::printf ( "Destructing  %lx\n", (unsigned long) p );
41     }
42 
43 int gCounter;
44 void count_construct ( void * ) { ++gCounter; }
45 void count_destruct  ( void * ) { --gCounter; }
46 
47 
48 int gConstructorCounter;
49 int gConstructorThrowTarget;
50 int gDestructorCounter;
51 int gDestructorThrowTarget;
52 void throw_construct ( void * ) { if ( gConstructorCounter   == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; }
53 void throw_destruct  ( void * ) { if ( ++gDestructorCounter  == gDestructorThrowTarget  ) throw 2; }
54 
55 struct vec_on_stack {
56     void *storage;
57     vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new    (            10, 40, 8, throw_construct, throw_destruct )) {}
58     ~vec_on_stack () {          __cxxabiv1::__cxa_vec_delete ( storage,       40, 8,                  throw_destruct );  }
59     };
60 
61 
62 //  Make sure the constructors and destructors are matched
63 void test_exception_in_destructor ( ) {
64 
65 //  Try throwing from a destructor while unwinding the stack -- should abort
66     gConstructorCounter = gDestructorCounter = 0;
67     gConstructorThrowTarget = -1;
68     gDestructorThrowTarget  = 5;
69     try {
70         vec_on_stack v;
71         throw 3;
72         }
73     catch ( int i ) {}
74 
75     std::cerr << "should never get here" << std::endl;
76     }
77 
78 
79 
80 int main () {
81     std::set_terminate ( my_terminate );
82     test_exception_in_destructor ();
83     return 1;       // we failed if we get here
84     }
85