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 throw()56 test_allocator() throw() : data_(0) {++count;} test_allocator(int i)57 explicit test_allocator(int i) throw() : data_(i) {++count;} throw()58 test_allocator(const test_allocator& a) throw() 59 : data_(a.data_) {++count;} test_allocator(const test_allocator<U> & a)60 template <class U> test_allocator(const test_allocator<U>& a) throw() 61 : data_(a.data_) {++count;} throw()62 ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} address(reference x)63 pointer address(reference x) const {return &x;} address(const_reference 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 } deallocate(pointer p,size_type n)79 void deallocate(pointer p, size_type n) 80 {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);} max_size()81 size_type max_size() const throw() 82 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)83 void construct(pointer p, const T& val) 84 {::new(p) T(val);} 85 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)86 void construct(pointer p, T&& val) 87 {::new(p) T(std::move(val));} 88 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)89 void destroy(pointer p) {p->~T();} 90 91 friend bool operator==(const test_allocator& x, const test_allocator& y) 92 {return x.data_ == y.data_;} 93 friend bool operator!=(const test_allocator& x, const test_allocator& y) 94 {return !(x == y);} 95 }; 96 97 template <class T> 98 class non_default_test_allocator 99 : public test_alloc_base 100 { 101 int data_; 102 103 template <class U> friend class non_default_test_allocator; 104 public: 105 106 typedef unsigned size_type; 107 typedef int difference_type; 108 typedef T value_type; 109 typedef value_type* pointer; 110 typedef const value_type* const_pointer; 111 typedef typename std::add_lvalue_reference<value_type>::type reference; 112 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 113 114 template <class U> struct rebind {typedef non_default_test_allocator<U> other;}; 115 116 // non_default_test_allocator() throw() : data_(0) {++count;} non_default_test_allocator(int i)117 explicit non_default_test_allocator(int i) throw() : data_(i) {++count;} throw()118 non_default_test_allocator(const non_default_test_allocator& a) throw() 119 : data_(a.data_) {++count;} non_default_test_allocator(const non_default_test_allocator<U> & a)120 template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw() 121 : data_(a.data_) {++count;} throw()122 ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} address(reference x)123 pointer address(reference x) const {return &x;} address(const_reference x)124 const_pointer address(const_reference x) const {return &x;} 125 pointer allocate(size_type n, const void* = 0) 126 { 127 assert(data_ >= 0); 128 if (time_to_throw >= throw_after) { 129 #ifndef _LIBCPP_NO_EXCEPTIONS 130 throw std::bad_alloc(); 131 #else 132 std::terminate(); 133 #endif 134 } 135 ++time_to_throw; 136 ++alloc_count; 137 return (pointer)::operator new (n * sizeof(T)); 138 } deallocate(pointer p,size_type n)139 void deallocate(pointer p, size_type n) 140 {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); } max_size()141 size_type max_size() const throw() 142 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)143 void construct(pointer p, const T& val) 144 {::new(p) T(val);} 145 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)146 void construct(pointer p, T&& val) 147 {::new(p) T(std::move(val));} 148 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)149 void destroy(pointer p) {p->~T();} 150 151 friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) 152 {return x.data_ == y.data_;} 153 friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) 154 {return !(x == y);} 155 }; 156 157 template <> 158 class test_allocator<void> 159 : public test_alloc_base 160 { 161 int data_; 162 163 template <class U> friend class test_allocator; 164 public: 165 166 typedef unsigned size_type; 167 typedef int difference_type; 168 typedef void value_type; 169 typedef value_type* pointer; 170 typedef const value_type* const_pointer; 171 172 template <class U> struct rebind {typedef test_allocator<U> other;}; 173 throw()174 test_allocator() throw() : data_(-1) {} test_allocator(int i)175 explicit test_allocator(int i) throw() : data_(i) {} throw()176 test_allocator(const test_allocator& a) throw() 177 : data_(a.data_) {} test_allocator(const test_allocator<U> & a)178 template <class U> test_allocator(const test_allocator<U>& a) throw() 179 : data_(a.data_) {} throw()180 ~test_allocator() throw() {data_ = 0;} 181 182 friend bool operator==(const test_allocator& x, const test_allocator& y) 183 {return x.data_ == y.data_;} 184 friend bool operator!=(const test_allocator& x, const test_allocator& y) 185 {return !(x == y);} 186 }; 187 188 template <class T> 189 class other_allocator 190 { 191 int data_; 192 193 template <class U> friend class other_allocator; 194 195 public: 196 typedef T value_type; 197 other_allocator()198 other_allocator() : data_(-1) {} other_allocator(int i)199 explicit other_allocator(int i) : data_(i) {} other_allocator(const other_allocator<U> & a)200 template <class U> other_allocator(const other_allocator<U>& a) 201 : data_(a.data_) {} allocate(std::size_t n)202 T* allocate(std::size_t n) 203 {return (T*)::operator new(n * sizeof(T));} deallocate(T * p,std::size_t n)204 void deallocate(T* p, std::size_t n) 205 {::operator delete((void*)p);} 206 select_on_container_copy_construction()207 other_allocator select_on_container_copy_construction() const 208 {return other_allocator(-2);} 209 210 friend bool operator==(const other_allocator& x, const other_allocator& y) 211 {return x.data_ == y.data_;} 212 friend bool operator!=(const other_allocator& x, const other_allocator& y) 213 {return !(x == y);} 214 215 typedef std::true_type propagate_on_container_copy_assignment; 216 typedef std::true_type propagate_on_container_move_assignment; 217 typedef std::true_type propagate_on_container_swap; 218 219 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE max_size()220 std::size_t max_size() const 221 {return UINT_MAX / sizeof(T);} 222 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 223 224 }; 225 226 #endif // TEST_ALLOCATOR_H 227