This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] libstdc++/58265 Implement N4258 noexcept for std::basic_string.


This updates the non-COW basic_string to meet the noexcept
requirements in the current draft, which required finishing the
allocator propagation support.

Tested powerpc64le-linux, normal and debug. Committed to trunk.


commit 909cf7116d75d42920e4b4f89ee8ddf04c843a9c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Sep 11 10:54:31 2015 +0100

    Implement N4258 noexcept for std::basic_string.
    
    	PR libstdc++/58265
    	* doc/xml/manual/intro.xml: Document LWG 2063 and 2064 resolutions.
    	* doc/html/manual/bugs.html: Regenerate.
    	* include/bits/basic_string.h (basic_string): Implement N4258. Add
    	correct exception-specifications and propagate allocators correctly.
    	* include/bits/basic_string.tcc (basic_string::swap): Propagate
    	allocators correctly.
    	* include/debug/string (__gnu_debug::basic_string): Add correct
    	exceptions-specifications and allcoator-extended constructors.
    	* testsuite/21_strings/basic_string/allocator/char/copy.cc: New.
    	* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
    	New.
    	* testsuite/21_strings/basic_string/allocator/char/minimal.cc: New.
    	* testsuite/21_strings/basic_string/allocator/char/move.cc: New.
    	* testsuite/21_strings/basic_string/allocator/char/move_assign.cc:
    	New.
    	* testsuite/21_strings/basic_string/allocator/char/noexcept.cc: New.
    	* testsuite/21_strings/basic_string/allocator/char/swap.cc: New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc: New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
    	New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc: New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/move.cc: New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc:
    	New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc: New.
    	* testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc: New.
    	* testsuite/util/testsuite_allocator.h (tracker_allocator): Define
    	defaulted assignment operators.

diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml
index 1cc183e..2aa9ba7 100644
--- a/libstdc++-v3/doc/xml/manual/intro.xml
+++ b/libstdc++-v3/doc/xml/manual/intro.xml
@@ -850,6 +850,18 @@ requirements of the license of GCC.
     <listitem><para>Add additional overloads.
     </para></listitem></varlistentry>
 
+    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink"; xlink:href="../ext/lwg-defects.html#2063">2063</link>:
+	<emphasis>Contradictory requirements for string move assignment</emphasis>
+    </term>
+    <listitem><para>Respect propagation trait for move assignment.
+    </para></listitem></varlistentry>
+
+    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink"; xlink:href="../ext/lwg-defects.html#2064">2064</link>:
+	<emphasis>More noexcept issues in basic_string</emphasis>
+    </term>
+    <listitem><para>Add noexcept to the comparison operators.
+    </para></listitem></varlistentry>
+
     <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink"; xlink:href="../ext/lwg-defects.html#2067">2067</link>:
 	<emphasis>packaged_task should have deleted copy c'tor with const parameter</emphasis>
     </term>
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 3226617..e6e7bb5 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -379,9 +379,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @brief  Default constructor creates an empty string.
        */
       basic_string()
-#if __cplusplus >= 201103L
-      noexcept(is_nothrow_default_constructible<_Alloc>::value)
-#endif
+      _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)
       : _M_dataplus(_M_local_data())
       { _M_set_length(0); }
 
@@ -389,7 +387,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @brief  Construct an empty string using allocator @a a.
        */
       explicit
-      basic_string(const _Alloc& __a)
+      basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT
       : _M_dataplus(_M_local_data(), __a)
       { _M_set_length(0); }
 
@@ -398,7 +396,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @param  __str  Source string.
        */
       basic_string(const basic_string& __str)
