brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · ac1ed5c Raw
279 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#include "cxxabi.h"10 11#include <cassert>12#include <cstdio>13#include <cstdlib>14 15#include "test_macros.h"16 17//  Wrapper routines18void *my_alloc2 ( size_t sz ) {19    void *p = std::malloc ( sz );20//  std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );21    return p;22}23 24void my_dealloc2 ( void *p ) {25//  std::printf ( "Freeing %lx\n", (unsigned long) p );26    std::free ( p );27}28 29void my_dealloc3 ( void *p, size_t ) {30//  std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );31    std::free ( p );32}33 34void my_construct ( void * ) {35//  std::printf ( "Constructing %lx\n", (unsigned long) p );36}37 38void my_destruct  ( void * ) {39//  std::printf ( "Destructing  %lx\n", (unsigned long) p );40}41 42int gCounter;43void count_construct ( void * ) { ++gCounter; }44void count_destruct  ( void * ) { --gCounter; }45 46 47int gConstructorCounter;48int gConstructorThrowTarget;49int gDestructorCounter;50int gDestructorThrowTarget;51void throw_construct ( void * ) {52#ifndef TEST_HAS_NO_EXCEPTIONS53    if ( gConstructorCounter   == gConstructorThrowTarget )54        throw 1;55    ++gConstructorCounter;56#endif57}58void throw_destruct  ( void * ) {59#ifndef TEST_HAS_NO_EXCEPTIONS60    if ( ++gDestructorCounter  == gDestructorThrowTarget  )61        throw 2;62#endif63}64 65#if __cplusplus >= 201103L66#   define CAN_THROW noexcept(false)67#else68#   define CAN_THROW69#endif70 71struct vec_on_stack {72    void *storage;73    vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new    (            10, 40, 8, throw_construct, throw_destruct )) {}74    ~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage,       40, 8,                  throw_destruct );  }75};76 77//  Test calls with empty constructors and destructors78int test_empty ( ) {79    void *one, *two, *three;80 81//  Try with no padding and no con/destructors82    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, NULL, NULL );83    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc2 );84    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, NULL, NULL, my_alloc2, my_dealloc3 );85 86    __cxxabiv1::__cxa_vec_delete ( one,       40, 0, NULL );87    __cxxabiv1::__cxa_vec_delete2( two,       40, 0, NULL, my_dealloc2 );88    __cxxabiv1::__cxa_vec_delete3( three,     40, 0, NULL, my_dealloc3 );89 90//  Try with no padding91    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );92    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );93    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc3 );94 95    __cxxabiv1::__cxa_vec_delete ( one,       40, 0, my_destruct );96    __cxxabiv1::__cxa_vec_delete2( two,       40, 0, my_destruct, my_dealloc2 );97    __cxxabiv1::__cxa_vec_delete3( three,     40, 0, my_destruct, my_dealloc3 );98 99//  Padding and no con/destructors100    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );101    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );102    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );103 104    __cxxabiv1::__cxa_vec_delete ( one,       40, 8, NULL );105    __cxxabiv1::__cxa_vec_delete2( two,       40, 8, NULL, my_dealloc2 );106    __cxxabiv1::__cxa_vec_delete3( three,     40, 8, NULL, my_dealloc3 );107 108//  Padding with con/destructors109    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );110    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );111    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );112 113    __cxxabiv1::__cxa_vec_delete ( one,       40, 8, my_destruct );114    __cxxabiv1::__cxa_vec_delete2( two,       40, 8, my_destruct, my_dealloc2 );115    __cxxabiv1::__cxa_vec_delete3( three,     40, 8, my_destruct, my_dealloc3 );116 117    return 0;118}119 120//  Make sure the constructors and destructors are matched121int test_counted ( ) {122    int retVal = 0;123    void *one, *two, *three;124 125//  Try with no padding126    gCounter = 0;127    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );128    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );129    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );130 131    __cxxabiv1::__cxa_vec_delete ( one,       40, 0, count_destruct );132    __cxxabiv1::__cxa_vec_delete2( two,       40, 0, count_destruct, my_dealloc2 );133    __cxxabiv1::__cxa_vec_delete3( three,     40, 0, count_destruct, my_dealloc3 );134 135//  Since there was no padding, the # of elements in the array are not stored136//  and the destructors are not called.137    if ( gCounter != 30 ) {138        std::printf("Mismatched Constructor/Destructor calls (1)\n");139        std::printf("  Expected 30, got %d\n", gCounter);140        retVal = 1;141    }142 143    gCounter = 0;144    one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );145    two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );146    three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );147 148    __cxxabiv1::__cxa_vec_delete ( one,       40, 8, count_destruct );149    __cxxabiv1::__cxa_vec_delete2( two,       40, 8, count_destruct, my_dealloc2 );150    __cxxabiv1::__cxa_vec_delete3( three,     40, 8, count_destruct, my_dealloc3 );151 152    if ( gCounter != 0 ) {153        std::printf("Mismatched Constructor/Destructor calls (2)\n");154        std::printf("  Expected 0, got %d\n", gCounter);155        retVal = 1;156    }157 158    return retVal;159}160 161#ifndef TEST_HAS_NO_EXCEPTIONS162//  Make sure the constructors and destructors are matched163int test_exception_in_constructor ( ) {164    int retVal = 0;165    void *one, *two, *three;166 167//  Try with no padding168    gConstructorCounter = gDestructorCounter = 0;169    gConstructorThrowTarget = 15;170    gDestructorThrowTarget  = -1;171    try {172        one = two = three = NULL;173        one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );174        two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );175        three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );176    }177    catch ( int i ) {}178 179    __cxxabiv1::__cxa_vec_delete ( one,       40, 0, throw_destruct );180    __cxxabiv1::__cxa_vec_delete2( two,       40, 0, throw_destruct, my_dealloc2 );181    __cxxabiv1::__cxa_vec_delete3( three,     40, 0, throw_destruct, my_dealloc3 );182 183//  Since there was no padding, the # of elements in the array are not stored184//  and the destructors are not called.185//  Since we threw after 15 calls to the constructor, we should see 5 calls to186//      the destructor from the partially constructed array.187    if ( gConstructorCounter - gDestructorCounter != 10 ) {188        std::printf("Mismatched Constructor/Destructor calls (1C)\n");189        std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);190        retVal = 1;191    }192 193    gConstructorCounter = gDestructorCounter = 0;194    gConstructorThrowTarget = 15;195    gDestructorThrowTarget  = -1;196    try {197        one = two = three = NULL;198        one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );199        two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );200        three   = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );201    }202    catch ( int i ) {}203 204    __cxxabiv1::__cxa_vec_delete ( one,       40, 8, throw_destruct );205    __cxxabiv1::__cxa_vec_delete2( two,       40, 8, throw_destruct, my_dealloc2 );206    __cxxabiv1::__cxa_vec_delete3( three,     40, 8, throw_destruct, my_dealloc3 );207 208    if ( gConstructorCounter != gDestructorCounter ) {209        std::printf("Mismatched Constructor/Destructor calls (2C)\n");210        std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);211        retVal = 1;212    }213 214    return retVal;215}216#endif217 218#ifndef TEST_HAS_NO_EXCEPTIONS219//  Make sure the constructors and destructors are matched220int test_exception_in_destructor ( ) {221    int retVal = 0;222    void *one, *two, *three;223    one = two = three = NULL;224 225//  Throw from within a destructor226    gConstructorCounter = gDestructorCounter = 0;227    gConstructorThrowTarget = -1;228    gDestructorThrowTarget  = 15;229    try {230        one = two = NULL;231        one     = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );232        two     = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );233    }234    catch ( int i ) {}235 236    try {237        __cxxabiv1::__cxa_vec_delete ( one,       40, 8, throw_destruct );238        __cxxabiv1::__cxa_vec_delete2( two,       40, 8, throw_destruct, my_dealloc2 );239        assert(false);240    }241    catch ( int i ) {}242 243//  We should have thrown in the middle of cleaning up "two", which means that244//  there should be 20 calls to the destructor and the try block should exit245//  before the assertion.246    if ( gConstructorCounter != 20 || gDestructorCounter != 20 ) {247        std::printf("Unexpected Constructor/Destructor calls (1D)\n");248        std::printf("Expected (20, 20), but got (%d, %d)\n", gConstructorCounter, gDestructorCounter);249        retVal = 1;250    }251 252//  Try throwing from a destructor - should be fine.253    gConstructorCounter = gDestructorCounter = 0;254    gConstructorThrowTarget = -1;255    gDestructorThrowTarget  = 5;256    try { vec_on_stack v; }257    catch ( int i ) {}258 259    if ( gConstructorCounter != gDestructorCounter ) {260        std::printf("Mismatched Constructor/Destructor calls (2D)\n");261        std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);262        retVal = 1;263    }264 265    return retVal;266}267#endif268 269int main(int, char**) {270    int retVal = 0;271    retVal += test_empty ();272    retVal += test_counted ();273#ifndef TEST_HAS_NO_EXCEPTIONS274    retVal += test_exception_in_constructor ();275    retVal += test_exception_in_destructor ();276#endif277    return retVal;278}279