summaryrefslogtreecommitdiffstats
path: root/libcxx/include/new
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2018-03-22 04:42:56 +0000
committerEric Fiselier <eric@efcs.ca>2018-03-22 04:42:56 +0000
commitf2918d1c24c9e69f1c63a4ca864bbd68ef5a51cc (patch)
treea3e112d71ad60d20340cfbf634b0da3a882d6ff7 /libcxx/include/new
parentfc179c6dd59b0da8068ecb800095e79d2ec41bc6 (diff)
downloadbcm5719-llvm-f2918d1c24c9e69f1c63a4ca864bbd68ef5a51cc.tar.gz
bcm5719-llvm-f2918d1c24c9e69f1c63a4ca864bbd68ef5a51cc.zip
Fix PR22634 - std::allocator doesn't respect over-aligned types.
This patch fixes std::allocator, and more specifically, all users of __libcpp_allocate and __libcpp_deallocate, to support over-aligned types. __libcpp_allocate/deallocate now take an alignment parameter, and when the specified alignment is greater than that supported by malloc/new, the aligned version of operator new is called (assuming it's available). When aligned new isn't available, the old behavior has been kept, and the alignment parameter is ignored. This patch depends on recent changes to __builtin_operator_new/delete which allow them to be used to call any regular new/delete operator. By using __builtin_operator_new/delete when possible, the new/delete erasure optimization is maintained. llvm-svn: 328180
Diffstat (limited to 'libcxx/include/new')
-rw-r--r--libcxx/include/new49
1 files changed, 45 insertions, 4 deletions
diff --git a/libcxx/include/new b/libcxx/include/new
index 27c248c83c9..e42ffad27ed 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -89,6 +89,7 @@ void operator delete[](void* ptr, void*) noexcept;
#include <__config>
#include <exception>
+#include <type_traits>
#include <cstddef>
#ifdef _LIBCPP_NO_EXCEPTIONS
#include <cstdlib>
@@ -113,6 +114,14 @@ void operator delete[](void* ptr, void*) noexcept;
# 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
{
@@ -223,7 +232,27 @@ inline _LIBCPP_INLINE_VISIBILITY void operator delete[](void*, void*) _NOEXCEPT
_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
@@ -231,11 +260,23 @@ inline _LIBCPP_INLINE_VISIBILITY void *__allocate(size_t __size) {
#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
}
OpenPOWER on IntegriCloud