-      : _M_dataplus(_M_local_data(), __str._M_get_allocator()) // TODO A traits
+      : _M_dataplus(_M_local_data(),
+		    _Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
       { _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
 
       /**
@@ -511,10 +510,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       { _M_construct(__str.begin(), __str.end()); }
 
       basic_string(basic_string&& __str, const _Alloc& __a)
+      noexcept(_Alloc_traits::_S_always_equal())
       : _M_dataplus(_M_local_data(), __a)
       {
-	if (__str.get_allocator() == __a)
-	  *this = std::move(__str);
+	if (__str._M_is_local())
+	  {
+	    traits_type::copy(_M_local_buf, __str._M_local_buf,
+			      _S_local_capacity + 1);
+	    _M_length(__str.length());
+	    __str._M_set_length(0);
+	  }
+	else if (_Alloc_traits::_S_always_equal()
+	    || __str.get_allocator() == __a)
+	  {
+	    _M_data(__str._M_data());
+	    _M_length(__str.length());
+	    _M_capacity(__str._M_allocated_capacity);
+	    __str._M_data(__str._M_local_buf);
+	    __str._M_set_length(0);
+	  }
 	else
 	  _M_construct(__str.begin(), __str.end());
       }
@@ -550,7 +564,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        */
       basic_string&
       operator=(const basic_string& __str)
-      { return this->assign(__str); }
+      {
+#if __cplusplus >= 201103L
+	if (_Alloc_traits::_S_propagate_on_copy_assign())
+	  {
+	    if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
+		&& _M_get_allocator() != __str._M_get_allocator())
+	      {
+		// replacement allocator cannot free existing storage
+		_M_destroy(_M_allocated_capacity);
+		_M_data(_M_local_data());
+		_M_set_length(0);
+	      }
+	    std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
+	  }
+#endif
+	return this->assign(__str);
+      }
 
       /**
        *  @brief  Copy contents of @a s into this string.
@@ -587,8 +617,51 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       // 2063. Contradictory requirements for string move assignment
       basic_string&
       operator=(basic_string&& __str)
+      noexcept(_Alloc_traits::_S_nothrow_move())
       {
-	this->swap(__str);
+	if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
+	    && !_Alloc_traits::_S_always_equal()
+	    && _M_get_allocator() != __str._M_get_allocator())
+	  {
+	    // Destroy existing storage before replacing allocator.
+	    _M_destroy(_M_allocated_capacity);
+	    _M_data(_M_local_data());
+	    _M_set_length(0);
+	  }
+	// Replace allocator if POCMA is true.
+	std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
+
+	if (!__str._M_is_local()
+	    && (_Alloc_traits::_S_propagate_on_move_assign()
+	      || _Alloc_traits::_S_always_equal()))
+	  {
+	    pointer __data = nullptr;
+	    size_type __capacity;
+	    if (!_M_is_local())
+	      {
+		if (_Alloc_traits::_S_always_equal())
+		  {
+		    __data = _M_data();
+		    __capacity = _M_allocated_capacity;
+		  }
+		else
+		  _M_destroy(_M_allocated_capacity);
+	      }
+
+	    _M_data(__str._M_data());
+	    _M_length(__str.length());
+	    _M_capacity(__str._M_allocated_capacity);
+	    if (__data)
+	      {
+		__str._M_data(__data);
+		__str._M_capacity(__capacity);
+	      }
+	    else
+	      __str._M_data(__str._M_local_buf);
+	  }
+	else
+	    assign(__str);
+	__str.clear();
 	return *this;
       }
 
@@ -1119,6 +1192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        */
       basic_string&
       assign(basic_string&& __str)
+      noexcept(_Alloc_traits::_S_nothrow_move())
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 2063. Contradictory requirements for string move assignment
@@ -4961,13 +5035,14 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.compare(__rhs) == 0; }
 
   template<typename _CharT>
     inline
     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
     operator==(const basic_string<_CharT>& __lhs,
-	       const basic_string<_CharT>& __rhs)
+	       const basic_string<_CharT>& __rhs) _GLIBCXX_NOEXCEPT
     { return (__lhs.size() == __rhs.size()
 	      && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
 						    __lhs.size())); }
