90 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// Reports leaks after https://github.com/llvm/llvm-project/pull/6628510// UNSUPPORTED: lsan11 12// UNSUPPORTED: no-exceptions13 14#include "cxxabi.h"15 16#include <cassert>17#include <cstdlib>18#include <exception>19 20void my_terminate () { exit ( 0 ); }21 22// Wrapper routines23void *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 29void my_dealloc2 ( void *p ) {30// std::printf ( "Freeing %lx\n", (unsigned long) p );31 std::free ( p );32}33 34void my_dealloc3 ( void *p, size_t ) {35// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );36 std::free ( p );37}38 39void my_construct ( void *) {40// std::printf ( "Constructing %lx\n", (unsigned long) p );41}42 43void my_destruct ( void *) {44// std::printf ( "Destructing %lx\n", (unsigned long) p );45}46 47int gCounter;48void count_construct ( void * ) { ++gCounter; }49void count_destruct ( void * ) { --gCounter; }50 51 52int gConstructorCounter;53int gConstructorThrowTarget;54int gDestructorCounter;55int gDestructorThrowTarget;56void throw_construct ( void * ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; }57void throw_destruct ( void * ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; }58 59struct vec_on_stack {60 void *storage;61 vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}62 ~vec_on_stack () { __cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }63};64 65 66// Make sure the constructors and destructors are matched67void test_exception_in_destructor ( ) {68 69// Try throwing from a destructor while unwinding the stack -- should abort70 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 85int main () {86 std::set_terminate ( my_terminate );87 test_exception_in_destructor ();88 return 1; // we failed if we get here89}90