1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef MIN_ALLOCATOR_H
10 #define MIN_ALLOCATOR_H
11 
12 #include <cstddef>
13 #include <cstdlib>
14 #include <cstddef>
15 #include <cassert>
16 #include <climits>
17 #include <memory>
18 
19 #include "test_macros.h"
20 
21 template <class T>
22 class bare_allocator
23 {
24 public:
25     typedef T value_type;
26 
27     bare_allocator() TEST_NOEXCEPT {}
28 
29     template <class U>
30     bare_allocator(bare_allocator<U>) TEST_NOEXCEPT {}
31 
32     T* allocate(std::size_t n)
33     {
34         return static_cast<T*>(::operator new(n*sizeof(T)));
35     }
36 
37     void deallocate(T* p, std::size_t)
38     {
39         return ::operator delete(static_cast<void*>(p));
40     }
41 
42     friend bool operator==(bare_allocator, bare_allocator) {return true;}
43     friend bool operator!=(bare_allocator x, bare_allocator y) {return !(x == y);}
44 };
45 
46 
47 template <class T>
48 class no_default_allocator
49 {
50 #if TEST_STD_VER >= 11
51     no_default_allocator() = delete;
52 #else
53     no_default_allocator();
54 #endif
55     struct construct_tag {};
56     explicit no_default_allocator(construct_tag) {}
57 
58 public:
59     static no_default_allocator create() {
60       construct_tag tag;
61       return no_default_allocator(tag);
62     }
63 
64 public:
65     typedef T value_type;
66 
67     template <class U>
68     no_default_allocator(no_default_allocator<U>) TEST_NOEXCEPT {}
69 
70     T* allocate(std::size_t n)
71     {
72         return static_cast<T*>(::operator new(n*sizeof(T)));
73     }
74 
75     void deallocate(T* p, std::size_t)
76     {
77         return ::operator delete(static_cast<void*>(p));
78     }
79 
80     friend bool operator==(no_default_allocator, no_default_allocator) {return true;}
81     friend bool operator!=(no_default_allocator x, no_default_allocator y) {return !(x == y);}
82 };
83 
84 struct malloc_allocator_base {
85     static size_t outstanding_bytes;
86     static size_t alloc_count;
87     static size_t dealloc_count;
88     static bool disable_default_constructor;
89 
90     static size_t outstanding_alloc() {
91       assert(alloc_count >= dealloc_count);
92       return (alloc_count - dealloc_count);
93     }
94 
95     static void reset() {
96         assert(outstanding_alloc() == 0);
97         disable_default_constructor = false;
98         outstanding_bytes = 0;
99         alloc_count = 0;
100         dealloc_count = 0;
101     }
102 };
103 
104 size_t malloc_allocator_base::outstanding_bytes = 0;
105 size_t malloc_allocator_base::alloc_count = 0;
106 size_t malloc_allocator_base::dealloc_count = 0;
107 bool malloc_allocator_base::disable_default_constructor = false;
108 
109 
110 template <class T>
111 class malloc_allocator : public malloc_allocator_base
112 {
113 public:
114     typedef T value_type;
115 
116     malloc_allocator() TEST_NOEXCEPT { assert(!disable_default_constructor); }
117 
118     template <class U>
119     malloc_allocator(malloc_allocator<U>) TEST_NOEXCEPT {}
120 
121     T* allocate(std::size_t n)
122     {
123         const size_t nbytes = n*sizeof(T);
124         ++alloc_count;
125         outstanding_bytes += nbytes;
126         return static_cast<T*>(std::malloc(nbytes));
127     }
128 
129     void deallocate(T* p, std::size_t n)
130     {
131         const size_t nbytes = n*sizeof(T);
132         ++dealloc_count;
133         outstanding_bytes -= nbytes;
134         std::free(static_cast<void*>(p));
135     }
136 
137     friend bool operator==(malloc_allocator, malloc_allocator) {return true;}
138     friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);}
139 };
140 
141 template <class T>
142 struct cpp03_allocator : bare_allocator<T>
143 {
144     typedef T value_type;
145     typedef value_type* pointer;
146 
147     static bool construct_called;
148 
149     // Returned value is not used but it's not prohibited.
150     pointer construct(pointer p, const value_type& val)
151     {
152         ::new(p) value_type(val);
153         construct_called = true;
154         return p;
155     }
156 
157     std::size_t max_size() const
158     {
159         return UINT_MAX / sizeof(T);
160     }
161 };
162 template <class T> bool cpp03_allocator<T>::construct_called = false;
163 
164 template <class T>
165 struct cpp03_overload_allocator : bare_allocator<T>
166 {
167     typedef T value_type;
168     typedef value_type* pointer;
169 
170     static bool construct_called;
171 
172     void construct(pointer p, const value_type& val)
173     {
174         construct(p, val, std::is_class<T>());
175     }
176     void construct(pointer p, const value_type& val, std::true_type)
177     {
178         ::new(p) value_type(val);
179         construct_called = true;
180     }
181     void construct(pointer p, const value_type& val, std::false_type)
182     {
183         ::new(p) value_type(val);
184         construct_called = true;
185     }
186 
187     std::size_t max_size() const
188     {
189         return UINT_MAX / sizeof(T);
190     }
191 };
192 template <class T> bool cpp03_overload_allocator<T>::construct_called = false;
193 
194 template <class T, class = std::integral_constant<size_t, 0> > class min_pointer;
195 template <class T, class ID> class min_pointer<const T, ID>;
196 template <class ID> class min_pointer<void, ID>;
197 template <class ID> class min_pointer<const void, ID>;
198 template <class T> class min_allocator;
199 
200 template <class ID>
201 class min_pointer<const void, ID>
202 {
203     const void* ptr_;
204 public:
205     min_pointer() TEST_NOEXCEPT = default;
206     min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {}
207     template <class T>
208     min_pointer(min_pointer<T, ID> p) TEST_NOEXCEPT : ptr_(p.ptr_) {}
209 
210     explicit operator bool() const {return ptr_ != nullptr;}
211 
212     friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;}
213     friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);}
214     template <class U, class XID> friend class min_pointer;
215 };
216 
217 template <class ID>
218 class min_pointer<void, ID>
219 {
220     void* ptr_;
221 public:
222     min_pointer() TEST_NOEXCEPT = default;
223     min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {}
224     template <class T,
225               class = typename std::enable_if
226                        <
227                             !std::is_const<T>::value
228                        >::type
229              >
230     min_pointer(min_pointer<T, ID> p) TEST_NOEXCEPT : ptr_(p.ptr_) {}
231 
232     explicit operator bool() const {return ptr_ != nullptr;}
233 
234     friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;}
235     friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);}
236     template <class U, class XID> friend class min_pointer;
237 };
238 
239 template <class T, class ID>
240 class min_pointer
241 {
242     T* ptr_;
243 
244     explicit min_pointer(T* p) TEST_NOEXCEPT : ptr_(p) {}
245 public:
246     min_pointer() TEST_NOEXCEPT = default;
247     min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {}
248     explicit min_pointer(min_pointer<void, ID> p) TEST_NOEXCEPT : ptr_(static_cast<T*>(p.ptr_)) {}
249 
250     explicit operator bool() const {return ptr_ != nullptr;}
251 
252     typedef std::ptrdiff_t difference_type;
253     typedef T& reference;
254     typedef T* pointer;
255     typedef T value_type;
256     typedef std::random_access_iterator_tag iterator_category;
257 
258     reference operator*() const {return *ptr_;}
259     pointer operator->() const {return ptr_;}
260 
261     min_pointer& operator++() {++ptr_; return *this;}
262     min_pointer operator++(int) {min_pointer tmp(*this); ++ptr_; return tmp;}
263 
264     min_pointer& operator--() {--ptr_; return *this;}
265     min_pointer operator--(int) {min_pointer tmp(*this); --ptr_; return tmp;}
266 
267     min_pointer& operator+=(difference_type n) {ptr_ += n; return *this;}
268     min_pointer& operator-=(difference_type n) {ptr_ -= n; return *this;}
269 
270     min_pointer operator+(difference_type n) const
271     {
272         min_pointer tmp(*this);
273         tmp += n;
274         return tmp;
275     }
276 
277     friend min_pointer operator+(difference_type n, min_pointer x)
278     {
279         return x + n;
280     }
281 
282     min_pointer operator-(difference_type n) const
283     {
284         min_pointer tmp(*this);
285         tmp -= n;
286         return tmp;
287     }
288 
289     friend difference_type operator-(min_pointer x, min_pointer y)
290     {
291         return x.ptr_ - y.ptr_;
292     }
293 
294     reference operator[](difference_type n) const {return ptr_[n];}
295 
296     friend bool operator< (min_pointer x, min_pointer y) {return x.ptr_ < y.ptr_;}
297     friend bool operator> (min_pointer x, min_pointer y) {return y < x;}
298     friend bool operator<=(min_pointer x, min_pointer y) {return !(y < x);}
299     friend bool operator>=(min_pointer x, min_pointer y) {return !(x < y);}
300 
301     static min_pointer pointer_to(T& t) {return min_pointer(std::addressof(t));}
302 
303     friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;}
304     friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);}
305     template <class U, class XID> friend class min_pointer;
306     template <class U> friend class min_allocator;
307 };
308 
309 template <class T, class ID>
310 class min_pointer<const T, ID>
311 {
312     const T* ptr_;
313 
314     explicit min_pointer(const T* p) : ptr_(p) {}
315 public:
316     min_pointer() TEST_NOEXCEPT = default;
317     min_pointer(std::nullptr_t) : ptr_(nullptr) {}
318     min_pointer(min_pointer<T, ID> p) : ptr_(p.ptr_) {}
319     explicit min_pointer(min_pointer<const void, ID> p) : ptr_(static_cast<const T*>(p.ptr_)) {}
320 
321     explicit operator bool() const {return ptr_ != nullptr;}
322 
323     typedef std::ptrdiff_t difference_type;
324     typedef const T& reference;
325     typedef const T* pointer;
326     typedef const T value_type;
327     typedef std::random_access_iterator_tag iterator_category;
328 
329     reference operator*() const {return *ptr_;}
330     pointer operator->() const {return ptr_;}
331 
332     min_pointer& operator++() {++ptr_; return *this;}
333     min_pointer operator++(int) {min_pointer tmp(*this); ++ptr_; return tmp;}
334 
335     min_pointer& operator--() {--ptr_; return *this;}
336     min_pointer operator--(int) {min_pointer tmp(*this); --ptr_; return tmp;}
337 
338     min_pointer& operator+=(difference_type n) {ptr_ += n; return *this;}
339     min_pointer& operator-=(difference_type n) {ptr_ -= n; return *this;}
340 
341     min_pointer operator+(difference_type n) const
342     {
343         min_pointer tmp(*this);
344         tmp += n;
345         return tmp;
346     }
347 
348     friend min_pointer operator+(difference_type n, min_pointer x)
349     {
350         return x + n;
351     }
352 
353     min_pointer operator-(difference_type n) const
354     {
355         min_pointer tmp(*this);
356         tmp -= n;
357         return tmp;
358     }
359 
360     friend difference_type operator-(min_pointer x, min_pointer y)
361     {
362         return x.ptr_ - y.ptr_;
363     }
364 
365     reference operator[](difference_type n) const {return ptr_[n];}
366 
367     friend bool operator< (min_pointer x, min_pointer y) {return x.ptr_ < y.ptr_;}
368     friend bool operator> (min_pointer x, min_pointer y) {return y < x;}
369     friend bool operator<=(min_pointer x, min_pointer y) {return !(y < x);}
370     friend bool operator>=(min_pointer x, min_pointer y) {return !(x < y);}
371 
372     static min_pointer pointer_to(const T& t) {return min_pointer(std::addressof(t));}
373 
374     friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;}
375     friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);}
376     template <class U, class XID> friend class min_pointer;
377 };
378 
379 template <class T, class ID>
380 inline
381 bool
382 operator==(min_pointer<T, ID> x, std::nullptr_t)
383 {
384     return !static_cast<bool>(x);
385 }
386 
387 template <class T, class ID>
388 inline
389 bool
390 operator==(std::nullptr_t, min_pointer<T, ID> x)
391 {
392     return !static_cast<bool>(x);
393 }
394 
395 template <class T, class ID>
396 inline
397 bool
398 operator!=(min_pointer<T, ID> x, std::nullptr_t)
399 {
400     return static_cast<bool>(x);
401 }
402 
403 template <class T, class ID>
404 inline
405 bool
406 operator!=(std::nullptr_t, min_pointer<T, ID> x)
407 {
408     return static_cast<bool>(x);
409 }
410 
411 template <class T>
412 class min_allocator
413 {
414 public:
415     typedef T value_type;
416     typedef min_pointer<T> pointer;
417 
418     min_allocator() = default;
419     template <class U>
420     min_allocator(min_allocator<U>) {}
421 
422     pointer allocate(std::ptrdiff_t n)
423     {
424         return pointer(static_cast<T*>(::operator new(n*sizeof(T))));
425     }
426 
427     void deallocate(pointer p, std::ptrdiff_t)
428     {
429         return ::operator delete(p.ptr_);
430     }
431 
432     friend bool operator==(min_allocator, min_allocator) {return true;}
433     friend bool operator!=(min_allocator x, min_allocator y) {return !(x == y);}
434 };
435 
436 template <class T>
437 class explicit_allocator
438 {
439 public:
440     typedef T value_type;
441 
442     explicit_allocator() TEST_NOEXCEPT {}
443 
444     template <class U>
445     explicit explicit_allocator(explicit_allocator<U>) TEST_NOEXCEPT {}
446 
447     T* allocate(std::size_t n)
448     {
449         return static_cast<T*>(::operator new(n*sizeof(T)));
450     }
451 
452     void deallocate(T* p, std::size_t)
453     {
454         return ::operator delete(static_cast<void*>(p));
455     }
456 
457     friend bool operator==(explicit_allocator, explicit_allocator) {return true;}
458     friend bool operator!=(explicit_allocator x, explicit_allocator y) {return !(x == y);}
459 };
460 
461 #endif  // MIN_ALLOCATOR_H
462