@@ -5007,6 +5082,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return !(__lhs == __rhs); }
 
   /**
@@ -5044,6 +5120,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.compare(__rhs) < 0; }
 
   /**
@@ -5081,6 +5158,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.compare(__rhs) > 0; }
 
   /**
@@ -5118,6 +5196,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.compare(__rhs) <= 0; }
 
   /**
@@ -5155,6 +5234,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline bool
     operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	       const basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.compare(__rhs) >= 0; }
 
   /**
@@ -5192,6 +5272,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
     inline void
     swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
 	 basic_string<_CharT, _Traits, _Alloc>& __rhs)
+    _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
     { __lhs.swap(__rhs); }
 
 
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index b9da93b..56af864 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -61,11 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (this == &__s)
 	return;
 
-      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-      // 431. Swapping containers with unequal allocators.
-      // TODO propagation traits
-      std::__alloc_swap<allocator_type>::_S_do_it(_M_get_allocator(),
-						  __s._M_get_allocator());
+      _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
 
       if (_M_is_local())
 	if (__s._M_is_local())
@@ -404,7 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       if (__new_size <= this->capacity())
 	{
-	  _CharT* __p = this->_M_data() + __pos1;
+	  pointer __p = this->_M_data() + __pos1;
 
 	  const size_type __how_much = __old_size - __pos1 - __n1;
 	  if (__how_much && __n1 != __n2)
@@ -433,7 +429,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       if (__new_size <= this->capacity())
 	{
-	  _CharT* __p = this->_M_data() + __pos;
+	  pointer __p = this->_M_data() + __pos;
 
 	  const size_type __how_much = __old_size - __pos - __len1;
 	  if (_M_disjunct(__s))
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index 72ae88e..d1f4a56 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -36,19 +36,19 @@
 
 namespace __gnu_debug
 {
-  /// Class std::basic_string with safety/checking/debug instrumentation.
-  template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
-	   typename _Allocator = std::allocator<_CharT> >
-    class basic_string
-    : public __gnu_debug::_Safe_container<
-	basic_string<_CharT, _Traits, _Allocator>,
-	_Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>,
-      public std::basic_string<_CharT, _Traits, _Allocator>
-    {
-      typedef std::basic_string<_CharT, _Traits, _Allocator>	_Base;
-      typedef __gnu_debug::_Safe_container<
-	basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>
-	_Safe;
+/// Class std::basic_string with safety/checking/debug instrumentation.
+template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
+	 typename _Allocator = std::allocator<_CharT> >
+  class basic_string
+  : public __gnu_debug::_Safe_container<
+      basic_string<_CharT, _Traits, _Allocator>,
+      _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>,
+    public std::basic_string<_CharT, _Traits, _Allocator>
+  {
+    typedef std::basic_string<_CharT, _Traits, _Allocator>	_Base;
+    typedef __gnu_debug::_Safe_container<
+      basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>
+      _Safe;
 
   public:
     // types:
@@ -72,9 +72,13 @@ namespace __gnu_debug
 
     using _Base::npos;
 
+    basic_string()
+    _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_default_constructible<_Base>::value)
+    : _Base() { }
+
     // 21.3.1 construct/copy/destroy:
-    explicit basic_string(const _Allocator& __a = _Allocator())
-    // _GLIBCXX_NOEXCEPT
+    explicit
+    basic_string(const _Allocator& __a) _GLIBCXX_NOEXCEPT
     : _Base(__a) { }
 
 #if __cplusplus < 201103L
@@ -91,7 +95,19 @@ namespace __gnu_debug
     : _Base(__l, __a)
     { }
 
+#if _GLIBCXX_USE_CXX11_ABI
+    basic_string(const basic_string& __s, const _Allocator& __a)
+    : _Base(__s, __a) { }
+
+    basic_string(basic_string&& __s, const _Allocator& __a)
+    : _Base(std::move(__s), __a) { }
+#endif
+
     ~basic_string() = default;
+
+    // Provides conversion from a normal-mode string to a debug-mode string
+    basic_string(_Base&& __base) noexcept
+    : _Base(std::move(__base)) { }
 #endif // C++11
 
     // Provides conversion from a normal-mode string to a debug-mode string
@@ -278,7 +294,7 @@ namespace __gnu_debug
     reference
     operator[](size_type __pos) // _GLIBCXX_NOEXCEPT
     {
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
+#if __cplusplus < 201103L && defined(_GLIBCXX_DEBUG_PEDANTIC)
       __glibcxx_check_subscript(__pos);
 #else
       // as an extension v3 allows s[s.size()] when s is non-const.
@@ -413,6 +429,7 @@ namespace __gnu_debug
 #if __cplusplus >= 201103L
     basic_string&
     assign(basic_string&& __x)
+    noexcept(noexcept(std::declval<_Base&>().assign(std::move(__x))))
     {
       _Base::assign(std::move(__x));
       this->_M_invalidate_all();
@@ -729,6 +746,7 @@ namespace __gnu_debug
 
     void
     swap(basic_string& __x)
+    _GLIBCXX_NOEXCEPT_IF(std::__is_nothrow_swappable<_Base>::value)
     {
       _Safe::_M_swap(__x);
       _Base::swap(__x);
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy.cc
new file mode 100644
index 0000000..d02e9b9
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy.cc
@@ -0,0 +1,97 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(0 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(0 == v3.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v3.get_allocator().get_personality());
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1, alloc_type(2));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1, alloc_type(3));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
new file mode 100644
index 0000000..94e0796
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
@@ -0,0 +1,114 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  v1.assign(1, c);
+  test_type v3(alloc_type(3));
+  v3.assign(100, c);
+  v3 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v4(alloc_type(4));
+  v4.assign(1, c);
+  v4 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(4 == v4.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  v5 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(5 == v5.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  v1.assign(1, c);
+  test_type v3(alloc_type(3));
+  v3.assign(100, c);
+  v3 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v3.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v4(alloc_type(4));
+  v4.assign(1, c);
+  v4 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v4.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  v5 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v5.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/minimal.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/minimal.cc
new file mode 100644
index 0000000..4bfd4ca
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/minimal.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 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 <string>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::SimpleAllocator;
+
+template class std::basic_string<C,traits, SimpleAllocator<C>>;
+
+void test01()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+  typedef SimpleAllocator<C> alloc_type;
+  typedef std::allocator_traits<alloc_type> traits_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v(alloc_type{});
+  v.assign(1, c);
+  v.assign(100, c);
+#endif
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move.cc
new file mode 100644
index 0000000..113df8f
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(std::move(v1));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  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;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
new file mode 100644
index 0000000..153ffd2
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
@@ -0,0 +1,160 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(4));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(3 == v3.get_allocator().get_personality());
+  VERIFY(4 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(6));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(5 == v5.get_allocator().get_personality());
+  VERIFY(6 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(8));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(7 == v7.get_allocator().get_personality());
+  VERIFY(8 == v8.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(0 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(4));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(0 == v3.get_allocator().get_personality());
+  VERIFY(3 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(6));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(0 == v5.get_allocator().get_personality());
+  VERIFY(5 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(8));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(0 == v7.get_allocator().get_personality());
+  VERIFY(7 == v8.get_allocator().get_personality());
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(1));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(3));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(3 == v3.get_allocator().get_personality());
+  VERIFY(3 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(5));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(5 == v5.get_allocator().get_personality());
+  VERIFY(5 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(7));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(7 == v7.get_allocator().get_personality());
+  VERIFY(7 == v8.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/noexcept.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/noexcept.cc
new file mode 100644
index 0000000..8733ea1
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/noexcept.cc
@@ -0,0 +1,61 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  typedef std::allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, 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<C, false> alloc_type;
+  typedef std::basic_string<C, traits, 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<C, true> alloc_type;
+  typedef std::basic_string<C, traits, 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 cannot throw" );
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/swap.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/swap.cc
new file mode 100644
index 0000000..21003eb
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/swap.cc
@@ -0,0 +1,89 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+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<C, false>&,
+           const propagating_allocator<C, false>&)
+{
+  return true;
+}
+
+bool
+operator!=(const propagating_allocator<C, false>&,
+           const propagating_allocator<C, false>&)
+{
+  return false;
+}
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.push_back(C());
+  test_type v2(alloc_type(2));
+  v2.push_back(C());
+  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<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.push_back(C());
+  test_type v2(alloc_type(2));
+  v2.push_back(C());
+  std::swap(v1, v2);
+  VERIFY(2 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc
new file mode 100644
index 0000000..c95e2ef
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc
@@ -0,0 +1,97 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(0 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(0 == v3.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v3.get_allocator().get_personality());
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(v1, alloc_type(2));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v3(v1, alloc_type(3));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
new file mode 100644
index 0000000..f69dff7
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
@@ -0,0 +1,114 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  v1.assign(1, c);
+  test_type v3(alloc_type(3));
+  v3.assign(100, c);
+  v3 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v4(alloc_type(4));
+  v4.assign(1, c);
+  v4 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(4 == v4.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  v5 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(5 == v5.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  v1.assign(1, c);
+  test_type v3(alloc_type(3));
+  v3.assign(100, c);
+  v3 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v3.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v4(alloc_type(4));
+  v4.assign(1, c);
+  v4 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v4.get_allocator().get_personality());
+
+  v1.assign(100, c);
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  v5 = v1;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v5.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc
new file mode 100644
index 0000000..bfba87c
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 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 <string>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::SimpleAllocator;
+
+template class std::basic_string<C,traits, SimpleAllocator<C>>;
+
+void test01()
+{
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+  typedef SimpleAllocator<C> alloc_type;
+  typedef std::allocator_traits<alloc_type> traits_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v(alloc_type{});
+  v.assign(1, c);
+  v.assign(100, c);
+#endif
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move.cc
new file mode 100644
index 0000000..88927a6
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(std::move(v1));
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef uneq_allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  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;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
new file mode 100644
index 0000000..45283a7
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
@@ -0,0 +1,160 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(2 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(4));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(3 == v3.get_allocator().get_personality());
+  VERIFY(4 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(6));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(5 == v5.get_allocator().get_personality());
+  VERIFY(6 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(8));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(7 == v7.get_allocator().get_personality());
+  VERIFY(8 == v8.get_allocator().get_personality());
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(2));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(0 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(4));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(0 == v3.get_allocator().get_personality());
+  VERIFY(3 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(6));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(0 == v5.get_allocator().get_personality());
+  VERIFY(5 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(8));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(0 == v7.get_allocator().get_personality());
+  VERIFY(7 == v8.get_allocator().get_personality());
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(alloc_type(1));
+  v1.assign(1, c);
+  test_type v2(alloc_type(1));
+  v2.assign(1, c);
+  v2 = std::move(v1);
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+
+  test_type v3(alloc_type(3));
+  v3.assign(1, c);
+  test_type v4(alloc_type(3));
+  v4.assign(100, c);
+  v4 = std::move(v3);
+  VERIFY(3 == v3.get_allocator().get_personality());
+  VERIFY(3 == v4.get_allocator().get_personality());
+
+  test_type v5(alloc_type(5));
+  v5.assign(100, c);
+  test_type v6(alloc_type(5));
+  v6.assign(1, c);
+  v6 = std::move(v5);
+  VERIFY(5 == v5.get_allocator().get_personality());
+  VERIFY(5 == v6.get_allocator().get_personality());
+
+  test_type v7(alloc_type(7));
+  v7.assign(100, c);
+  test_type v8(alloc_type(7));
+  v8.assign(100, c);
+  v8 = std::move(v7);
+  VERIFY(7 == v7.get_allocator().get_personality());
+  VERIFY(7 == v8.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc
new file mode 100644
index 0000000..5fb3c1b
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc
@@ -0,0 +1,61 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+  typedef std::allocator<C> alloc_type;
+  typedef std::basic_string<C, traits, 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<C, false> alloc_type;
+  typedef std::basic_string<C, traits, 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<C, true> alloc_type;
+  typedef std::basic_string<C, traits, 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 cannot throw" );
+}
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc
new file mode 100644
index 0000000..5490f9e
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc
@@ -0,0 +1,89 @@
+// Copyright (C) 2015 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 <string>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+ 
+#if _GLIBCXX_USE_CXX11_ABI && defined(_GLIBCXX_USE_WCHAR_T)
+using C = char;
+const C c = 'a';
+using traits = std::char_traits<C>;
+
+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<C, false>&,
+           const propagating_allocator<C, false>&)
+{
+  return true;
+}
+
+bool
+operator!=(const propagating_allocator<C, false>&,
+           const propagating_allocator<C, false>&)
+{
+  return false;
+}
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef propagating_allocator<C, false> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.push_back(C());
+  test_type v2(alloc_type(2));
+  v2.push_back(C());
+  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<C, true> alloc_type;
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+  test_type v1(alloc_type(1));
+  v1.push_back(C());
+  test_type v2(alloc_type(2));
+  v2.push_back(C());
+  std::swap(v1, v2);
+  VERIFY(2 == v1.get_allocator().get_personality());
+  VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
+#else
+int main()
+{
+  // COW strings don't support C++11 allocators
+}
+#endif
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index ebe7de0..2fa6a96 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -119,6 +119,8 @@ namespace __gnu_test
       tracker_allocator() = default;
       tracker_allocator(const tracker_allocator&) = default;
       tracker_allocator(tracker_allocator&&) = default;
+      tracker_allocator& operator=(const tracker_allocator&) = default;
+      tracker_allocator& operator=(tracker_allocator&&) = default;
 
       // Perfect forwarding constructor.
       template<typename... _Args>

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]