Implement P0035R4 -- Add C++17 aligned allocation functions
Summary: This patch implements the library side of P0035R4. The implementation is thanks to @rsmith. In addition to the C++17 implementation, the library implementation can be explicitly turned on using `-faligned-allocation` in all dialects. Reviewers: mclow.lists, rsmith Subscribers: rsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D25591 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@284206 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
79
include/new
79
include/new
@@ -27,18 +27,19 @@ public:
|
|||||||
virtual const char* what() const noexcept;
|
virtual const char* what() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
class bad_array_length : public bad_alloc // C++14
|
class bad_array_length : public bad_alloc // FIXME: Not part of C++
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_array_length() noexcept;
|
bad_array_length() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
class bad_array_new_length : public bad_alloc
|
class bad_array_new_length : public bad_alloc // C++14
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bad_array_new_length() noexcept;
|
bad_array_new_length() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class align_val_t : size_t {}; // C++17
|
||||||
struct nothrow_t {};
|
struct nothrow_t {};
|
||||||
extern const nothrow_t nothrow;
|
extern const nothrow_t nothrow;
|
||||||
typedef void (*new_handler)();
|
typedef void (*new_handler)();
|
||||||
@@ -48,16 +49,34 @@ new_handler get_new_handler() noexcept;
|
|||||||
} // std
|
} // std
|
||||||
|
|
||||||
void* operator new(std::size_t size); // replaceable
|
void* operator new(std::size_t size); // replaceable
|
||||||
|
void* operator new(std::size_t size, std::align_val_t alignment); // replaceable, C++17
|
||||||
void* operator new(std::size_t size, const std::nothrow_t&) noexcept; // replaceable
|
void* operator new(std::size_t size, const std::nothrow_t&) noexcept; // replaceable
|
||||||
|
void* operator new(std::size_t size, std::align_val_t alignment,
|
||||||
|
const std::nothrow_t&) noexcept; // replaceable, C++17
|
||||||
void operator delete(void* ptr) noexcept; // replaceable
|
void operator delete(void* ptr) noexcept; // replaceable
|
||||||
void operator delete(void* ptr, std::size_t size) noexcept; // replaceable, C++14
|
void operator delete(void* ptr, std::size_t size) noexcept; // replaceable, C++14
|
||||||
|
void operator delete(void* ptr, std::align_val_t alignment) noexcept; // replaceable, C++17
|
||||||
|
void operator delete(void* ptr, std::size_t size,
|
||||||
|
std::align_val_t alignment) noexcept; // replaceable, C++17
|
||||||
void operator delete(void* ptr, const std::nothrow_t&) noexcept; // replaceable
|
void operator delete(void* ptr, const std::nothrow_t&) noexcept; // replaceable
|
||||||
|
void operator delete(void* ptr, std:align_val_t alignment,
|
||||||
|
const std::nothrow_t&) noexcept; // replaceable, C++17
|
||||||
|
|
||||||
void* operator new[](std::size_t size); // replaceable
|
void* operator new[](std::size_t size); // replaceable
|
||||||
|
void* operator new[](std::size_t size,
|
||||||
|
std::align_val_t alignment) noexcept; // replaceable, C++17
|
||||||
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; // replaceable
|
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; // replaceable
|
||||||
|
void* operator new[](std::size_t size, std::align_val_t alignment,
|
||||||
|
const std::nothrow_t&) noexcept; // replaceable, C++17
|
||||||
void operator delete[](void* ptr) noexcept; // replaceable
|
void operator delete[](void* ptr) noexcept; // replaceable
|
||||||
void operator delete[](void* ptr, std::size_t size) noexcept; // replaceable, C++14
|
void operator delete[](void* ptr, std::size_t size) noexcept; // replaceable, C++14
|
||||||
|
void operator delete[](void* ptr,
|
||||||
|
std::align_val_t alignment) noexcept; // replaceable, C++17
|
||||||
|
void operator delete[](void* ptr, std::size_t size,
|
||||||
|
std::align_val_t alignment) noexcept; // replaceable, C++17
|
||||||
void operator delete[](void* ptr, const std::nothrow_t&) noexcept; // replaceable
|
void operator delete[](void* ptr, const std::nothrow_t&) noexcept; // replaceable
|
||||||
|
void operator delete[](void* ptr, std::align_val_t alignment,
|
||||||
|
const std::nothrow_t&) noexcept; // replaceable, C++17
|
||||||
|
|
||||||
void* operator new (std::size_t size, void* ptr) noexcept;
|
void* operator new (std::size_t size, void* ptr) noexcept;
|
||||||
void* operator new[](std::size_t size, void* ptr) noexcept;
|
void* operator new[](std::size_t size, void* ptr) noexcept;
|
||||||
@@ -79,6 +98,16 @@ void operator delete[](void* ptr, void*) noexcept;
|
|||||||
#pragma GCC system_header
|
#pragma GCC system_header
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
|
||||||
|
(defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309))
|
||||||
|
# define _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER > 14 || \
|
||||||
|
(defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606))
|
||||||
|
# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace std // purposefully not using versioning namespace
|
namespace std // purposefully not using versioning namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -117,6 +146,14 @@ public:
|
|||||||
|
|
||||||
#endif // defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11)
|
#endif // defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11)
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||||
|
#ifndef _LIBCPP_CXX03_LANG
|
||||||
|
enum class _LIBCPP_ENUM_VIS align_val_t : size_t { };
|
||||||
|
#else
|
||||||
|
enum align_val_t { __zero = 0, __max = (size_t)-1 };
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
struct _LIBCPP_TYPE_VIS nothrow_t {};
|
struct _LIBCPP_TYPE_VIS nothrow_t {};
|
||||||
extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
|
extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
|
||||||
typedef void (*new_handler)();
|
typedef void (*new_handler)();
|
||||||
@@ -131,32 +168,46 @@ _LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
|
|||||||
# define _LIBCPP_NEW_DELETE_VIS _LIBCPP_FUNC_VIS
|
# define _LIBCPP_NEW_DELETE_VIS _LIBCPP_FUNC_VIS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz)
|
|
||||||
#if !__has_feature(cxx_noexcept)
|
#if !__has_feature(cxx_noexcept)
|
||||||
throw(std::bad_alloc)
|
#define _THROW_BAD_ALLOC throw(std::bad_alloc)
|
||||||
|
#else
|
||||||
|
#define _THROW_BAD_ALLOC
|
||||||
#endif
|
#endif
|
||||||
;
|
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz) _THROW_BAD_ALLOC;
|
||||||
_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 || \
|
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||||
(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
|
||||||
|
|
||||||
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
|
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz) _THROW_BAD_ALLOC;
|
||||||
#if !__has_feature(cxx_noexcept)
|
|
||||||
throw(std::bad_alloc)
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
_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 || \
|
#ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||||
(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
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::align_val_t) _NOEXCEPT;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::align_val_t) _NOEXCEPT;
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||||
|
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||||
|
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||||
|
#endif
|
||||||
|
#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;}
|
||||||
inline _LIBCPP_INLINE_VISIBILITY void operator delete (void*, void*) _NOEXCEPT {}
|
inline _LIBCPP_INLINE_VISIBILITY void operator delete (void*, void*) _NOEXCEPT {}
|
||||||
|
|||||||
@@ -16,6 +16,22 @@ New entries should be added directly below the "Version" header.
|
|||||||
Version 4.0
|
Version 4.0
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
* rTBD - Implement C++17 aligned allocation in <new>
|
||||||
|
|
||||||
|
x86_64-linux-gnu
|
||||||
|
----------------
|
||||||
|
Symbol added: posix_memalign@GLIBC_2.2.5
|
||||||
|
Symbol added: _ZdaPvSt11align_val_t
|
||||||
|
Symbol added: _ZdlPvSt11align_val_t
|
||||||
|
Symbol added: _ZnamSt11align_val_t
|
||||||
|
Symbol added: _ZdaPvmSt11align_val_t
|
||||||
|
Symbol added: _ZdlPvmSt11align_val_t
|
||||||
|
Symbol added: _ZdlPvSt11align_val_tRKSt9nothrow_t
|
||||||
|
Symbol added: _ZnwmSt11align_val_tRKSt9nothrow_t
|
||||||
|
Symbol added: _ZnamSt11align_val_tRKSt9nothrow_t
|
||||||
|
Symbol added: _ZdaPvSt11align_val_tRKSt9nothrow_t
|
||||||
|
Symbol added: _ZnwmSt11align_val_t
|
||||||
|
|
||||||
* r283980 - Implement C++17 <optional>
|
* r283980 - Implement C++17 <optional>
|
||||||
|
|
||||||
x86_64-linux-gnu
|
x86_64-linux-gnu
|
||||||
|
|||||||
@@ -1874,14 +1874,24 @@
|
|||||||
{'type': 'FUNC', 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev'}
|
{'type': 'FUNC', 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev'}
|
||||||
{'type': 'FUNC', 'name': '_ZdaPv'}
|
{'type': 'FUNC', 'name': '_ZdaPv'}
|
||||||
{'type': 'FUNC', 'name': '_ZdaPvRKSt9nothrow_t'}
|
{'type': 'FUNC', 'name': '_ZdaPvRKSt9nothrow_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdaPvSt11align_val_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdaPvSt11align_val_tRKSt9nothrow_t'}
|
||||||
{'type': 'FUNC', 'name': '_ZdaPvm'}
|
{'type': 'FUNC', 'name': '_ZdaPvm'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdaPvmSt11align_val_t'}
|
||||||
{'type': 'FUNC', 'name': '_ZdlPv'}
|
{'type': 'FUNC', 'name': '_ZdlPv'}
|
||||||
{'type': 'FUNC', 'name': '_ZdlPvRKSt9nothrow_t'}
|
{'type': 'FUNC', 'name': '_ZdlPvRKSt9nothrow_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdlPvSt11align_val_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdlPvSt11align_val_tRKSt9nothrow_t'}
|
||||||
{'type': 'FUNC', 'name': '_ZdlPvm'}
|
{'type': 'FUNC', 'name': '_ZdlPvm'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZdlPvmSt11align_val_t'}
|
||||||
{'type': 'FUNC', 'name': '_Znam'}
|
{'type': 'FUNC', 'name': '_Znam'}
|
||||||
{'type': 'FUNC', 'name': '_ZnamRKSt9nothrow_t'}
|
{'type': 'FUNC', 'name': '_ZnamRKSt9nothrow_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZnamSt11align_val_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZnamSt11align_val_tRKSt9nothrow_t'}
|
||||||
{'type': 'FUNC', 'name': '_Znwm'}
|
{'type': 'FUNC', 'name': '_Znwm'}
|
||||||
{'type': 'FUNC', 'name': '_ZnwmRKSt9nothrow_t'}
|
{'type': 'FUNC', 'name': '_ZnwmRKSt9nothrow_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZnwmSt11align_val_t'}
|
||||||
|
{'type': 'FUNC', 'name': '_ZnwmSt11align_val_tRKSt9nothrow_t'}
|
||||||
{'type': 'FUNC', 'name': '__assert_fail@GLIBC_2.2.5'}
|
{'type': 'FUNC', 'name': '__assert_fail@GLIBC_2.2.5'}
|
||||||
{'type': 'FUNC', 'name': '__ctype_get_mb_cur_max@GLIBC_2.2.5'}
|
{'type': 'FUNC', 'name': '__ctype_get_mb_cur_max@GLIBC_2.2.5'}
|
||||||
{'type': 'FUNC', 'name': '__cxa_allocate_exception'}
|
{'type': 'FUNC', 'name': '__cxa_allocate_exception'}
|
||||||
@@ -1943,6 +1953,7 @@
|
|||||||
{'type': 'FUNC', 'name': 'nanosleep@GLIBC_2.2.5'}
|
{'type': 'FUNC', 'name': 'nanosleep@GLIBC_2.2.5'}
|
||||||
{'type': 'FUNC', 'name': 'newlocale@GLIBC_2.3'}
|
{'type': 'FUNC', 'name': 'newlocale@GLIBC_2.3'}
|
||||||
{'type': 'FUNC', 'name': 'open@GLIBC_2.2.5'}
|
{'type': 'FUNC', 'name': 'open@GLIBC_2.2.5'}
|
||||||
|
{'type': 'FUNC', 'name': 'posix_memalign@GLIBC_2.2.5'}
|
||||||
{'type': 'FUNC', 'name': 'pthread_cond_broadcast@GLIBC_2.3.2'}
|
{'type': 'FUNC', 'name': 'pthread_cond_broadcast@GLIBC_2.3.2'}
|
||||||
{'type': 'FUNC', 'name': 'pthread_cond_destroy@GLIBC_2.3.2'}
|
{'type': 'FUNC', 'name': 'pthread_cond_destroy@GLIBC_2.3.2'}
|
||||||
{'type': 'FUNC', 'name': 'pthread_cond_signal@GLIBC_2.3.2'}
|
{'type': 'FUNC', 'name': 'pthread_cond_signal@GLIBC_2.3.2'}
|
||||||
|
|||||||
126
src/new.cpp
126
src/new.cpp
@@ -39,10 +39,7 @@
|
|||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void *
|
void *
|
||||||
operator new(std::size_t size)
|
operator new(std::size_t size) _THROW_BAD_ALLOC
|
||||||
#if !__has_feature(cxx_noexcept)
|
|
||||||
throw(std::bad_alloc)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
size = 1;
|
size = 1;
|
||||||
@@ -64,6 +61,34 @@ operator new(std::size_t size)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void *
|
||||||
|
operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
size = 1;
|
||||||
|
if (static_cast<size_t>(alignment) < sizeof(void*))
|
||||||
|
alignment = std::align_val_t(sizeof(void*));
|
||||||
|
void* p;
|
||||||
|
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
||||||
|
{
|
||||||
|
// If posix_memalign fails and there is a new_handler,
|
||||||
|
// call it to try free up memory.
|
||||||
|
std::new_handler nh = std::get_new_handler();
|
||||||
|
if (nh)
|
||||||
|
nh();
|
||||||
|
else {
|
||||||
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
|
throw std::bad_alloc();
|
||||||
|
#else
|
||||||
|
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void*
|
void*
|
||||||
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||||
@@ -85,14 +110,37 @@ operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
|||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void*
|
void*
|
||||||
operator new[](size_t size)
|
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||||
#if !__has_feature(cxx_noexcept)
|
{
|
||||||
throw(std::bad_alloc)
|
void* p = 0;
|
||||||
#endif
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
p = ::operator new(size, alignment);
|
||||||
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void*
|
||||||
|
operator new[](size_t size) _THROW_BAD_ALLOC
|
||||||
{
|
{
|
||||||
return ::operator new(size);
|
return ::operator new(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void*
|
||||||
|
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||||
|
{
|
||||||
|
return ::operator new(size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void*
|
void*
|
||||||
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||||
@@ -112,6 +160,25 @@ operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void*
|
||||||
|
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||||
|
{
|
||||||
|
void* p = 0;
|
||||||
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
p = ::operator new[](size, alignment);
|
||||||
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete(void* ptr) _NOEXCEPT
|
operator delete(void* ptr) _NOEXCEPT
|
||||||
@@ -120,6 +187,14 @@ operator delete(void* ptr) _NOEXCEPT
|
|||||||
::free(ptr);
|
::free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
::free(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
|
||||||
@@ -127,6 +202,13 @@ operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|||||||
::operator delete(ptr);
|
::operator delete(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete(ptr, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete(void* ptr, size_t) _NOEXCEPT
|
operator delete(void* ptr, size_t) _NOEXCEPT
|
||||||
@@ -134,6 +216,13 @@ 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, std::align_val_t alignment) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete(ptr, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete[] (void* ptr) _NOEXCEPT
|
operator delete[] (void* ptr) _NOEXCEPT
|
||||||
@@ -141,6 +230,13 @@ operator delete[] (void* ptr) _NOEXCEPT
|
|||||||
::operator delete(ptr);
|
::operator delete(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete(ptr, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
_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
|
||||||
@@ -148,6 +244,13 @@ operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|||||||
::operator delete[](ptr);
|
::operator delete[](ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
|
void
|
||||||
|
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete[](ptr, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
|
||||||
void
|
void
|
||||||
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
||||||
@@ -155,6 +258,13 @@ 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, std::align_val_t alignment) _NOEXCEPT
|
||||||
|
{
|
||||||
|
::operator delete[](ptr, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
#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 libc++'s implementation of align_val_t, and the relevent new/delete
|
||||||
|
// overloads in all dialects when -faligned-allocation is present.
|
||||||
|
|
||||||
|
// REQUIRES: -faligned-allocation
|
||||||
|
|
||||||
|
// RUN: %build -faligned-allocation
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
static_assert(std::is_enum<std::align_val_t>::value, "");
|
||||||
|
typedef std::underlying_type<std::align_val_t>::type UT;
|
||||||
|
static_assert((std::is_same<UT, std::size_t>::value), "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static_assert((!std::is_constructible<std::align_val_t, std::size_t>::value), "");
|
||||||
|
#if TEST_STD_VER >= 11
|
||||||
|
static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, "");
|
||||||
|
#else
|
||||||
|
static_assert((std::is_constructible<std::size_t, std::align_val_t>::value), "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::align_val_t a = std::align_val_t(0);
|
||||||
|
std::align_val_t b = std::align_val_t(32);
|
||||||
|
assert(a != b);
|
||||||
|
assert(a == std::align_val_t(0));
|
||||||
|
assert(b == std::align_val_t(32));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
void *ptr = ::operator new(1, std::align_val_t(128));
|
||||||
|
assert(ptr);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0);
|
||||||
|
::operator delete(ptr, std::align_val_t(128));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
void *ptr = ::operator new(1, std::align_val_t(128), std::nothrow);
|
||||||
|
assert(ptr);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0);
|
||||||
|
::operator delete(ptr, std::align_val_t(128), std::nothrow);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
void *ptr = ::operator new[](1, std::align_val_t(128));
|
||||||
|
assert(ptr);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0);
|
||||||
|
::operator delete[](ptr, std::align_val_t(128));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
void *ptr = ::operator new[](1, std::align_val_t(128), std::nothrow);
|
||||||
|
assert(ptr);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0);
|
||||||
|
::operator delete[](ptr, std::align_val_t(128), std::nothrow);
|
||||||
|
}
|
||||||
|
#ifndef TEST_HAS_NO_RTTI
|
||||||
|
{
|
||||||
|
// Check that libc++ doesn't define align_val_t in a versioning namespace.
|
||||||
|
// And that it mangles the same in C++03 through C++17
|
||||||
|
assert(typeid(std::align_val_t).name() == std::string("St11align_val_t"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -313,6 +313,9 @@ class Configuration(object):
|
|||||||
if self.cxx.hasCompileFlag('-fsized-deallocation'):
|
if self.cxx.hasCompileFlag('-fsized-deallocation'):
|
||||||
self.config.available_features.add('fsized-deallocation')
|
self.config.available_features.add('fsized-deallocation')
|
||||||
|
|
||||||
|
if self.cxx.hasCompileFlag('-faligned-allocation'):
|
||||||
|
self.config.available_features.add('-faligned-allocation')
|
||||||
|
|
||||||
if self.get_lit_bool('has_libatomic', False):
|
if self.get_lit_bool('has_libatomic', False):
|
||||||
self.config.available_features.add('libatomic')
|
self.config.available_features.add('libatomic')
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// enum class align_val_t : size_t {}
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
static_assert(std::is_enum<std::align_val_t>::value, "");
|
||||||
|
static_assert(std::is_same<std::underlying_type<std::align_val_t>::type, std::size_t>::value, "");
|
||||||
|
static_assert(!std::is_constructible<std::align_val_t, std::size_t>::value, "");
|
||||||
|
static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
constexpr auto a = std::align_val_t(0);
|
||||||
|
constexpr auto b = std::align_val_t(32);
|
||||||
|
constexpr auto c = std::align_val_t(-1);
|
||||||
|
static_assert(a != b, "");
|
||||||
|
static_assert(a == std::align_val_t(0), "");
|
||||||
|
static_assert(b == std::align_val_t(32), "");
|
||||||
|
static_assert(static_cast<std::size_t>(c) == (std::size_t)-1, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 aligned operator delete replacement.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// Older Clang versions do not support this
|
||||||
|
// XFAIL: clang-3, apple-clang
|
||||||
|
|
||||||
|
// None of the current GCC compilers support this.
|
||||||
|
// XFAIL: gcc-4, gcc-5, gcc-6
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int aligned_delete_called = 0;
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
unsized_delete_called = 0;
|
||||||
|
unsized_delete_nothrow_called = 0;
|
||||||
|
aligned_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::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
++aligned_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A {};
|
||||||
|
struct alignas(std::max_align_t) B {};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
B *x = new B;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(1 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
{
|
||||||
|
A *x = new A;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(1 == aligned_delete_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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new
|
||||||
|
|
||||||
|
// asan and msan will not call the new handler.
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() { ++A_constructed;}
|
||||||
|
~A() { --A_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_throw_max_size() {
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new[] (std::numeric_limits<std::size_t>::max(),
|
||||||
|
static_cast<std::align_val_t>(32));
|
||||||
|
((void)vp);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new A[2];
|
||||||
|
assert(ap);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ap) % OverAligned == 0);
|
||||||
|
assert(A_constructed == 2);
|
||||||
|
delete [] ap;
|
||||||
|
assert(A_constructed == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_throw_max_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new (nothrow)
|
||||||
|
|
||||||
|
// asan and msan will not call the new handler.
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() { ++A_constructed; }
|
||||||
|
~A() { --A_constructed; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_max_alloc() {
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
auto do_test = []() {
|
||||||
|
void* vp = operator new [](std::numeric_limits<std::size_t>::max(),
|
||||||
|
std::align_val_t(OverAligned),
|
||||||
|
std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
};
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
do_test();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
do_test();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) A[3];
|
||||||
|
assert(ap);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ap) % OverAligned == 0);
|
||||||
|
assert(A_constructed == 3);
|
||||||
|
delete [] ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_max_alloc();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new nothrow by replacing only operator new
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
// TODO Investigate why UBSAN prevents nothrow new from calling our replacement.
|
||||||
|
// XFAIL: ubsan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() {++A_constructed;}
|
||||||
|
~A() {--A_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int B_constructed = 0;
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
std::max_align_t member;
|
||||||
|
B() { ++B_constructed; }
|
||||||
|
~B() { --B_constructed; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int new_called = 0;
|
||||||
|
alignas(OverAligned) char Buff[OverAligned * 3];
|
||||||
|
|
||||||
|
void* operator new[](std::size_t s, std::align_val_t a) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
assert(!new_called);
|
||||||
|
assert(s <= sizeof(Buff));
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
++new_called;
|
||||||
|
return Buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
assert(p == Buff);
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
assert(new_called);
|
||||||
|
--new_called;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new (std::nothrow) A[2];
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed == 2);
|
||||||
|
assert(new_called);
|
||||||
|
delete [] ap;
|
||||||
|
assert(A_constructed == 0);
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
B* bp = new (std::nothrow) B[2];
|
||||||
|
assert(bp);
|
||||||
|
assert(B_constructed == 2);
|
||||||
|
assert(!new_called);
|
||||||
|
delete [] bp;
|
||||||
|
assert(!new_called);
|
||||||
|
assert(!B_constructed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new replacement
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int A_constructed = 0;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A {
|
||||||
|
A() { ++A_constructed;}
|
||||||
|
~A() { --A_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int B_constructed = 0;
|
||||||
|
|
||||||
|
struct alignas(std::max_align_t) B
|
||||||
|
{
|
||||||
|
std::max_align_t member;
|
||||||
|
B() { ++B_constructed;}
|
||||||
|
~B() { --B_constructed;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int new_called = 0;
|
||||||
|
|
||||||
|
alignas(OverAligned) char DummyData[OverAligned * 4];
|
||||||
|
|
||||||
|
void* operator new[](std::size_t s, std::align_val_t a) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
assert(new_called == 0); // We already allocated
|
||||||
|
assert(s <= sizeof(DummyData));
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
++new_called;
|
||||||
|
return DummyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[](void* p, std::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
assert(new_called == 1);
|
||||||
|
--new_called;
|
||||||
|
assert(p == DummyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new A[3];
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed == 3);
|
||||||
|
assert(new_called);
|
||||||
|
delete [] ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
B* bp = new B[3];
|
||||||
|
assert(bp);
|
||||||
|
assert(B_constructed == 3);
|
||||||
|
assert(!new_called);
|
||||||
|
delete [] bp;
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 aligned operator delete replacement.
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// Older Clang versions do not support this
|
||||||
|
// XFAIL: clang-3, apple-clang
|
||||||
|
|
||||||
|
// None of the current GCC compilers support this.
|
||||||
|
// XFAIL: gcc-4, gcc-5, gcc-6
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int unsized_delete_called = 0;
|
||||||
|
int unsized_delete_nothrow_called = 0;
|
||||||
|
int aligned_delete_called = 0;
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
unsized_delete_called = 0;
|
||||||
|
unsized_delete_nothrow_called = 0;
|
||||||
|
aligned_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::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
++aligned_delete_called;
|
||||||
|
std::free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A {};
|
||||||
|
struct alignas(std::max_align_t) B {};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
B *x = new B;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(1 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
{
|
||||||
|
A *x = new A;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(0 == aligned_delete_called);
|
||||||
|
|
||||||
|
delete x;
|
||||||
|
assert(0 == unsized_delete_called);
|
||||||
|
assert(0 == unsized_delete_nothrow_called);
|
||||||
|
assert(1 == aligned_delete_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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new
|
||||||
|
|
||||||
|
// asan and msan will not call the new handler.
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_throw_max_size() {
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
void* vp = operator new (std::numeric_limits<std::size_t>::max(),
|
||||||
|
static_cast<std::align_val_t>(32));
|
||||||
|
((void)vp);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new A;
|
||||||
|
assert(ap);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ap) % OverAligned == 0);
|
||||||
|
assert(A_constructed);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_throw_max_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new (nothrow)
|
||||||
|
|
||||||
|
// asan and msan will not call the new handler.
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
int new_handler_called = 0;
|
||||||
|
|
||||||
|
void new_handler()
|
||||||
|
{
|
||||||
|
++new_handler_called;
|
||||||
|
std::set_new_handler(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_max_alloc() {
|
||||||
|
std::set_new_handler(new_handler);
|
||||||
|
auto do_test = []() {
|
||||||
|
void* vp = operator new (std::numeric_limits<std::size_t>::max(),
|
||||||
|
std::align_val_t(OverAligned),
|
||||||
|
std::nothrow);
|
||||||
|
assert(new_handler_called == 1);
|
||||||
|
assert(vp == 0);
|
||||||
|
};
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
do_test();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
do_test();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new(std::nothrow) A;
|
||||||
|
assert(ap);
|
||||||
|
assert(reinterpret_cast<std::uintptr_t>(ap) % OverAligned == 0);
|
||||||
|
assert(A_constructed);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_max_alloc();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new nothrow by replacing only operator new
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
// TODO Investigate why UBSAN prevents nothrow new from calling our replacement.
|
||||||
|
// XFAIL: ubsan
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A
|
||||||
|
{
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool B_constructed = false;
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
std::max_align_t member;
|
||||||
|
B() { B_constructed = true; }
|
||||||
|
~B() { B_constructed = false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int new_called = 0;
|
||||||
|
alignas(OverAligned) char Buff[OverAligned * 2];
|
||||||
|
|
||||||
|
void* operator new(std::size_t s, std::align_val_t a) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
assert(!new_called);
|
||||||
|
assert(s <= sizeof(Buff));
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
++new_called;
|
||||||
|
return Buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
assert(p == Buff);
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
assert(new_called);
|
||||||
|
--new_called;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new (std::nothrow) A;
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed);
|
||||||
|
assert(new_called);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
B* bp = new (std::nothrow) B;
|
||||||
|
assert(bp);
|
||||||
|
assert(B_constructed);
|
||||||
|
assert(!new_called);
|
||||||
|
delete bp;
|
||||||
|
assert(!new_called);
|
||||||
|
assert(!B_constructed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||||
|
|
||||||
|
// test operator new replacement
|
||||||
|
|
||||||
|
// UNSUPPORTED: sanitizer-new-delete
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
constexpr auto OverAligned = alignof(std::max_align_t) * 2;
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
|
||||||
|
struct alignas(OverAligned) A {
|
||||||
|
A() {A_constructed = true;}
|
||||||
|
~A() {A_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool B_constructed = false;
|
||||||
|
|
||||||
|
struct alignas(std::max_align_t) B
|
||||||
|
{
|
||||||
|
std::max_align_t member;
|
||||||
|
B() {B_constructed = true;}
|
||||||
|
~B() {B_constructed = false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
int new_called = 0;
|
||||||
|
|
||||||
|
alignas(OverAligned) char DummyData[OverAligned];
|
||||||
|
|
||||||
|
void* operator new(std::size_t s, std::align_val_t a) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
assert(new_called == 0); // We already allocated
|
||||||
|
assert(s <= sizeof(DummyData));
|
||||||
|
assert(static_cast<std::size_t>(a) == OverAligned);
|
||||||
|
++new_called;
|
||||||
|
return DummyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p, std::align_val_t a) throw()
|
||||||
|
{
|
||||||
|
assert(new_called == 1);
|
||||||
|
--new_called;
|
||||||
|
assert(p == DummyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
A* ap = new A;
|
||||||
|
assert(ap);
|
||||||
|
assert(A_constructed);
|
||||||
|
assert(new_called);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_constructed);
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
B* bp = new B;
|
||||||
|
assert(bp);
|
||||||
|
assert(B_constructed);
|
||||||
|
assert(!new_called);
|
||||||
|
delete bp;
|
||||||
|
assert(!new_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user