Home | History | Annotate | Download | only in new.delete.single
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // test nothrow sized operator delete replacement.
     11 
     12 // Note that sized delete operator definitions below are simply ignored
     13 // when sized deallocation is not supported, e.g., prior to C++14.
     14 
     15 // UNSUPPORTED: asan, msan
     16 
     17 #include <new>
     18 #include <cstddef>
     19 #include <cstdlib>
     20 #include <cassert>
     21 #include <limits>
     22 
     23 int unsized_delete_called = 0;
     24 int unsized_delete_nothrow_called = 0;
     25 int sized_delete_called = 0;
     26 int sized_delete_nothrow_called = 0;
     27 
     28 void operator delete(void* p) throw()
     29 {
     30     ++unsized_delete_called;
     31     std::free(p);
     32 }
     33 
     34 void operator delete(void* p, const std::nothrow_t&) throw()
     35 {
     36     ++unsized_delete_nothrow_called;
     37     std::free(p);
     38 }
     39 
     40 void operator delete(void* p, std::size_t) throw()
     41 {
     42     ++sized_delete_called;
     43     std::free(p);
     44 }
     45 
     46 void operator delete(void* p, std::size_t, const std::nothrow_t&) throw()
     47 {
     48     ++sized_delete_nothrow_called;
     49     std::free(p);
     50 }
     51 
     52 int new_handler_called = 0;
     53 
     54 void new_handler()
     55 {
     56     ++new_handler_called;
     57     std::set_new_handler(0);
     58 }
     59 
     60 bool A_constructed = false;
     61 
     62 struct A
     63 {
     64     A() {A_constructed = true;}
     65     ~A() {A_constructed = false;}
     66 };
     67 
     68 struct BadA : public A {
     69     BadA() { throw std::bad_alloc(); }
     70 };
     71 
     72 int main()
     73 {
     74     std::set_new_handler(new_handler);
     75     try
     76     {
     77         void*volatile vp = operator new (std::numeric_limits<std::size_t>::max(), std::nothrow);
     78         assert(new_handler_called == 1);
     79         assert(vp == 0);
     80     }
     81     catch (...)
     82     {
     83         assert(false);
     84     }
     85     try
     86     {
     87         A* ap = new(std::nothrow) BadA;
     88         assert(false);
     89     }
     90     catch (...)
     91     {
     92         assert(!A_constructed);
     93 #if _LIBCPP_STD_VER >= 14
     94         // FIXME: Do we need a version of [Expr.Delete]#10 for nothrow
     95         // deallocation functions (selecting sized ones whenever available)?
     96         // It is not required by the standard. If it were, the following would
     97         // be the expected behaviour (instead of the current one):
     98         //   assert(!unsized_delete_nothrow_called);
     99         //   assert(sized_delete_nothrow_called == 1);
    100         assert(unsized_delete_nothrow_called == 1);
    101         assert(!sized_delete_nothrow_called);
    102 #else // if _LIBCPP_STD_VER < 14
    103         assert(unsized_delete_nothrow_called == 1);
    104         assert(!sized_delete_nothrow_called);
    105 #endif
    106         assert(!unsized_delete_called);
    107         assert(!sized_delete_called);
    108     }
    109 }
    110