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
68     allocator() _NOEXCEPT { }
69 
70     template <class _Up>
71     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
72     allocator(const allocator<_Up>&) _NOEXCEPT { }
73 
74     _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
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
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
108     pointer address(reference __x) const _NOEXCEPT {
109         return _VSTD::addressof(__x);
110     }
111     _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY
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
117     _Tp* allocate(size_t __n, const void*) {
118         return allocate(__n);
119     }
120 
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
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
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
149     allocator() _NOEXCEPT { }
150 
151     template <class _Up>
152     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
153     allocator(const allocator<_Up>&) _NOEXCEPT { }
154 
155     _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
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
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
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
194     const _Tp* allocate(size_t __n, const void*) {
195         return allocate(__n);
196     }
197 
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
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
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