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