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_ALLOCATOR_H 11 #define _LIBCPP___MEMORY_ALLOCATOR_H 12 13 #include <__config> 14 #include <__memory/allocator_traits.h> 15 #include <cstddef> 16 #include <new> 17 #include <stdexcept> 18 #include <type_traits> 19 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21 #pragma GCC system_header 22 #endif 23 24 _LIBCPP_PUSH_MACROS 25 #include <__undef_macros> 26 27 _LIBCPP_BEGIN_NAMESPACE_STD 28 29 template <class _Tp> class allocator; 30 31 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) 32 template <> 33 class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<void> 34 { 35 public: 36 typedef void* pointer; 37 typedef const void* const_pointer; 38 typedef void value_type; 39 40 template <class _Up> struct rebind {typedef allocator<_Up> other;}; 41 }; 42 43 template <> 44 class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<const void> 45 { 46 public: 47 typedef const void* pointer; 48 typedef const void* const_pointer; 49 typedef const void value_type; 50 51 template <class _Up> struct rebind {typedef allocator<_Up> other;}; 52 }; 53 #endif 54 55 // allocator 56 57 template <class _Tp> 58 class _LIBCPP_TEMPLATE_VIS allocator 59 { 60 public: 61 typedef size_t size_type; 62 typedef ptrdiff_t difference_type; 63 typedef _Tp value_type; 64 typedef true_type propagate_on_container_move_assignment; 65 typedef true_type is_always_equal; 66 67 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator()68 allocator() _NOEXCEPT { } 69 70 template <class _Up> 71 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator(const allocator<_Up> &)72 allocator(const allocator<_Up>&) _NOEXCEPT { } 73 74 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocate(size_t __n)75 _Tp* allocate(size_t __n) { 76 if (__n > allocator_traits<allocator>::max_size(*this)) 77 __throw_length_error("allocator<T>::allocate(size_t n)" 78 " 'n' exceeds maximum supported size"); 79 if (__libcpp_is_constant_evaluated()) { 80 return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); 81 } else { 82 return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); 83 } 84 } 85 86 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 deallocate(_Tp * __p,size_t __n)87 void deallocate(_Tp* __p, size_t __n) _NOEXCEPT { 88 if (__libcpp_is_constant_evaluated()) { 89 ::operator delete(__p); 90 } else { 91 _VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); 92 } 93 } 94 95 // C++20 Removed members 96 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) 97 _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* pointer; 98 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; 99 _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp& reference; 100 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; 101 102 template <class _Up> 103 struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { 104 typedef allocator<_Up> other; 105 }; 106 107 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY address(reference __x)108 pointer address(reference __x) const _NOEXCEPT { 109 return _VSTD::addressof(__x); 110 } 111 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY address(const_reference __x)112 const_pointer address(const_reference __x) const _NOEXCEPT { 113 return _VSTD::addressof(__x); 114 } 115 116 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 allocate(size_t __n,const void *)117 _Tp* allocate(size_t __n, const void*) { 118 return allocate(__n); 119 } 120 max_size()121 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { 122 return size_type(~0) / sizeof(_Tp); 123 } 124 125 template <class _Up, class... _Args> 126 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY construct(_Up * __p,_Args &&...__args)127 void construct(_Up* __p, _Args&&... __args) { 128 ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); 129 } 130 131 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY destroy(pointer __p)132 void destroy(pointer __p) { 133 __p->~_Tp(); 134 } 135 #endif 136 }; 137 138 template <class _Tp> 139 class _LIBCPP_TEMPLATE_VIS allocator<const _Tp> 140 { 141 public: 142 typedef size_t size_type; 143 typedef ptrdiff_t difference_type; 144 typedef const _Tp value_type; 145 typedef true_type propagate_on_container_move_assignment; 146 typedef true_type is_always_equal; 147 148 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator()149 allocator() _NOEXCEPT { } 150 151 template <class _Up> 152 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator(const allocator<_Up> &)153 allocator(const allocator<_Up>&) _NOEXCEPT { } 154 155 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocate(size_t __n)156 const _Tp* allocate(size_t __n) { 157 if (__n > allocator_traits<allocator>::max_size(*this)) 158 __throw_length_error("allocator<const T>::allocate(size_t n)" 159 " 'n' exceeds maximum supported size"); 160 if (__libcpp_is_constant_evaluated()) { 161 return static_cast<const _Tp*>(::operator new(__n * sizeof(_Tp))); 162 } else { 163 return static_cast<const _Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); 164 } 165 } 166 167 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 deallocate(const _Tp * __p,size_t __n)168 void deallocate(const _Tp* __p, size_t __n) { 169 if (__libcpp_is_constant_evaluated()) { 170 ::operator delete(const_cast<_Tp*>(__p)); 171 } else { 172 _VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); 173 } 174 } 175 176 // C++20 Removed members 177 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) 178 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; 179 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; 180 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; 181 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; 182 183 template <class _Up> 184 struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { 185 typedef allocator<_Up> other; 186 }; 187 188 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY address(const_reference __x)189 const_pointer address(const_reference __x) const _NOEXCEPT { 190 return _VSTD::addressof(__x); 191 } 192 193 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 allocate(size_t __n,const void *)194 const _Tp* allocate(size_t __n, const void*) { 195 return allocate(__n); 196 } 197 max_size()198 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { 199 return size_type(~0) / sizeof(_Tp); 200 } 201 202 template <class _Up, class... _Args> 203 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY construct(_Up * __p,_Args &&...__args)204 void construct(_Up* __p, _Args&&... __args) { 205 ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); 206 } 207 208 _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY destroy(pointer __p)209 void destroy(pointer __p) { 210 __p->~_Tp(); 211 } 212 #endif 213 }; 214 215 template <class _Tp, class _Up> 216 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 217 bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} 218 219 template <class _Tp, class _Up> 220 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 221 bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} 222 223 _LIBCPP_END_NAMESPACE_STD 224 225 _LIBCPP_POP_MACROS 226 227 #endif // _LIBCPP___MEMORY_ALLOCATOR_H 228