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