# endif
#endif // defined(__APPLE__)
+
#if defined(__APPLE__) || defined(__FreeBSD__)
#define _LIBCPP_HAS_DEFAULTRUNELOCALE
#endif
__allocated_ = true;
return (pointer)&buf_;
}
- return static_cast<pointer>(_VSTD::__allocate(__n * sizeof(_Tp)));
+ return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
}
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type)
{
if (__p == (pointer)&buf_)
__allocated_ = false;
else
- _VSTD::__libcpp_deallocate(__p);
+ _VSTD::__libcpp_deallocate(__p, __alignof(_Tp));
}
_LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);}
if (__n > max_size())
__throw_length_error("allocator<T>::allocate(size_t n)"
" 'n' exceeds maximum supported size");
- return static_cast<pointer>(_VSTD::__allocate(__n * sizeof(_Tp)));
+ return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
}
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type) _NOEXCEPT
- {_VSTD::__libcpp_deallocate((void*)__p);}
+ {_VSTD::__libcpp_deallocate((void*)__p, __alignof(_Tp));}
_LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT
{return size_type(~0) / sizeof(_Tp);}
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
if (__n > max_size())
__throw_length_error("allocator<const T>::allocate(size_t n)"
" 'n' exceeds maximum supported size");
- return static_cast<pointer>(_VSTD::__allocate(__n * sizeof(_Tp)));
+ return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
}
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type) _NOEXCEPT
- {_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p));}
+ {_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __alignof(_Tp));}
_LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT
{return size_type(~0) / sizeof(_Tp);}
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
while (__n > 0)
{
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
- if (std::alignment_of<_Tp>::value > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
-#else
- if (std::alignment_of<_Tp>::value >
- std::alignment_of<std::max_align_t>::value)
-#endif
+ if (__is_overaligned_for_new(__alignof(_Tp)))
{
std::align_val_t __al =
std::align_val_t(std::alignment_of<_Tp>::value);
__n * sizeof(_Tp), nothrow));
}
#else
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
- if (std::alignment_of<_Tp>::value > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
-#else
- if (std::alignment_of<_Tp>::value >
- std::alignment_of<std::max_align_t>::value)
-#endif
+ if (__is_overaligned_for_new(__alignof(_Tp)))
{
// Since aligned operator new is unavailable, return an empty
// buffer rather than one with invalid alignment.
inline _LIBCPP_INLINE_VISIBILITY
void return_temporary_buffer(_Tp* __p) _NOEXCEPT
{
-#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
- if (std::alignment_of<_Tp>::value > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
-#else
- if (std::alignment_of<_Tp>::value >
- std::alignment_of<std::max_align_t>::value)
-#endif
- {
- std::align_val_t __al = std::align_val_t(std::alignment_of<_Tp>::value);
- ::operator delete(__p, __al);
- return;
- }
-#endif
- ::operator delete(__p);
+ _VSTD::__libcpp_deallocate((void*)__p, __alignof(_Tp));
}
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
#include <__config>
#include <exception>
+#include <type_traits>
#include <cstddef>
#ifdef _LIBCPP_NO_EXCEPTIONS
#include <cstdlib>
# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
#endif
+
+#if !__has_builtin(__builtin_operator_new) || \
+ __has_builtin(__builtin_operator_new) < 201802L || \
+ defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) || \
+ !defined(__cpp_aligned_new) || __cpp_aligned_new < 201606
+#define _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
+#endif
+
namespace std // purposefully not using versioning namespace
{
_LIBCPP_BEGIN_NAMESPACE_STD
-inline _LIBCPP_INLINE_VISIBILITY void *__allocate(size_t __size) {
+_LIBCPP_CONSTEXPR inline _LIBCPP_INLINE_VISIBILITY bool __is_overaligned_for_new(size_t __align) _NOEXCEPT {
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+ return __align > __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+ return __align > alignment_of<max_align_t>::value;
+#endif
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t __align) {
+#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+ if (__is_overaligned_for_new(__align)) {
+ const align_val_t __align_val = static_cast<align_val_t>(__align);
+# ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
+ return ::operator new(__size, __align_val);
+# else
+ return __builtin_operator_new(__size, __align_val);
+# endif
+ }
+#else
+ ((void)__align);
+#endif
#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE
return ::operator new(__size);
#else
#endif
}
-inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void *__ptr) {
+inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __align) {
+#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+ if (__is_overaligned_for_new(__align)) {
+ const align_val_t __align_val = static_cast<align_val_t>(__align);
+# ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
+ return ::operator delete(__ptr, __align_val);
+# else
+ return __builtin_operator_delete(__ptr, __align_val);
+# endif
+ }
+#else
+ ((void)__align);
+#endif
#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE
- ::operator delete(__ptr);
+ return ::operator delete(__ptr);
#else
- __builtin_operator_delete(__ptr);
+ return __builtin_operator_delete(__ptr);
#endif
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<result_type*>(_VSTD::__allocate(__n * sizeof(result_type)));
+ static_cast<result_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(result_type), __alignof(result_type)));
for (size_t __i = 0; __i != __n; ++__r.__end_, ++__i)
::new (__r.__end_) result_type(__expr_[__i]);
}
{
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
{
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
{
if (__v.size())
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__v.size() * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__v.size() * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
size_t __n = __il.size();
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+_VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
size_t __n = __sa.__size_;
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
size_t __n = __ga.__1d_.size();
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
size_t __n = __ma.__1d_.size();
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
size_t __n = __ia.__1d_.size();
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
if (size() != __n)
{
__clear();
- __begin_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
__end_ = __begin_ + __n;
_VSTD::uninitialized_copy(__f, __l, __begin_);
} else {
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) value_type(+*__p);
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) value_type(-*__p);
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) value_type(~*__p);
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<bool*>(_VSTD::__allocate(__n * sizeof(bool)));
+ static_cast<bool*>(_VSTD::__libcpp_allocate(__n * sizeof(bool), __alignof(bool)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) bool(!*__p);
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
const value_type* __sb;
value_type* __tb;
value_type* __te;
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
__i %= static_cast<int>(__n);
const value_type* __m = __i >= 0 ? __begin_ + __i : __end_ + __i;
for (const value_type* __s = __m; __s != __end_; ++__r.__end_, ++__s)
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) value_type(__f(*__p));
}
{
__r.__begin_ =
__r.__end_ =
- static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n)
::new (__r.__end_) value_type(__f(*__p));
}
{
while (__end_ != __begin_)
(--__end_)->~value_type();
- _VSTD::__libcpp_deallocate(__begin_);
+ _VSTD::__libcpp_deallocate(__begin_, __alignof(value_type));
__begin_ = __end_ = nullptr;
}
}
__clear();
if (__n)
{
- __begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
+ __begin_ = __end_ = static_cast<value_type*>(
+ _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
protected:
virtual void* do_allocate(size_t __size, size_t __align)
- { return __allocate(__size); }
+ { return _VSTD::__libcpp_allocate(__size, __align); /* FIXME */}
- virtual void do_deallocate(void * __p, size_t, size_t)
- { _VSTD::__libcpp_deallocate(__p); }
+ virtual void do_deallocate(void * __p, size_t, size_t __align)
+ { _VSTD::__libcpp_deallocate(__p, __align); /* FIXME */ }
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
{ return &__other == this; }
#include <memory>
#include <cassert>
+#include "test_macros.h"
#include "count_new.hpp"
-int A_constructed = 0;
-struct A
-{
- int data;
- A() {++A_constructed;}
- A(const A&) {++A_constructed;}
- ~A() {--A_constructed;}
+#ifdef TEST_HAS_NO_ALIGNED_ALLOCATION
+static const bool UsingAlignedNew = false;
+#else
+static const bool UsingAlignedNew = true;
+#endif
+
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+static const size_t MaxAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+static const size_t MaxAligned = std::alignment_of<std::max_align_t>::value;
+#endif
+
+static const size_t OverAligned = MaxAligned * 2;
+
+
+template <size_t Align>
+struct TEST_ALIGNAS(Align) AlignedType {
+ char data;
+ static int constructed;
+ AlignedType() { ++constructed; }
+ AlignedType(AlignedType const&) { ++constructed; }
+ ~AlignedType() { --constructed; }
};
+template <size_t Align>
+int AlignedType<Align>::constructed = 0;
-int main()
-{
- globalMemCounter.reset();
- std::allocator<A> a;
+
+template <size_t Align>
+void test_aligned() {
+ typedef AlignedType<Align> T;
+ T::constructed = 0;
+ globalMemCounter.reset();
+ std::allocator<T> a;
+ const bool IsOverAlignedType = Align > MaxAligned;
+ const bool ExpectAligned = IsOverAlignedType && UsingAlignedNew;
+ {
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(A_constructed == 0);
+ assert(T::constructed == 0);
globalMemCounter.last_new_size = 0;
- A* volatile ap = a.allocate(3);
+ globalMemCounter.last_new_align = 0;
+ T* volatile ap = a.allocate(3);
assert(globalMemCounter.checkOutstandingNewEq(1));
- assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
- assert(A_constructed == 0);
+ assert(globalMemCounter.checkNewCalledEq(1));
+ assert(globalMemCounter.checkAlignedNewCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(T)));
+ assert(globalMemCounter.checkLastNewAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ globalMemCounter.last_delete_align = 0;
a.deallocate(ap, 3);
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(A_constructed == 0);
-
+ assert(globalMemCounter.checkDeleteCalledEq(1));
+ assert(globalMemCounter.checkAlignedDeleteCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastDeleteAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ }
+ globalMemCounter.reset();
+ {
globalMemCounter.last_new_size = 0;
- A* volatile ap2 = a.allocate(3, (const void*)5);
+ globalMemCounter.last_new_align = 0;
+ T* volatile ap2 = a.allocate(11, (const void*)5);
assert(globalMemCounter.checkOutstandingNewEq(1));
- assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
- assert(A_constructed == 0);
- a.deallocate(ap2, 3);
+ assert(globalMemCounter.checkNewCalledEq(1));
+ assert(globalMemCounter.checkAlignedNewCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastNewSizeEq(11 * sizeof(T)));
+ assert(globalMemCounter.checkLastNewAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ globalMemCounter.last_delete_align = 0;
+ a.deallocate(ap2, 11);
assert(globalMemCounter.checkOutstandingNewEq(0));
- assert(A_constructed == 0);
+ assert(globalMemCounter.checkDeleteCalledEq(1));
+ assert(globalMemCounter.checkAlignedDeleteCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastDeleteAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ }
+}
+
+int main() {
+ test_aligned<1>();
+ test_aligned<2>();
+ test_aligned<4>();
+ test_aligned<8>();
+ test_aligned<16>();
+ test_aligned<MaxAligned>();
+ test_aligned<OverAligned>();
+ test_aligned<OverAligned * 2>();
}
int outstanding_new;
int new_called;
int delete_called;
+ int aligned_new_called;
+ int aligned_delete_called;
std::size_t last_new_size;
+ std::size_t last_new_align;
+ std::size_t last_delete_align;
int outstanding_array_new;
int new_array_called;
int delete_array_called;
+ int aligned_new_array_called;
+ int aligned_delete_array_called;
std::size_t last_new_array_size;
+ std::size_t last_new_array_align;
+ std::size_t last_delete_array_align;
public:
void newCalled(std::size_t s)
last_new_size = s;
}
+ void alignedNewCalled(std::size_t s, std::size_t a) {
+ newCalled(s);
+ ++aligned_new_called;
+ last_new_align = a;
+ }
+
void deleteCalled(void * p)
{
assert(p);
++delete_called;
}
+ void alignedDeleteCalled(void *p, std::size_t a) {
+ deleteCalled(p);
+ ++aligned_delete_called;
+ last_delete_align = a;
+ }
+
void newArrayCalled(std::size_t s)
{
assert(disable_allocations == false);
last_new_array_size = s;
}
+ void alignedNewArrayCalled(std::size_t s, std::size_t a) {
+ newArrayCalled(s);
+ ++aligned_new_array_called;
+ last_new_array_align = a;
+ }
+
void deleteArrayCalled(void * p)
{
assert(p);
++delete_array_called;
}
+ void alignedDeleteArrayCalled(void * p, std::size_t a) {
+ deleteArrayCalled(p);
+ ++aligned_delete_array_called;
+ last_delete_array_align = a;
+ }
+
void disableAllocations()
{
disable_allocations = true;
disable_allocations = false;
}
-
void reset()
{
disable_allocations = false;
outstanding_new = 0;
new_called = 0;
delete_called = 0;
+ aligned_new_called = 0;
+ aligned_delete_called = 0;
last_new_size = 0;
+ last_new_align = 0;
outstanding_array_new = 0;
new_array_called = 0;
delete_array_called = 0;
+ aligned_new_array_called = 0;
+ aligned_delete_array_called = 0;
last_new_array_size = 0;
+ last_new_array_align = 0;
}
public:
return disable_checking || n != delete_called;
}
+ bool checkAlignedNewCalledEq(int n) const
+ {
+ return disable_checking || n == aligned_new_called;
+ }
+
+ bool checkAlignedNewCalledNotEq(int n) const
+ {
+ return disable_checking || n != aligned_new_called;
+ }
+
+ bool checkAlignedNewCalledGreaterThan(int n) const
+ {
+ return disable_checking || aligned_new_called > n;
+ }
+
+ bool checkAlignedDeleteCalledEq(int n) const
+ {
+ return disable_checking || n == aligned_delete_called;
+ }
+
+ bool checkAlignedDeleteCalledNotEq(int n) const
+ {
+ return disable_checking || n != aligned_delete_called;
+ }
+
bool checkLastNewSizeEq(std::size_t n) const
{
return disable_checking || n == last_new_size;
return disable_checking || n != last_new_size;
}
+ bool checkLastNewAlignEq(std::size_t n) const
+ {
+ return disable_checking || n == last_new_align;
+ }
+
+ bool checkLastNewAlignNotEq(std::size_t n) const
+ {
+ return disable_checking || n != last_new_align;
+ }
+
+ bool checkLastDeleteAlignEq(std::size_t n) const
+ {
+ return disable_checking || n == last_delete_align;
+ }
+
+ bool checkLastDeleteAlignNotEq(std::size_t n) const
+ {
+ return disable_checking || n != last_delete_align;
+ }
+
bool checkOutstandingArrayNewEq(int n) const
{
return disable_checking || n == outstanding_array_new;
return disable_checking || n != delete_array_called;
}
+ bool checkAlignedNewArrayCalledEq(int n) const
+ {
+ return disable_checking || n == aligned_new_array_called;
+ }
+
+ bool checkAlignedNewArrayCalledNotEq(int n) const
+ {
+ return disable_checking || n != aligned_new_array_called;
+ }
+
+ bool checkAlignedNewArrayCalledGreaterThan(int n) const
+ {
+ return disable_checking || aligned_new_array_called > n;
+ }
+
+ bool checkAlignedDeleteArrayCalledEq(int n) const
+ {
+ return disable_checking || n == aligned_delete_array_called;
+ }
+
+ bool checkAlignedDeleteArrayCalledNotEq(int n) const
+ {
+ return disable_checking || n != aligned_delete_array_called;
+ }
+
bool checkLastNewArraySizeEq(std::size_t n) const
{
return disable_checking || n == last_new_array_size;
{
return disable_checking || n != last_new_array_size;
}
+
+ bool checkLastNewArrayAlignEq(std::size_t n) const
+ {
+ return disable_checking || n == last_new_array_align;
+ }
+
+ bool checkLastNewArrayAlignNotEq(std::size_t n) const
+ {
+ return disable_checking || n != last_new_array_align;
+ }
};
#ifdef DISABLE_NEW_COUNT
std::free(p);
}
-
void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
{
getGlobalMemCounter()->newArrayCalled(s);
return operator new(s);
}
-
void operator delete[](void* p) TEST_NOEXCEPT
{
getGlobalMemCounter()->deleteArrayCalled(p);
operator delete(p);
}
-#endif // DISABLE_NEW_COUNT
+#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
+#if defined(_LIBCPP_MSVCRT_LIKE) || \
+ (!defined(_LIBCPP_VERSION) && defined(_WIN32))
+#define USE_ALIGNED_ALLOC
+#endif
+void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
+ const std::size_t a = static_cast<std::size_t>(av);
+ getGlobalMemCounter()->alignedNewCalled(s, a);
+ void *ret;
+#ifdef USE_ALIGNED_ALLOC
+ ret = _aligned_malloc(s, a);
+#else
+ posix_memalign(&ret, a, s);
+#endif
+ if (ret == nullptr)
+ detail::throw_bad_alloc_helper();
+ return ret;
+}
+
+void operator delete(void *p, std::align_val_t av) TEST_NOEXCEPT {
+ const std::size_t a = static_cast<std::size_t>(av);
+ getGlobalMemCounter()->alignedDeleteCalled(p, a);
+ if (p) {
+#ifdef USE_ALIGNED_ALLOC
+ ::_aligned_free(p);
+#else
+ ::free(p);
+#endif
+ }
+}
+
+void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
+ const std::size_t a = static_cast<std::size_t>(av);
+ getGlobalMemCounter()->alignedNewArrayCalled(s, a);
+ return operator new(s, av);
+}
+
+void operator delete[](void *p, std::align_val_t av) TEST_NOEXCEPT {
+ const std::size_t a = static_cast<std::size_t>(av);
+ getGlobalMemCounter()->alignedDeleteArrayCalled(p, a);
+ return operator delete(p, av);
+}
+
+#endif // TEST_HAS_NO_ALIGNED_ALLOCATION
+
+#endif // DISABLE_NEW_COUNT
struct DisableAllocationGuard {
explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
DisableAllocationGuard& operator=(DisableAllocationGuard const&);
};
-
struct RequireAllocationGuard {
explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
: m_req_alloc(RequireAtLeast),
#define TEST_NORETURN [[noreturn]]
#endif
+#if !defined(__cpp_aligned_new) || __cpp_aligned_new < 201606L || \
+ defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
+#define TEST_HAS_NO_ALIGNED_ALLOCATION
+#endif
+
#if defined(_LIBCPP_SAFE_STATIC)
#define TEST_SAFE_STATIC _LIBCPP_SAFE_STATIC
#else
}
#endif
+
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif