Author: rsmith Date: Thu Feb 1 14:24:45 2018 New Revision: 324020 URL: http://llvm.org/viewvc/llvm-project?rev=324020&view=rev Log: Make std::get_temporary_buffer respect overaligned types when possible
Patch by Chris Kennelly! Differential Revision: https://reviews.llvm.org/D41746 Added: libcxx/trunk/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp Modified: libcxx/trunk/include/memory Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=324020&r1=324019&r2=324020&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Thu Feb 1 14:24:45 2018 @@ -2004,7 +2004,38 @@ get_temporary_buffer(ptrdiff_t __n) _NOE __n = __m; 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 + { + std::align_val_t __al = + std::align_val_t(std::alignment_of<_Tp>::value); + __r.first = static_cast<_Tp*>(::operator new( + __n * sizeof(_Tp), __al, nothrow)); + } else { + __r.first = static_cast<_Tp*>(::operator new( + __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 + { + // Since aligned operator new is unavailable, return an empty + // buffer rather than one with invalid alignment. + return __r; + } + __r.first = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), nothrow)); +#endif + if (__r.first) { __r.second = __n; @@ -2017,7 +2048,23 @@ get_temporary_buffer(ptrdiff_t __n) _NOE template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -void return_temporary_buffer(_Tp* __p) _NOEXCEPT {::operator delete(__p);} +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); +} #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) template <class _Tp> Added: libcxx/trunk/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp?rev=324020&view=auto ============================================================================== --- libcxx/trunk/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp (added) +++ libcxx/trunk/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp Thu Feb 1 14:24:45 2018 @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <memory> + +// template <class T> +// pair<T*, ptrdiff_t> +// get_temporary_buffer(ptrdiff_t n); +// +// template <class T> +// void +// return_temporary_buffer(T* p); + +#include <memory> +#include <cassert> + +struct alignas(32) A { + int field; +}; + +int main() +{ + std::pair<A*, std::ptrdiff_t> ip = std::get_temporary_buffer<A>(5); + assert(!(ip.first == nullptr) ^ (ip.second == 0)); + assert(reinterpret_cast<uintptr_t>(ip.first) % alignof(A) == 0); + std::return_temporary_buffer(ip.first); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits