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