diff mbox

Make std::vector<bool> meet C++11 allocator requirements.

Message ID 20141031204945.GO3033@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 31, 2014, 8:49 p.m. UTC
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.

Comments

Daniel Krügler Oct. 31, 2014, 8:52 p.m. UTC | #1
2014-10-31 21:49 GMT+01:00 Jonathan Wakely <jwakely@redhat.com>:
> There's no better time to fix evil vector<bool> than Halloween.

Great - so you removed vector<bool>?    ;-)

- Daniel
diff mbox

Patch

commit fa404848f2a2753f2b1a52188b5ec30a6dd9949f
Author: Jonathan Wakely <jwakely@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;
+}