1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___MEMORY_TEMPORARY_BUFFER_H 11 #define _LIBCPP___MEMORY_TEMPORARY_BUFFER_H 12 13 #include <__config> 14 #include <cstddef> 15 #include <new> 16 #include <utility> // pair 17 18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19 #pragma GCC system_header 20 #endif 21 22 _LIBCPP_BEGIN_NAMESPACE_STD 23 24 template <class _Tp> 25 _LIBCPP_NODISCARD_EXT _LIBCPP_NO_CFI 26 pair<_Tp*, ptrdiff_t> 27 get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT 28 { 29 pair<_Tp*, ptrdiff_t> __r(0, 0); 30 const ptrdiff_t __m = (~ptrdiff_t(0) ^ 31 ptrdiff_t(ptrdiff_t(1) << (sizeof(ptrdiff_t) * __CHAR_BIT__ - 1))) 32 / sizeof(_Tp); 33 if (__n > __m) 34 __n = __m; 35 while (__n > 0) 36 { 37 #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) 38 if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) 39 { 40 align_val_t __al = 41 align_val_t(alignment_of<_Tp>::value); 42 __r.first = static_cast<_Tp*>(::operator new( 43 __n * sizeof(_Tp), __al, nothrow)); 44 } else { 45 __r.first = static_cast<_Tp*>(::operator new( 46 __n * sizeof(_Tp), nothrow)); 47 } 48 #else 49 if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) 50 { 51 // Since aligned operator new is unavailable, return an empty 52 // buffer rather than one with invalid alignment. 53 return __r; 54 } 55 56 __r.first = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), nothrow)); 57 #endif 58 59 if (__r.first) 60 { 61 __r.second = __n; 62 break; 63 } 64 __n /= 2; 65 } 66 return __r; 67 } 68 69 template <class _Tp> 70 inline _LIBCPP_INLINE_VISIBILITY 71 void return_temporary_buffer(_Tp* __p) _NOEXCEPT 72 { 73 _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); 74 } 75 76 struct __return_temporary_buffer 77 { 78 template <class _Tp> 79 _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) const {_VSTD::return_temporary_buffer(__p);} 80 }; 81 82 _LIBCPP_END_NAMESPACE_STD 83 84 #endif // _LIBCPP___MEMORY_TEMPORARY_BUFFER_H 85