[libcxx] Rework sized delete.
Summary: This patch does 2 main things: 1. Enable sized delete if the feature test macro `__cpp_sized_deallocation` is enabled. 2. Rework and cleanup all of the sized delete tests. Test Plan: The sized delete replacement tests are now split into 4 files: 1. sized_delete11.pass.cpp: Ensure overriding sized delete in C++11 has no effect. 2. sized_delete14.pass.cpp: Test overriding sized delete in C++14 and ensure it is called. This test fails on clang and GCC < 5.1. 3. size_delete_calls_unsized_delete_.pass.cpp: Test that the default sized delete calls unsized delete. 4. sized_delete_fsizeddeallocation.pass.cpp: Test overriding sized delete when -fsized-deallocation is passed. This test should pass on clang and GCC >= 5.1 I have also removed a lot of cruft from the old tests. They no longer replace the new handler and tests that it is called for bad allocations. Reviewers: mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D9831 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@237662 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e7b12e343b
commit
f4c97290fc
@ -136,7 +136,8 @@ _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, 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
|
#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
|
||||||
|
(defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
|
||||||
_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) _NOEXCEPT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -148,7 +149,8 @@ _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, 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
|
#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
|
||||||
|
(defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
|
||||||
_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) _NOEXCEPT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,68 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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: c++14, c++1z
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Use a class with a non-trivial destructor as the test type in order
|
||||||
|
// to ensure the correct overload is called.
|
||||||
|
// C++14 5.3.5 [expr.delete]p10
|
||||||
|
// - If the type is complete and if, for the second alternative (delete array)
|
||||||
|
// only, the operand is a pointer to a class type with a non-trivial
|
||||||
|
// destructor or a (possibly multi-dimensional) array thereof, the function
|
||||||
|
// with two parameters is selected.
|
||||||
|
// - Otherwise, it is unspecified which of the two deallocation functions is
|
||||||
|
// selected.
|
||||||
|
struct A { ~A() {} };
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
A* x = new A[3];
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
|
||||||
|
delete [] x;
|
||||||
|
assert(1 == unsized_delete_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11
|
||||||
|
|
||||||
|
// TODO: Clang does not enable sized-deallocation in c++14 and behond by
|
||||||
|
// default. It is only enabled when -fsized-deallocation is given.
|
||||||
|
// XFAIL: clang
|
||||||
|
|
||||||
|
// TODO: GCC 4.9.1 does not support sized-deallocation in c++14. However
|
||||||
|
// GCC 5.1 does.
|
||||||
|
// XFAIL: gcc-4.8, gcc-4.9
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Use a class with a non-trivial destructor as the test type in order
|
||||||
|
// to ensure the correct overload is called.
|
||||||
|
// C++14 5.3.5 [expr.delete]p10
|
||||||
|
// - If the type is complete and if, for the second alternative (delete array)
|
||||||
|
// only, the operand is a pointer to a class type with a non-trivial
|
||||||
|
// destructor or a (possibly multi-dimensional) array thereof, the function
|
||||||
|
// with two parameters is selected.
|
||||||
|
// - Otherwise, it is unspecified which of the two deallocation functions is
|
||||||
|
// selected.
|
||||||
|
struct A { ~A() {} };
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A* x = new A[3];
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
|
||||||
|
delete [] x;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(1 == sized_delete_called);
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 calls the unsized operator [] delete.
|
||||||
|
// When sized operator delete [] is not available (ex C++11) then the unsized
|
||||||
|
// operator delete [] is called directly.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Use a class with a non-trivial destructor as the test type in order
|
||||||
|
// to ensure the correct overload is called.
|
||||||
|
// C++14 5.3.5 [expr.delete]p10
|
||||||
|
// - If the type is complete and if, for the second alternative (delete array)
|
||||||
|
// only, the operand is a pointer to a class type with a non-trivial
|
||||||
|
// destructor or a (possibly multi-dimensional) array thereof, the function
|
||||||
|
// with two parameters is selected.
|
||||||
|
// - Otherwise, it is unspecified which of the two deallocation functions is
|
||||||
|
// selected.
|
||||||
|
struct A { ~A() {} };
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A* x = new A[3];
|
||||||
|
assert(0 == delete_called);
|
||||||
|
assert(0 == delete_nothrow_called);
|
||||||
|
|
||||||
|
delete [] x;
|
||||||
|
assert(1 == delete_called);
|
||||||
|
assert(0 == 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 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: sanitizer-new-delete
|
||||||
|
|
||||||
|
// TODO: -fsized-deallocation was only added to GCC in 5.1.
|
||||||
|
// XFAIL: gcc-4.8, gcc-4.9
|
||||||
|
|
||||||
|
// RUN: %build -fsized-deallocation
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#if !defined(__cpp_sized_deallocation)
|
||||||
|
# error __cpp_sized_deallocation should be defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(__cpp_sized_deallocation >= 201309L)
|
||||||
|
# error expected __cpp_sized_deallocation >= 201309L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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) noexcept
|
||||||
|
{
|
||||||
|
++sized_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Use a class with a non-trivial destructor as the test type in order
|
||||||
|
// to ensure the correct overload is called.
|
||||||
|
// C++14 5.3.5 [expr.delete]p10
|
||||||
|
// - If the type is complete and if, for the second alternative (delete array)
|
||||||
|
// only, the operand is a pointer to a class type with a non-trivial
|
||||||
|
// destructor or a (possibly multi-dimensional) array thereof, the function
|
||||||
|
// with two parameters is selected.
|
||||||
|
// - Otherwise, it is unspecified which of the two deallocation functions is
|
||||||
|
// selected.
|
||||||
|
struct A { ~A() {} };
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A* x = new A[3];
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
|
||||||
|
delete [] x;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(1 == sized_delete_called);
|
||||||
|
}
|
@ -1,80 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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;}
|
|
||||||
};
|
|
||||||
|
|
||||||
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,56 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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: c++14, c++1z
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int *x = new int(42);
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(1 == unsized_delete_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11
|
||||||
|
|
||||||
|
// TODO: Clang does not enable sized-deallocation in c++14 and behond by
|
||||||
|
// default. It is only enabled when -fsized-deallocation is given.
|
||||||
|
// XFAIL: clang
|
||||||
|
|
||||||
|
// TODO: GCC 4.9.1 does not support sized-deallocation in c++14. However
|
||||||
|
// GCC 5.1 does.
|
||||||
|
// XFAIL: gcc-4.8, gcc-4.9
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int *x = new int(42);
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(1 == sized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 calls the unsized operator delete.
|
||||||
|
// When sized operator delete is not available (ex C++11) then the unsized
|
||||||
|
// operator delete is called directly.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
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 main()
|
||||||
|
{
|
||||||
|
int *x = new int(42);
|
||||||
|
assert(0 == delete_called);
|
||||||
|
assert(0 == delete_nothrow_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(1 == delete_called);
|
||||||
|
assert(0 == delete_nothrow_called);
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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: sanitizer-new-delete
|
||||||
|
|
||||||
|
// TODO: -fsized-deallocation was only added to GCC in 5.1.
|
||||||
|
// XFAIL: gcc-4.8, gcc-4.9
|
||||||
|
|
||||||
|
// RUN: %build -fsized-deallocation
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#if !defined(__cpp_sized_deallocation)
|
||||||
|
# error __cpp_sized_deallocation should be defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(__cpp_sized_deallocation >= 201309L)
|
||||||
|
# error expected __cpp_sized_deallocation >= 201309L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int sized_delete_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int *x = new int(42);
|
||||||
|
assert(0 == sized_delete_called);
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(1 == sized_delete_called);
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
}
|
@ -1,80 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// 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: sanitizer-new-delete
|
|
||||||
|
|
||||||
#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…
x
Reference in New Issue
Block a user