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