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 TEST_ALLOCATOR_H
11 #define TEST_ALLOCATOR_H
12 
13 #include <cstddef>
14 #include <type_traits>
15 #include <cstdlib>
16 #include <new>
17 #include <climits>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 
22 class test_alloc_base
23 {
24 protected:
25     static int time_to_throw;
26 public:
27     static int throw_after;
28     static int count;
29     static int alloc_count;
30 };
31 
32 int test_alloc_base::count = 0;
33 int test_alloc_base::time_to_throw = 0;
34 int test_alloc_base::alloc_count = 0;
35 int test_alloc_base::throw_after = INT_MAX;
36 
37 template <class T>
38 class test_allocator
39     : public test_alloc_base
40 {
41     int data_;
42 
43     template <class U> friend class test_allocator;
44 public:
45 
46     typedef unsigned                                                   size_type;
47     typedef int                                                        difference_type;
48     typedef T                                                          value_type;
49     typedef value_type*                                                pointer;
50     typedef const value_type*                                          const_pointer;
51     typedef typename std::add_lvalue_reference<value_type>::type       reference;
52     typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
53 
54     template <class U> struct rebind {typedef test_allocator<U> other;};
55 
56     test_allocator() throw() : data_(0) {++count;}
57     explicit test_allocator(int i) throw() : data_(i) {++count;}
58     test_allocator(const test_allocator& a) throw()
59         : data_(a.data_) {++count;}
60     template <class U> test_allocator(const test_allocator<U>& a) throw()
61         : data_(a.data_) {++count;}
62     ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
63     pointer address(reference x) const {return &x;}
64     const_pointer address(const_reference x) const {return &x;}
65     pointer allocate(size_type n, const void* = 0)
66         {
67             assert(data_ >= 0);
68             if (time_to_throw >= throw_after) {
69 #ifndef _LIBCPP_NO_EXCEPTIONS
70                 throw std::bad_alloc();
71 #else
72                 std::terminate();
73 #endif
74             }
75             ++time_to_throw;
76             ++alloc_count;
77             return (pointer)::operator new(n * sizeof(T));
78         }
79     void deallocate(pointer p, size_type)
80         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);}
81     size_type max_size() const throw()
82         {return UINT_MAX / sizeof(T);}
83 #if TEST_STD_VER < 11
84     void construct(pointer p, const T& val)
85         {::new(static_cast<void*>(p)) T(val);}
86 #else
87     template <class U> void construct(pointer p, U&& val)
88         {::new(static_cast<void*>(p)) T(std::forward<U>(val));}
89 #endif
90     void destroy(pointer p)
91         {
92             p->~T();
93             ((void)p); // Prevent MSVC's spurious unused warning
94         }
95     friend bool operator==(const test_allocator& x, const test_allocator& y)
96         {return x.data_ == y.data_;}
97     friend bool operator!=(const test_allocator& x, const test_allocator& y)
98         {return !(x == y);}
99 };
100 
101 template <class T>
102 class non_default_test_allocator
103     : public test_alloc_base
104 {
105     int data_;
106 
107     template <class U> friend class non_default_test_allocator;
108 public:
109 
110     typedef unsigned                                                   size_type;
111     typedef int                                                        difference_type;
112     typedef T                                                          value_type;
113     typedef value_type*                                                pointer;
114     typedef const value_type*                                          const_pointer;
115     typedef typename std::add_lvalue_reference<value_type>::type       reference;
116     typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
117 
118     template <class U> struct rebind {typedef non_default_test_allocator<U> other;};
119 
120 //    non_default_test_allocator() throw() : data_(0) {++count;}
121     explicit non_default_test_allocator(int i) throw() : data_(i) {++count;}
122     non_default_test_allocator(const non_default_test_allocator& a) throw()
123         : data_(a.data_) {++count;}
124     template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw()
125         : data_(a.data_) {++count;}
126     ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
127     pointer address(reference x) const {return &x;}
128     const_pointer address(const_reference x) const {return &x;}
129     pointer allocate(size_type n, const void* = 0)
130         {
131             assert(data_ >= 0);
132             if (time_to_throw >= throw_after) {
133 #ifndef _LIBCPP_NO_EXCEPTIONS
134                 throw std::bad_alloc();
135 #else
136                 std::terminate();
137 #endif
138             }
139             ++time_to_throw;
140             ++alloc_count;
141             return (pointer)::operator new (n * sizeof(T));
142         }
143     void deallocate(pointer p, size_type)
144         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); }
145     size_type max_size() const throw()
146         {return UINT_MAX / sizeof(T);}
147 #if TEST_STD_VER < 11
148     void construct(pointer p, const T& val)
149         {::new(static_cast<void*>(p)) T(val);}
150 #else
151     template <class U> void construct(pointer p, U&& val)
152         {::new(static_cast<void*>(p)) T(std::forward<U>(val));}
153 #endif
154     void destroy(pointer p) {p->~T();}
155 
156     friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y)
157         {return x.data_ == y.data_;}
158     friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y)
159         {return !(x == y);}
160 };
161 
162 template <>
163 class test_allocator<void>
164     : public test_alloc_base
165 {
166     int data_;
167 
168     template <class U> friend class test_allocator;
169 public:
170 
171     typedef unsigned                                                   size_type;
172     typedef int                                                        difference_type;
173     typedef void                                                       value_type;
174     typedef value_type*                                                pointer;
175     typedef const value_type*                                          const_pointer;
176 
177     template <class U> struct rebind {typedef test_allocator<U> other;};
178 
179     test_allocator() throw() : data_(0) {}
180     explicit test_allocator(int i) throw() : data_(i) {}
181     test_allocator(const test_allocator& a) throw()
182         : data_(a.data_) {}
183     template <class U> test_allocator(const test_allocator<U>& a) throw()
184         : data_(a.data_) {}
185     ~test_allocator() throw() {data_ = -1;}
186 
187     friend bool operator==(const test_allocator& x, const test_allocator& y)
188         {return x.data_ == y.data_;}
189     friend bool operator!=(const test_allocator& x, const test_allocator& y)
190         {return !(x == y);}
191 };
192 
193 template <class T>
194 class other_allocator
195 {
196     int data_;
197 
198     template <class U> friend class other_allocator;
199 
200 public:
201     typedef T value_type;
202 
203     other_allocator() : data_(-1) {}
204     explicit other_allocator(int i) : data_(i) {}
205     template <class U> other_allocator(const other_allocator<U>& a)
206         : data_(a.data_) {}
207     T* allocate(std::size_t n)
208         {return (T*)::operator new(n * sizeof(T));}
209     void deallocate(T* p, std::size_t)
210         {::operator delete((void*)p);}
211 
212     other_allocator select_on_container_copy_construction() const
213         {return other_allocator(-2);}
214 
215     friend bool operator==(const other_allocator& x, const other_allocator& y)
216         {return x.data_ == y.data_;}
217     friend bool operator!=(const other_allocator& x, const other_allocator& y)
218         {return !(x == y);}
219 
220     typedef std::true_type propagate_on_container_copy_assignment;
221     typedef std::true_type propagate_on_container_move_assignment;
222     typedef std::true_type propagate_on_container_swap;
223 
224 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE
225     std::size_t max_size() const
226         {return UINT_MAX / sizeof(T);}
227 #endif  // _LIBCPP_HAS_NO_ADVANCED_SFINAE
228 
229 };
230 
231 #endif  // TEST_ALLOCATOR_H
232