There's no better time to fix evil vector<bool> than Halloween.
All allocator operations must go through allocator_traits and _Bit_type* must be replaced with the allocator's pointer type. Rather than rewriting all the iterators and base classes to use _Bit_pointer everywhere I only changed _M_end_of_storage and added _M_end_addr() to convert it from _Bit_pointer to _Bit_type*, which optimizes to nothing for the usual case where they're the same type. Tested x86_64-linux, committed to trunk.
commit fa404848f2a2753f2b1a52188b5ec30a6dd9949f Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Oct 31 20:02:13 2014 +0000 Make std::vector<bool> meet C++11 allocator requirements. * include/bits/stl_bvector.h (_Bvector_base): Use allocator_traits. (_Bvector_base::_Bvector_impl): Use allocator's pointer type. (_Bvector_base::_M_end_addr()): Convert to raw pointer. (vector<bool>): Use allocator_traits and _M_end_addr. Add allocator extended constructors. * include/bits/vector.tcc (vector<bool>): Use allocator_traits and _M_end_addr. * testsuite/23_containers/vector/bool/allocator/copy.cc: New. * testsuite/23_containers/vector/bool/allocator/minimal.cc: New. * testsuite/23_containers/vector/bool/allocator/noexcept.cc: New. * testsuite/23_containers/vector/bool/allocator/copy_assign.cc: New. * testsuite/23_containers/vector/bool/allocator/move.cc: New. * testsuite/23_containers/vector/bool/allocator/swap.cc: New. * testsuite/23_containers/vector/bool/allocator/ext_ptr.cc: New. * testsuite/23_containers/vector/bool/allocator/move_assign.cc: New. diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 996eb1a..c93b96c 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -410,30 +410,41 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Alloc> struct _Bvector_base { - typedef typename _Alloc::template rebind<_Bit_type>::other - _Bit_alloc_type; - + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Bit_type>::other _Bit_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type> + _Bit_alloc_traits; + typedef typename _Bit_alloc_traits::pointer _Bit_pointer; + struct _Bvector_impl : public _Bit_alloc_type { _Bit_iterator _M_start; _Bit_iterator _M_finish; - _Bit_type* _M_end_of_storage; + _Bit_pointer _M_end_of_storage; _Bvector_impl() - : _Bit_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage(0) + : _Bit_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage() { } _Bvector_impl(const _Bit_alloc_type& __a) - : _Bit_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage(0) + : _Bit_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage() { } #if __cplusplus >= 201103L _Bvector_impl(_Bit_alloc_type&& __a) : _Bit_alloc_type(std::move(__a)), _M_start(), _M_finish(), - _M_end_of_storage(0) + _M_end_of_storage() { } #endif + + _Bit_type* + _M_end_addr() const _GLIBCXX_NOEXCEPT + { + if (_M_end_of_storage) + return std::__addressof(_M_end_of_storage[-1]) + 1; + return 0; + } }; public: @@ -466,7 +477,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; __x._M_impl._M_start = _Bit_iterator(); __x._M_impl._M_finish = _Bit_iterator(); - __x._M_impl._M_end_of_storage = 0; + __x._M_impl._M_end_of_storage = nullptr; } #endif @@ -476,16 +487,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER protected: _Bvector_impl _M_impl; - _Bit_type* + _Bit_pointer _M_allocate(size_t __n) - { return _M_impl.allocate(_S_nword(__n)); } + { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); } void _M_deallocate() { if (_M_impl._M_start._M_p) - _M_impl.deallocate(_M_impl._M_start._M_p, - _M_impl._M_end_of_storage - _M_impl._M_start._M_p); + { + const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p; + _Bit_alloc_traits::deallocate(_M_impl, + _M_impl._M_end_of_storage - __n, + __n); + } } static size_t @@ -526,6 +541,8 @@ template<typename _Alloc> class vector<bool, _Alloc> : protected _Bvector_base<_Alloc> { typedef _Bvector_base<_Alloc> _Base; + typedef typename _Base::_Bit_pointer _Bit_pointer; + typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits; #if __cplusplus >= 201103L template<typename> friend struct hash; @@ -573,7 +590,7 @@ template<typename _Alloc> : _Base(__a) { _M_initialize(__n); - std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_of_storage, + std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_addr(), __value ? ~0 : 0); } #else @@ -583,13 +600,13 @@ template<typename _Alloc> : _Base(__a) { _M_initialize(__n); - std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_of_storage, + std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_addr(), __value ? ~0 : 0); } #endif vector(const vector& __x) - : _Base(__x._M_get_Bit_allocator()) + : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator())) { _M_initialize(__x.size()); _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); @@ -599,6 +616,34 @@ template<typename _Alloc> vector(vector&& __x) noexcept : _Base(std::move(__x)) { } + vector(vector&& __x, const allocator_type& __a) + noexcept(_Bit_alloc_traits::_S_always_equal()) + : _Base(__a) + { + if (__x.get_allocator() == __a) + { + this->_M_impl._M_start = __x._M_impl._M_start; + this->_M_impl._M_finish = __x._M_impl._M_finish; + this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; + __x._M_impl._M_start = _Bit_iterator(); + __x._M_impl._M_finish = _Bit_iterator(); + __x._M_impl._M_end_of_storage = nullptr; + } + else + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), begin()); + __x.clear(); + } + } + + vector(const vector& __x, const allocator_type& __a) + : _Base(__a) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + vector(initializer_list<bool> __l, const allocator_type& __a = allocator_type()) : _Base(__a) @@ -633,6 +678,21 @@ template<typename _Alloc> { if (&__x == this) return *this; +#if __cplusplus >= 201103L + if (_Bit_alloc_traits::_S_propagate_on_copy_assign()) + { + if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + _M_initialize(__x.size()); + } + else + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } +#endif if (__x.size() > capacity()) { this->_M_deallocate(); @@ -645,12 +705,32 @@ template<typename _Alloc> #if __cplusplus >= 201103L vector& - operator=(vector&& __x) + operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move()) { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); + if (_Bit_alloc_traits::_S_propagate_on_move_assign() + || this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + this->_M_impl._M_start = __x._M_impl._M_start; + this->_M_impl._M_finish = __x._M_impl._M_finish; + this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; + __x._M_impl._M_start = _Bit_iterator(); + __x._M_impl._M_finish = _Bit_iterator(); + __x._M_impl._M_end_of_storage = nullptr; + std::__alloc_on_move(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + else + { + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + __x.clear(); + } return *this; } @@ -752,14 +832,15 @@ template<typename _Alloc> const size_type __isize = __gnu_cxx::__numeric_traits<difference_type>::__max - int(_S_word_bit) + 1; - const size_type __asize = _M_get_Bit_allocator().max_size(); + const size_type __asize + = _Bit_alloc_traits::max_size(_M_get_Bit_allocator()); return (__asize <= __isize / int(_S_word_bit) ? __asize * int(_S_word_bit) : __isize); } size_type capacity() const _GLIBCXX_NOEXCEPT - { return size_type(const_iterator(this->_M_impl._M_end_of_storage, 0) + { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0) - begin()); } bool @@ -836,7 +917,7 @@ template<typename _Alloc> void push_back(bool __x) { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) *this->_M_impl._M_finish++ = __x; else _M_insert_aux(end(), __x); @@ -844,16 +925,16 @@ template<typename _Alloc> void swap(vector& __x) +#if __cplusplus >= 201103L + noexcept(_Bit_alloc_traits::_S_nothrow_swap()) +#endif { std::swap(this->_M_impl._M_start, __x._M_impl._M_start); std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); std::swap(this->_M_impl._M_end_of_storage, __x._M_impl._M_end_of_storage); - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 431. Swapping containers with unequal allocators. - std::__alloc_swap<typename _Base::_Bit_alloc_type>:: - _S_do_it(_M_get_Bit_allocator(), __x._M_get_Bit_allocator()); + _Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); } // [23.2.5]/1, third-to-last entry in synopsis listing @@ -873,7 +954,7 @@ template<typename _Alloc> #endif { const difference_type __n = __position - begin(); - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr() && __position == end()) *this->_M_impl._M_finish++ = __x; else @@ -962,8 +1043,8 @@ template<typename _Alloc> void flip() _GLIBCXX_NOEXCEPT { - for (_Bit_type * __p = this->_M_impl._M_start._M_p; - __p != this->_M_impl._M_end_of_storage; ++__p) + _Bit_type * const __end = this->_M_impl._M_end_addr(); + for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p) *__p = ~*__p; } @@ -997,9 +1078,9 @@ template<typename _Alloc> void _M_initialize(size_type __n) { - _Bit_type* __q = this->_M_allocate(__n); + _Bit_pointer __q = this->_M_allocate(__n); this->_M_impl._M_end_of_storage = __q + _S_nword(__n); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = iterator(std::__addressof(*__q), 0); this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); } @@ -1021,7 +1102,7 @@ template<typename _Alloc> { _M_initialize(static_cast<size_type>(__n)); std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); } template<typename _InputIterator> @@ -1069,14 +1150,14 @@ template<typename _Alloc> if (__n > size()) { std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); insert(end(), __n - size(), __x); } else { _M_erase_at_end(begin() + __n); std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); } } diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 19784c0..229fa6d 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -699,11 +699,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<bool, _Alloc>:: _M_reallocate(size_type __n) { - _Bit_type* __q = this->_M_allocate(__n); - this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__n); + iterator __start(std::__addressof(*__q), 0); + this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), __start); this->_M_deallocate(); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; this->_M_impl._M_end_of_storage = __q + _S_nword(__n); } @@ -725,15 +725,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(__n, "vector<bool>::_M_fill_insert"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); std::fill(__i, __i + difference_type(__n), __x); this->_M_impl._M_finish = std::copy(__position, end(), __i + difference_type(__n)); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } @@ -759,14 +759,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(__n, "vector<bool>::_M_insert_range"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); __i = std::copy(__first, __last, __i); this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } } @@ -776,7 +776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<bool, _Alloc>:: _M_insert_aux(iterator __position, bool __x) { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) { std::copy_backward(__position, this->_M_impl._M_finish, this->_M_impl._M_finish + 1); @@ -787,14 +787,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(size_type(1), "vector<bool>::_M_insert_aux"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); *__i++ = __x; this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc new file mode 100644 index 0000000..7bd0b98 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc @@ -0,0 +1,70 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(0 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1, alloc_type(2)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc new file mode 100644 index 0000000..eac6b43 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = v1; + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = v1; + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc new file mode 100644 index 0000000..94087be --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <memory> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::CustomPointerAlloc; + +template class std::vector<T, CustomPointerAlloc<T>>; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef CustomPointerAlloc<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v; + v.push_back(T()); + VERIFY( ++v.begin() == v.end() ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc new file mode 100644 index 0000000..56d88b0 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc @@ -0,0 +1,38 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include <vector> +#include <memory> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::SimpleAllocator; + +template class std::vector<T, SimpleAllocator<T>>; + +void test01() +{ + typedef SimpleAllocator<T> alloc_type; + typedef std::allocator_traits<alloc_type> traits_type; + typedef std::vector<T, alloc_type> test_type; + test_type v(alloc_type{}); + v.push_back(T()); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc new file mode 100644 index 0000000..c6afcd3 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + auto it = v1.begin(); + test_type v2(std::move(v1)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + test_type v2(std::move(v1), alloc_type(2)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc new file mode 100644 index 0000000..da95498 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc @@ -0,0 +1,80 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + auto it = v1.begin(); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); + VERIFY(0 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + auto it = v1.begin(); + test_type v2(alloc_type(1)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc new file mode 100644 index 0000000..e86e6b2 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_allocator.h> + +using T = bool; + +namespace __gnu_test +{ + template<typename U> + inline void + swap(propagating_allocator<U, true>& l, propagating_allocator<U, true>& r) + noexcept(false) + { } +} + +using __gnu_test::propagating_allocator; + +void test01() +{ + typedef std::allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1; + test_type v2; + // this is a GNU extension for std::allocator + static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); + static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" ); +} + +void test02() +{ + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + test_type v2(alloc_type(2)); + static_assert( !noexcept( v1 = std::move(v2) ), "Move assign can throw" ); + static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" ); +} + +void test03() +{ + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + test_type v2(alloc_type(2)); + static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); + static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" ); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc new file mode 100644 index 0000000..cedb24f --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc @@ -0,0 +1,80 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +using T = bool; + +using __gnu_test::propagating_allocator; + +// It is undefined behaviour to swap() containers wth unequal allocators +// if the allocator doesn't propagate, so ensure the allocators compare +// equal, while still being able to test propagation via get_personality(). +bool +operator==(const propagating_allocator<T, false>&, + const propagating_allocator<T, false>&) +{ + return true; +} + +bool +operator!=(const propagating_allocator<T, false>&, + const propagating_allocator<T, false>&) +{ + return false; +} + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, false> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + std::swap(v1, v2); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); + // swap back so assertions in uneq_allocator::deallocate don't fail + std::swap(v1, v2); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator<T, true> alloc_type; + typedef std::vector<T, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + std::swap(v1, v2); + VERIFY(2 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +}