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_PUSH_MACROS 23 #include <__undef_macros> 24 25 _LIBCPP_BEGIN_NAMESPACE_STD 26 27 template <class _Tp> 28 _LIBCPP_NODISCARD_EXT _LIBCPP_NO_CFI 29 pair<_Tp*, ptrdiff_t> 30 get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT 31 { 32 pair<_Tp*, ptrdiff_t> __r(0, 0); 33 const ptrdiff_t __m = (~ptrdiff_t(0) ^ 34 ptrdiff_t(ptrdiff_t(1) << (sizeof(ptrdiff_t) * __CHAR_BIT__ - 1))) 35 / sizeof(_Tp); 36 if (__n > __m) 37 __n = __m; 38 while (__n > 0) 39 { 40 #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) 41 if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) 42 { 43 align_val_t __al = 44 align_val_t(alignment_of<_Tp>::value); 45 __r.first = static_cast<_Tp*>(::operator new( 46 __n * sizeof(_Tp), __al, nothrow)); 47 } else { 48 __r.first = static_cast<_Tp*>(::operator new( 49 __n * sizeof(_Tp), nothrow)); 50 } 51 #else 52 if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) 53 { 54 // Since aligned operator new is unavailable, return an empty 55 // buffer rather than one with invalid alignment. 56 return __r; 57 } 58 59 __r.first = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), nothrow)); 60 #endif 61 62 if (__r.first) 63 { 64 __r.second = __n; 65 break; 66 } 67 __n /= 2; 68 } 69 return __r; 70 } 71 72 template <class _Tp> 73 inline _LIBCPP_INLINE_VISIBILITY 74 void return_temporary_buffer(_Tp* __p) _NOEXCEPT 75 { 76 _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); 77 } 78 79 struct __return_temporary_buffer 80 { 81 template <class _Tp> 82 _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) const {_VSTD::return_temporary_buffer(__p);} 83 }; 84 85 _LIBCPP_END_NAMESPACE_STD 86 87 _LIBCPP_POP_MACROS 88 89 #endif // _LIBCPP___MEMORY_TEMPORARY_BUFFER_H 90