More on adding sized deallocation functions in libc++: Continuing from r229281, this adds version guards and test cases.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@229968 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d75a44ba24
commit
74f95a01cd
@ -139,9 +139,11 @@ _LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz)
|
|||||||
;
|
;
|
||||||
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p) _NOEXCEPT;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz, const std::nothrow_t&) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#endif
|
||||||
|
|
||||||
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
|
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
|
||||||
#if !__has_feature(cxx_noexcept)
|
#if !__has_feature(cxx_noexcept)
|
||||||
@ -150,9 +152,11 @@ _LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
|
|||||||
;
|
;
|
||||||
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p) _NOEXCEPT;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
|
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
|
||||||
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz, const std::nothrow_t&) _NOEXCEPT;
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#endif
|
||||||
|
|
||||||
inline _LIBCPP_INLINE_VISIBILITY void* operator new (std::size_t, void* __p) _NOEXCEPT {return __p;}
|
inline _LIBCPP_INLINE_VISIBILITY void* operator new (std::size_t, void* __p) _NOEXCEPT {return __p;}
|
||||||
inline _LIBCPP_INLINE_VISIBILITY void* operator new[](std::size_t, void* __p) _NOEXCEPT {return __p;}
|
inline _LIBCPP_INLINE_VISIBILITY void* operator new[](std::size_t, void* __p) _NOEXCEPT {return __p;}
|
||||||
|
32
src/new.cpp
32
src/new.cpp
@ -124,13 +124,6 @@ operator delete(void* ptr) _NOEXCEPT
|
|||||||
::free(ptr);
|
::free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
|
||||||
void
|
|
||||||
operator delete(void* ptr, size_t) _NOEXCEPT
|
|
||||||
{
|
|
||||||
::operator delete(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
||||||
@ -140,11 +133,18 @@ operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete(void* ptr, size_t, const std::nothrow_t&) _NOEXCEPT
|
operator delete(void* ptr, size_t) _NOEXCEPT
|
||||||
{
|
{
|
||||||
::operator delete(ptr);
|
::operator delete(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete(void* ptr, size_t, const std::nothrow_t& nt) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete(ptr, nt);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete[] (void* ptr) _NOEXCEPT
|
operator delete[] (void* ptr) _NOEXCEPT
|
||||||
@ -152,13 +152,6 @@ operator delete[] (void* ptr) _NOEXCEPT
|
|||||||
::operator delete(ptr);
|
::operator delete(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
|
||||||
void
|
|
||||||
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
|
||||||
{
|
|
||||||
::operator delete[](ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
||||||
@ -168,11 +161,18 @@ operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete[] (void* ptr, size_t, const std::nothrow_t&) _NOEXCEPT
|
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
||||||
{
|
{
|
||||||
::operator delete[](ptr);
|
::operator delete[](ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete[] (void* ptr, size_t, const std::nothrow_t& nt) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete[](ptr, nt);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !__GLIBCXX__
|
#endif // !__GLIBCXX__
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test sized operator delete[] by replacing unsized operator delete[].
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int delete_called = 0;
|
||||||
|
int delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete[](void* p) throw()
|
||||||
|
{
|
||||||
|
++delete_called;
|
||||||
|
delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {++A_constructed;}
|
||||||
|
~A() {--A_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new [] (std::numeric_limits<std::size_t>::max());
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
A* ap = new A[3];
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed == 3);
|
||||||
|
assert(!delete_called);
|
||||||
|
assert(!delete_nothrow_called);
|
||||||
|
delete [] ap;
|
||||||
|
assert(A_constructed == 0);
|
||||||
|
assert(delete_called == 1);
|
||||||
|
assert(!delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test nothrow sized operator delete[] by replacing
|
||||||
|
// nothrow unsized operator delete[].
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int delete_called = 0;
|
||||||
|
int delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete[](void* p) throw()
|
||||||
|
{
|
||||||
|
++delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadA : public A {
|
||||||
|
BadA() { throw std::bad_alloc(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void*volatile vp = operator new [] (std::numeric_limits<std::size_t>::max(), std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) BadA [3];
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(!delete_called);
|
||||||
|
assert(delete_nothrow_called == 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test nothrow sized operator delete[] replacement.
|
||||||
|
|
||||||
|
// Note that sized delete operator definitions below are simply ignored
|
||||||
|
// when sized deallocation is not supported, e.g., prior to C++14.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_called = 0;
|
||||||
|
int sized_delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete[](void* p) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::size_t) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::size_t, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadA : public A {
|
||||||
|
BadA() { throw std::bad_alloc(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void*volatile vp = operator new [] (std::numeric_limits<std::size_t>::max(), std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) BadA [3];
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(!A_constructed);
|
||||||
|
#if _LIBCPP_STD_VER >= 14
|
||||||
|
// FIXME: Do we need a version of [Expr.Delete]#10 for nothrow
|
||||||
|
// deallocation functions (selecting sized ones whenever available)?
|
||||||
|
// It is not required by the standard. If it were, the following would
|
||||||
|
// be the expected behaviour (instead of the current one):
|
||||||
|
// assert(!unsized_delete_nothrow_called);
|
||||||
|
// assert(sized_delete_nothrow_called == 1);
|
||||||
|
assert(unsized_delete_nothrow_called == 1);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
#else // if _LIBCPP_STD_VER < 14
|
||||||
|
assert(unsized_delete_nothrow_called == 1);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
#endif
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test sized operator delete[] replacement.
|
||||||
|
|
||||||
|
// Note that sized delete operator definitions below are simply ignored
|
||||||
|
// when sized deallocation is not supported, e.g., prior to C++14.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_called = 0;
|
||||||
|
int sized_delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete[](void* p) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::size_t) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::size_t, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {++A_constructed;}
|
||||||
|
~A() {--A_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new [] (std::numeric_limits<std::size_t>::max());
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
A* ap = new A[3];
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed == 3);
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(!unsized_delete_nothrow_called);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
delete [] ap;
|
||||||
|
assert(A_constructed == 0);
|
||||||
|
#if _LIBCPP_STD_VER >= 14
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(sized_delete_called == 1);
|
||||||
|
#else // if _LIBCPP_STD_VER < 14
|
||||||
|
assert(unsized_delete_called == 1);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
#endif
|
||||||
|
assert(!unsized_delete_nothrow_called);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test sized operator delete by replacing unsized operator delete.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int delete_called = 0;
|
||||||
|
int delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete(void* p) throw()
|
||||||
|
{
|
||||||
|
++delete_called;
|
||||||
|
delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new (std::numeric_limits<std::size_t>::max());
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
A* ap = new A;
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed);
|
||||||
|
assert(!delete_called);
|
||||||
|
assert(!delete_nothrow_called);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(delete_called == 1);
|
||||||
|
assert(!delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test nothrow sized operator delete by replacing
|
||||||
|
// nothrow unsized operator delete.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int delete_called = 0;
|
||||||
|
int delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete(void* p) throw()
|
||||||
|
{
|
||||||
|
++delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadA : public A {
|
||||||
|
BadA() { throw std::bad_alloc(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* volatile vp = operator new (std::numeric_limits<std::size_t>::max(), std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) BadA;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(!delete_called);
|
||||||
|
assert(delete_nothrow_called == 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test nothrow sized operator delete replacement.
|
||||||
|
|
||||||
|
// Note that sized delete operator definitions below are simply ignored
|
||||||
|
// when sized deallocation is not supported, e.g., prior to C++14.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_called = 0;
|
||||||
|
int sized_delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete(void* p) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::size_t) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::size_t, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadA : public A {
|
||||||
|
BadA() { throw std::bad_alloc(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void*volatile vp = operator new (std::numeric_limits<std::size_t>::max(), std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) BadA;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(!A_constructed);
|
||||||
|
#if _LIBCPP_STD_VER >= 14
|
||||||
|
// FIXME: Do we need a version of [Expr.Delete]#10 for nothrow
|
||||||
|
// deallocation functions (selecting sized ones whenever available)?
|
||||||
|
// It is not required by the standard. If it were, the following would
|
||||||
|
// be the expected behaviour (instead of the current one):
|
||||||
|
// assert(!unsized_delete_nothrow_called);
|
||||||
|
// assert(sized_delete_nothrow_called == 1);
|
||||||
|
assert(unsized_delete_nothrow_called == 1);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
#else // if _LIBCPP_STD_VER < 14
|
||||||
|
assert(unsized_delete_nothrow_called == 1);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
#endif
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// test sized operator delete replacement.
|
||||||
|
|
||||||
|
// Note that sized delete operator definitions below are simply ignored
|
||||||
|
// when sized deallocation is not supported, e.g., prior to C++14.
|
||||||
|
|
||||||
|
// UNSUPPORTED: asan, msan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_called = 0;
|
||||||
|
int sized_delete_nothrow_called = 0;
|
||||||
|
|
||||||
|
void operator delete(void* p) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++unsized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::size_t) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::size_t, const std::nothrow_t&) throw()
|
||||||
|
{
|
||||||
|
++sized_delete_nothrow_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new (std::numeric_limits<std::size_t>::max());
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
A* ap = new A;
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed);
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(!unsized_delete_nothrow_called);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
#if _LIBCPP_STD_VER >= 14
|
||||||
|
assert(!unsized_delete_called);
|
||||||
|
assert(sized_delete_called == 1);
|
||||||
|
#else // if _LIBCPP_STD_VER < 14
|
||||||
|
assert(unsized_delete_called == 1);
|
||||||
|
assert(!sized_delete_called);
|
||||||
|
#endif
|
||||||
|
assert(!unsized_delete_nothrow_called);
|
||||||
|
assert(!sized_delete_nothrow_called);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user