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
diff --git a/include/new b/include/new
index e77d3e6..c42ea08 100644
--- a/include/new
+++ b/include/new
@@ -27,18 +27,19 @@
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:
bad_array_length() noexcept;
};
-class bad_array_new_length : public bad_alloc
+class bad_array_new_length : public bad_alloc // C++14
{
public:
bad_array_new_length() noexcept;
};
+enum class align_val_t : size_t {}; // C++17
struct nothrow_t {};
extern const nothrow_t nothrow;
typedef void (*new_handler)();
@@ -48,16 +49,34 @@
} // std
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, 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, 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, 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,
+ 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, 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, 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, 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;
@@ -79,6 +98,16 @@
#pragma GCC system_header
#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
{
@@ -117,6 +146,14 @@
#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 {};
extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
typedef void (*new_handler)();
@@ -131,32 +168,46 @@
# define _LIBCPP_NEW_DELETE_VIS _LIBCPP_FUNC_VIS
#endif
-_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz)
#if !__has_feature(cxx_noexcept)
- throw(std::bad_alloc)
+#define _THROW_BAD_ALLOC throw(std::bad_alloc)
+#else
+#define _THROW_BAD_ALLOC
#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 delete(void* __p) _NOEXCEPT;
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
-#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
- (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
+#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
_LIBCPP_NEW_DELETE_VIS void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
#endif
-_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
-#if !__has_feature(cxx_noexcept)
- throw(std::bad_alloc)
-#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 delete[](void* __p) _NOEXCEPT;
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
-#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
- (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
+#ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
_LIBCPP_NEW_DELETE_VIS void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
#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 delete (void*, void*) _NOEXCEPT {}