Implement N4258 noexcept for std::basic_string.
authorJonathan Wakely <jwakely@redhat.com>
Fri, 11 Sep 2015 11:02:14 +0000 (12:02 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 11 Sep 2015 11:02:14 +0000 (12:02 +0100)
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.

From-SVN: r227681

21 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/bits/basic_string.tcc
libstdc++-v3/include/debug/string
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/minimal.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/noexcept.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/swap.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_allocator.h

index c4505fd05f0bed387b01f0144d61fac8099585de..3bd33ba504c387070d74217caf3681bb060ab977 100644 (file)
@@ -1,5 +1,35 @@
 2015-09-11  Jonathan Wakely  <jwakely@redhat.com>
 
+       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.
+
        PR libstdc++/65092
        * include/bits/stl_queue.h (queue, priority_queue): Add
        allocator-extended constructors.
index 1ea5fffab6cac468cd7ca375b8e843858ec0f0f6..65ffc01a45be557ec3575ea5dff506afbe81d4cf 100644 (file)
     </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2059" target="_top">2059</a>:
        <span class="emphasis"><em>C++0x ambiguity problem with map::erase</em></span>
     </span></dt><dd><p>Add additional overloads.
+    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2063" target="_top">2063</a>:
+       <span class="emphasis"><em>Contradictory requirements for string move assignment</em></span>
+    </span></dt><dd><p>Respect propagation trait for move assignment.
+    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2064" target="_top">2064</a>:
+       <span class="emphasis"><em>More noexcept issues in basic_string</em></span>
+    </span></dt><dd><p>Add noexcept to the comparison operators.
     </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2067" target="_top">2067</a>:
        <span class="emphasis"><em>packaged_task should have deleted copy c'tor with const parameter</em></span>
     </span></dt><dd><p>Fix signatures.
index 1cc183e2dc3af12b54b23a206d151d88952b659c..2aa9ba7a896d78f5734841e5915b5922f40b9366 100644 (file)
@@ -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>
index 3226617fec8063ebc4891816a398f73f6b1da6af..e6e7bb525ba7bfa2aa77b5d5ce578ce56707940e 100644 (file)
@@ -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); }
 
 
index b9da93bf17483fa06093707e2aa75668ea9eaab6..56af86471e5f7868274bbda08b04c1f3b5ecc371 100644 (file)
@@ -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))
index 72ae88e54956e9204d429955fd6067d6108f0f14..d1f4a565aa271879db605aeddf72f3cf7ca63afd 100644 (file)
 
 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 (file)
index 0000000..d02e9b9
--- /dev/null
@@ -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 (file)
index 0000000..94e0796
--- /dev/null
@@ -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 (file)
index 0000000..4bfd4ca
--- /dev/null
@@ -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 (file)
index 0000000..113df8f
--- /dev/null
@@ -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 (file)
index 0000000..153ffd2
--- /dev/null
@@ -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 (file)
index 0000000..8733ea1
--- /dev/null
@@ -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 (file)
index 0000000..21003eb
--- /dev/null
@@ -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 (file)
index 0000000..c95e2ef
--- /dev/null
@@ -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 (file)
index 0000000..f69dff7
--- /dev/null
@@ -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 (file)
index 0000000..bfba87c
--- /dev/null
@@ -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 (file)
index 0000000..88927a6
--- /dev/null
@@ -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 (file)
index 0000000..45283a7
--- /dev/null
@@ -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 (file)
index 0000000..5fb3c1b
--- /dev/null
@@ -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 (file)
index 0000000..5490f9e
--- /dev/null
@@ -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
index ebe7de0981e9691ec4b42ceb827f147428eea342..2fa6a96303737396595af02821d626d0934cbede 100644 (file)
@@ -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>