1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef MIN_ALLOCATOR_H
10 #define MIN_ALLOCATOR_H
19 #include <type_traits>
22 #include "test_macros.h"
30 bare_allocator() TEST_NOEXCEPT
{}
33 bare_allocator(bare_allocator
<U
>) TEST_NOEXCEPT
{}
35 T
* allocate(std::size_t n
)
37 return static_cast<T
*>(::operator new(n
*sizeof(T
)));
40 void deallocate(T
* p
, std::size_t)
42 return ::operator delete(static_cast<void*>(p
));
45 friend bool operator==(bare_allocator
, bare_allocator
) {return true;}
46 friend bool operator!=(bare_allocator x
, bare_allocator y
) {return !(x
== y
);}
51 class no_default_allocator
53 #if TEST_STD_VER >= 11
54 no_default_allocator() = delete;
56 no_default_allocator();
58 struct construct_tag
{};
59 explicit no_default_allocator(construct_tag
) {}
62 static no_default_allocator
create() {
64 return no_default_allocator(tag
);
71 no_default_allocator(no_default_allocator
<U
>) TEST_NOEXCEPT
{}
73 T
* allocate(std::size_t n
)
75 return static_cast<T
*>(::operator new(n
*sizeof(T
)));
78 void deallocate(T
* p
, std::size_t)
80 return ::operator delete(static_cast<void*>(p
));
83 friend bool operator==(no_default_allocator
, no_default_allocator
) {return true;}
84 friend bool operator!=(no_default_allocator x
, no_default_allocator y
) {return !(x
== y
);}
87 struct malloc_allocator_base
{
88 static std::size_t outstanding_bytes
;
89 static std::size_t alloc_count
;
90 static std::size_t dealloc_count
;
91 static bool disable_default_constructor
;
93 static std::size_t outstanding_alloc() {
94 assert(alloc_count
>= dealloc_count
);
95 return (alloc_count
- dealloc_count
);
99 assert(outstanding_alloc() == 0);
100 disable_default_constructor
= false;
101 outstanding_bytes
= 0;
107 size_t malloc_allocator_base::outstanding_bytes
= 0;
108 size_t malloc_allocator_base::alloc_count
= 0;
109 size_t malloc_allocator_base::dealloc_count
= 0;
110 bool malloc_allocator_base::disable_default_constructor
= false;
114 class malloc_allocator
: public malloc_allocator_base
117 typedef T value_type
;
119 malloc_allocator() TEST_NOEXCEPT
{ assert(!disable_default_constructor
); }
122 malloc_allocator(malloc_allocator
<U
>) TEST_NOEXCEPT
{}
124 T
* allocate(std::size_t n
)
126 const std::size_t nbytes
= n
*sizeof(T
);
128 outstanding_bytes
+= nbytes
;
129 return static_cast<T
*>(std::malloc(nbytes
));
132 void deallocate(T
* p
, std::size_t n
)
134 const std::size_t nbytes
= n
*sizeof(T
);
136 outstanding_bytes
-= nbytes
;
137 std::free(static_cast<void*>(p
));
140 friend bool operator==(malloc_allocator
, malloc_allocator
) {return true;}
141 friend bool operator!=(malloc_allocator x
, malloc_allocator y
) {return !(x
== y
);}
145 struct cpp03_allocator
: bare_allocator
<T
>
147 typedef T value_type
;
148 typedef value_type
* pointer
;
150 static bool construct_called
;
152 // Returned value is not used but it's not prohibited.
153 pointer
construct(pointer p
, const value_type
& val
)
155 ::new(p
) value_type(val
);
156 construct_called
= true;
160 std::size_t max_size() const
162 return UINT_MAX
/ sizeof(T
);
165 template <class T
> bool cpp03_allocator
<T
>::construct_called
= false;
168 struct cpp03_overload_allocator
: bare_allocator
<T
>
170 typedef T value_type
;
171 typedef value_type
* pointer
;
173 static bool construct_called
;
175 void construct(pointer p
, const value_type
& val
)
177 construct(p
, val
, std::is_class
<T
>());
179 void construct(pointer p
, const value_type
& val
, std::true_type
)
181 ::new(p
) value_type(val
);
182 construct_called
= true;
184 void construct(pointer p
, const value_type
& val
, std::false_type
)
186 ::new(p
) value_type(val
);
187 construct_called
= true;
190 std::size_t max_size() const
192 return UINT_MAX
/ sizeof(T
);
195 template <class T
> bool cpp03_overload_allocator
<T
>::construct_called
= false;
197 template <class T
, class = std::integral_constant
<std::size_t, 0> > class min_pointer
;
198 template <class T
, class ID
> class min_pointer
<const T
, ID
>;
199 template <class ID
> class min_pointer
<void, ID
>;
200 template <class ID
> class min_pointer
<const void, ID
>;
201 template <class T
> class min_allocator
;
204 class min_pointer
<const void, ID
>
208 min_pointer() TEST_NOEXCEPT
= default;
209 min_pointer(std::nullptr_t
) TEST_NOEXCEPT
: ptr_(nullptr) {}
211 min_pointer(min_pointer
<T
, ID
> p
) TEST_NOEXCEPT
: ptr_(p
.ptr_
) {}
213 explicit operator bool() const {return ptr_
!= nullptr;}
215 friend bool operator==(min_pointer x
, min_pointer y
) {return x
.ptr_
== y
.ptr_
;}
216 friend bool operator!=(min_pointer x
, min_pointer y
) {return !(x
== y
);}
217 template <class U
, class XID
> friend class min_pointer
;
221 class min_pointer
<void, ID
>
225 min_pointer() TEST_NOEXCEPT
= default;
226 TEST_CONSTEXPR_CXX14
min_pointer(std::nullptr_t
) TEST_NOEXCEPT
: ptr_(nullptr) {}
228 class = typename
std::enable_if
230 !std::is_const
<T
>::value
233 TEST_CONSTEXPR_CXX14
min_pointer(min_pointer
<T
, ID
> p
) TEST_NOEXCEPT
: ptr_(p
.ptr_
) {}
235 TEST_CONSTEXPR_CXX14
explicit operator bool() const {return ptr_
!= nullptr;}
237 TEST_CONSTEXPR_CXX14
friend bool operator==(min_pointer x
, min_pointer y
) {return x
.ptr_
== y
.ptr_
;}
238 TEST_CONSTEXPR_CXX14
friend bool operator!=(min_pointer x
, min_pointer y
) {return !(x
== y
);}
239 template <class U
, class XID
> friend class min_pointer
;
242 template <class T
, class ID
>
247 TEST_CONSTEXPR_CXX14
explicit min_pointer(T
* p
) TEST_NOEXCEPT
: ptr_(p
) {}
249 min_pointer() TEST_NOEXCEPT
= default;
250 TEST_CONSTEXPR_CXX14
min_pointer(std::nullptr_t
) TEST_NOEXCEPT
: ptr_(nullptr) {}
251 TEST_CONSTEXPR_CXX14
explicit min_pointer(min_pointer
<void, ID
> p
) TEST_NOEXCEPT
: ptr_(static_cast<T
*>(p
.ptr_
)) {}
253 TEST_CONSTEXPR_CXX14
explicit operator bool() const {return ptr_
!= nullptr;}
255 typedef std::ptrdiff_t difference_type
;
256 typedef T
& reference
;
258 typedef T value_type
;
259 typedef std::random_access_iterator_tag iterator_category
;
261 TEST_CONSTEXPR_CXX14 reference
operator*() const {return *ptr_
;}
262 TEST_CONSTEXPR_CXX14 pointer
operator->() const {return ptr_
;}
264 TEST_CONSTEXPR_CXX14 min_pointer
& operator++() {++ptr_
; return *this;}
265 TEST_CONSTEXPR_CXX14 min_pointer
operator++(int) {min_pointer
tmp(*this); ++ptr_
; return tmp
;}
267 TEST_CONSTEXPR_CXX14 min_pointer
& operator--() {--ptr_
; return *this;}
268 TEST_CONSTEXPR_CXX14 min_pointer
operator--(int) {min_pointer
tmp(*this); --ptr_
; return tmp
;}
270 TEST_CONSTEXPR_CXX14 min_pointer
& operator+=(difference_type n
) {ptr_
+= n
; return *this;}
271 TEST_CONSTEXPR_CXX14 min_pointer
& operator-=(difference_type n
) {ptr_
-= n
; return *this;}
273 TEST_CONSTEXPR_CXX14 min_pointer
operator+(difference_type n
) const
275 min_pointer
tmp(*this);
280 friend TEST_CONSTEXPR_CXX14 min_pointer
operator+(difference_type n
, min_pointer x
)
285 TEST_CONSTEXPR_CXX14 min_pointer
operator-(difference_type n
) const
287 min_pointer
tmp(*this);
292 friend TEST_CONSTEXPR_CXX14 difference_type
operator-(min_pointer x
, min_pointer y
)
294 return x
.ptr_
- y
.ptr_
;
297 TEST_CONSTEXPR_CXX14 reference
operator[](difference_type n
) const {return ptr_
[n
];}
299 friend TEST_CONSTEXPR_CXX14
bool operator< (min_pointer x
, min_pointer y
) {return x
.ptr_
< y
.ptr_
;}
300 friend TEST_CONSTEXPR_CXX14
bool operator> (min_pointer x
, min_pointer y
) {return y
< x
;}
301 friend TEST_CONSTEXPR_CXX14
bool operator<=(min_pointer x
, min_pointer y
) {return !(y
< x
);}
302 friend TEST_CONSTEXPR_CXX14
bool operator>=(min_pointer x
, min_pointer y
) {return !(x
< y
);}
304 static TEST_CONSTEXPR_CXX14 min_pointer
pointer_to(T
& t
) {return min_pointer(std::addressof(t
));}
306 friend TEST_CONSTEXPR_CXX14
bool operator==(min_pointer x
, min_pointer y
) {return x
.ptr_
== y
.ptr_
;}
307 friend TEST_CONSTEXPR_CXX14
bool operator!=(min_pointer x
, min_pointer y
) {return !(x
== y
);}
308 template <class U
, class XID
> friend class min_pointer
;
309 template <class U
> friend class min_allocator
;
312 template <class T
, class ID
>
313 class min_pointer
<const T
, ID
>
317 TEST_CONSTEXPR_CXX14
explicit min_pointer(const T
* p
) : ptr_(p
) {}
319 min_pointer() TEST_NOEXCEPT
= default;
320 TEST_CONSTEXPR_CXX14
min_pointer(std::nullptr_t
) : ptr_(nullptr) {}
321 TEST_CONSTEXPR_CXX14
min_pointer(min_pointer
<T
, ID
> p
) : ptr_(p
.ptr_
) {}
322 TEST_CONSTEXPR_CXX14
explicit min_pointer(min_pointer
<const void, ID
> p
) : ptr_(static_cast<const T
*>(p
.ptr_
)) {}
324 TEST_CONSTEXPR_CXX14
explicit operator bool() const {return ptr_
!= nullptr;}
326 typedef std::ptrdiff_t difference_type
;
327 typedef const T
& reference
;
328 typedef const T
* pointer
;
329 typedef const T value_type
;
330 typedef std::random_access_iterator_tag iterator_category
;
332 TEST_CONSTEXPR_CXX14 reference
operator*() const {return *ptr_
;}
333 TEST_CONSTEXPR_CXX14 pointer
operator->() const {return ptr_
;}
335 TEST_CONSTEXPR_CXX14 min_pointer
& operator++() {++ptr_
; return *this;}
336 TEST_CONSTEXPR_CXX14 min_pointer
operator++(int) {min_pointer
tmp(*this); ++ptr_
; return tmp
;}
338 TEST_CONSTEXPR_CXX14 min_pointer
& operator--() {--ptr_
; return *this;}
339 TEST_CONSTEXPR_CXX14 min_pointer
operator--(int) {min_pointer
tmp(*this); --ptr_
; return tmp
;}
341 TEST_CONSTEXPR_CXX14 min_pointer
& operator+=(difference_type n
) {ptr_
+= n
; return *this;}
342 TEST_CONSTEXPR_CXX14 min_pointer
& operator-=(difference_type n
) {ptr_
-= n
; return *this;}
344 TEST_CONSTEXPR_CXX14 min_pointer
operator+(difference_type n
) const
346 min_pointer
tmp(*this);
351 friend TEST_CONSTEXPR_CXX14 min_pointer
operator+(difference_type n
, min_pointer x
)
356 TEST_CONSTEXPR_CXX14 min_pointer
operator-(difference_type n
) const
358 min_pointer
tmp(*this);
363 friend TEST_CONSTEXPR_CXX14 difference_type
operator-(min_pointer x
, min_pointer y
)
365 return x
.ptr_
- y
.ptr_
;
368 TEST_CONSTEXPR_CXX14 reference
operator[](difference_type n
) const {return ptr_
[n
];}
370 friend TEST_CONSTEXPR_CXX14
bool operator< (min_pointer x
, min_pointer y
) {return x
.ptr_
< y
.ptr_
;}
371 friend TEST_CONSTEXPR_CXX14
bool operator> (min_pointer x
, min_pointer y
) {return y
< x
;}
372 friend TEST_CONSTEXPR_CXX14
bool operator<=(min_pointer x
, min_pointer y
) {return !(y
< x
);}
373 friend TEST_CONSTEXPR_CXX14
bool operator>=(min_pointer x
, min_pointer y
) {return !(x
< y
);}
375 static TEST_CONSTEXPR_CXX14 min_pointer
pointer_to(const T
& t
) {return min_pointer(std::addressof(t
));}
377 friend TEST_CONSTEXPR_CXX14
bool operator==(min_pointer x
, min_pointer y
) {return x
.ptr_
== y
.ptr_
;}
378 friend TEST_CONSTEXPR_CXX14
bool operator!=(min_pointer x
, min_pointer y
) {return x
.ptr_
!= y
.ptr_
;}
379 friend TEST_CONSTEXPR_CXX14
bool operator==(min_pointer x
, std::nullptr_t
) {return x
.ptr_
== nullptr;}
380 friend TEST_CONSTEXPR_CXX14
bool operator!=(min_pointer x
, std::nullptr_t
) {return x
.ptr_
!= nullptr;}
381 friend TEST_CONSTEXPR_CXX14
bool operator==(std::nullptr_t
, min_pointer x
) {return x
.ptr_
== nullptr;}
382 friend TEST_CONSTEXPR_CXX14
bool operator!=(std::nullptr_t
, min_pointer x
) {return x
.ptr_
!= nullptr;}
383 template <class U
, class XID
> friend class min_pointer
;
390 typedef T value_type
;
391 typedef min_pointer
<T
> pointer
;
393 min_allocator() = default;
395 TEST_CONSTEXPR_CXX20
min_allocator(min_allocator
<U
>) {}
397 TEST_CONSTEXPR_CXX20 pointer
allocate(std::ptrdiff_t n
)
399 return pointer(std::allocator
<T
>().allocate(n
));
402 TEST_CONSTEXPR_CXX20
void deallocate(pointer p
, std::ptrdiff_t n
)
404 std::allocator
<T
>().deallocate(p
.ptr_
, n
);
407 TEST_CONSTEXPR_CXX20
friend bool operator==(min_allocator
, min_allocator
) {return true;}
408 TEST_CONSTEXPR_CXX20
friend bool operator!=(min_allocator x
, min_allocator y
) {return !(x
== y
);}
412 class explicit_allocator
415 typedef T value_type
;
417 TEST_CONSTEXPR_CXX20
explicit_allocator() TEST_NOEXCEPT
{}
420 TEST_CONSTEXPR_CXX20
explicit explicit_allocator(explicit_allocator
<U
>) TEST_NOEXCEPT
{}
422 TEST_CONSTEXPR_CXX20 T
* allocate(std::size_t n
)
424 return static_cast<T
*>(std::allocator
<T
>().allocate(n
));
427 TEST_CONSTEXPR_CXX20
void deallocate(T
* p
, std::size_t n
)
429 std::allocator
<T
>().deallocate(p
, n
);
432 TEST_CONSTEXPR_CXX20
friend bool operator==(explicit_allocator
, explicit_allocator
) {return true;}
433 TEST_CONSTEXPR_CXX20
friend bool operator!=(explicit_allocator x
, explicit_allocator y
) {return !(x
== y
);}
437 class unaligned_allocator
{
439 static_assert(TEST_ALIGNOF(T
) == 1, "Type T cannot be created on unaligned address (UB)");
440 typedef T value_type
;
442 TEST_CONSTEXPR_CXX20
unaligned_allocator() TEST_NOEXCEPT
{}
445 TEST_CONSTEXPR_CXX20
explicit unaligned_allocator(unaligned_allocator
<U
>) TEST_NOEXCEPT
{}
447 TEST_CONSTEXPR_CXX20 T
* allocate(std::size_t n
) { return std::allocator
<T
>().allocate(n
+ 1) + 1; }
449 TEST_CONSTEXPR_CXX20
void deallocate(T
* p
, std::size_t n
) { std::allocator
<T
>().deallocate(p
- 1, n
+ 1); }
451 TEST_CONSTEXPR_CXX20
friend bool operator==(unaligned_allocator
, unaligned_allocator
) { return true; }
452 TEST_CONSTEXPR_CXX20
friend bool operator!=(unaligned_allocator x
, unaligned_allocator y
) { return !(x
== y
); }
456 class safe_allocator
{
458 typedef T value_type
;
460 TEST_CONSTEXPR_CXX20
safe_allocator() TEST_NOEXCEPT
{}
463 TEST_CONSTEXPR_CXX20
safe_allocator(safe_allocator
<U
>) TEST_NOEXCEPT
{}
465 TEST_CONSTEXPR_CXX20 T
* allocate(std::size_t n
) {
466 T
* memory
= std::allocator
<T
>().allocate(n
);
467 if (!TEST_IS_CONSTANT_EVALUATED
)
468 std::memset(static_cast<void*>(memory
), 0, sizeof(T
) * n
);
473 TEST_CONSTEXPR_CXX20
void deallocate(T
* p
, std::size_t n
) {
474 if (!TEST_IS_CONSTANT_EVALUATED
)
475 DoNotOptimize(std::memset(static_cast<void*>(p
), 0, sizeof(T
) * n
));
476 std::allocator
<T
>().deallocate(p
, n
);
479 TEST_CONSTEXPR_CXX20
friend bool operator==(safe_allocator
, safe_allocator
) { return true; }
480 TEST_CONSTEXPR_CXX20
friend bool operator!=(safe_allocator x
, safe_allocator y
) { return !(x
== y
); }
483 #endif // MIN_ALLOCATOR_H