libstdc++: Add remaining C++20 additions to <sstream> [P0408R7]
authorJonathan Wakely <jwakely@redhat.com>
Tue, 10 Nov 2020 15:57:04 +0000 (15:57 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 10 Nov 2020 19:22:47 +0000 (19:22 +0000)
This adds the new overloads of basic_stringbuf::str, and the
corresponding overloads to basic_istringstream, basic_ostringstream and
basic_stringstream.

libstdc++-v3/ChangeLog:

* config/abi/pre/gnu.ver (GLIBCXX_3.4.21): Tighten patterns.
(GLIBCXX_3.4.29): Export new symbols.
* include/bits/alloc_traits.h (__allocator_like): New concept.
* include/std/sstream (basic_stringbuf::swap): Add exception
specification.
(basic_stringbuf::str() const): Add ref-qualifier. Use new
_M_high_mark function.
(basic_stringbuf::str(const SAlloc&) const): Define new function.
(basic_stringbuf::str() &&): Likewise.
(basic_stringbuf::str(const basic_string<C,T,SAlloc>&)):
Likewise.
(basic_stringbuf::str(basic_string<C,T,Alloc>&&)): Likewise.
(basic_stringbuf::view() const): Use _M_high_mark.
(basic_istringstream::str, basic_ostringstream::str)
(basic_stringstream::str): Define new overloads.
* src/c++20/sstream-inst.cc (basic_stringbuf::str)
(basic_istringstream::str, basic_ostringstream::str)
(basic_stringstream::str): Explicit instantiation definitions
for new overloads.
* testsuite/27_io/basic_istringstream/view/char/1.cc: Add more
checks.
* testsuite/27_io/basic_istringstream/view/wchar_t/1.cc:
Likewise.
* testsuite/27_io/basic_ostringstream/view/char/1.cc:
Likewise.
* testsuite/27_io/basic_ostringstream/view/wchar_t/1.cc:
Likewise.
* testsuite/27_io/basic_stringstream/view/char/1.cc:
Likewise.
* testsuite/27_io/basic_stringstream/view/wchar_t/1.cc:
Likewise.
* testsuite/27_io/basic_istringstream/str/char/2.cc: New test.
* testsuite/27_io/basic_istringstream/str/wchar_t/2.cc: New test.
* testsuite/27_io/basic_ostringstream/str/char/3.cc: New test.
* testsuite/27_io/basic_ostringstream/str/wchar_t/3.cc: New test.
* testsuite/27_io/basic_stringbuf/str/char/4.cc: New test.
* testsuite/27_io/basic_stringbuf/str/wchar_t/4.cc: New test.
* testsuite/27_io/basic_stringstream/str/char/5.cc: New test.
* testsuite/27_io/basic_stringstream/str/wchar_t/5.cc.cc: New test.

18 files changed:
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/include/bits/alloc_traits.h
libstdc++-v3/include/std/sstream
libstdc++-v3/src/c++20/sstream-inst.cc
libstdc++-v3/testsuite/27_io/basic_istringstream/str/char/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_istringstream/str/wchar_t/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_istringstream/view/char/1.cc
libstdc++-v3/testsuite/27_io/basic_istringstream/view/wchar_t/1.cc
libstdc++-v3/testsuite/27_io/basic_ostringstream/str/char/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_ostringstream/str/wchar_t/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_ostringstream/view/char/1.cc
libstdc++-v3/testsuite/27_io/basic_ostringstream/view/wchar_t/1.cc
libstdc++-v3/testsuite/27_io/basic_stringbuf/str/char/4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_stringbuf/str/wchar_t/4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_stringstream/str/char/5.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_stringstream/str/wchar_t/5.cc.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_stringstream/view/char/1.cc
libstdc++-v3/testsuite/27_io/basic_stringstream/view/wchar_t/1.cc

index 2d0f87aa7cc7a2357b8048891e3668a4741dbd75..46769db15303aa9f62930d95342a7700b6d88e93 100644 (file)
@@ -1776,14 +1776,16 @@ GLIBCXX_3.4.21 {
     _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EED[012]Ev;
     _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EOS4_ONS4_14__xfer_bufptrsE;
     _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]14__xfer_bufptrs[CD][12]*;
-    _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[a1346789]*;
+    _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[a146789]*;
+    _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE3strERK*;
 #   _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]*;
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EOS4_;
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EOSa*;
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]ERKNS_12basic_stringI[cw]S2_S3_EESt13_Ios_Openmode;
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]ESt13_Ios_Openmode;
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EED[012]Ev;
-    _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE[a34]*;
+    _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE[a4]*;
+    _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strERK*;
 #   _ZNSt7__cxx1119basic_istringstreamI[cw]St11char_traitsI[cw]*;
 #   _ZNSt7__cxx1119basic_ostringstreamI[cw]St11char_traitsI[cw]*;
     _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EOS4_;
@@ -1791,7 +1793,8 @@ GLIBCXX_3.4.21 {
     _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]ERKNS_12basic_stringI[cw]S2_S3_EESt13_Ios_Openmode;
     _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]ESt13_Ios_Openmode;
     _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EED[012]Ev;
-    _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE[a34]*;
+    _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE[a4]*;
+    _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strERK*;
     _ZNKSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
     _ZNKSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
     _ZNKSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE5rdbufEv;
@@ -2354,6 +2357,10 @@ GLIBCXX_3.4.29 {
 
     # basic_stringbuf::view()
     _ZNKSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE4viewEv;
+    # basic_stringbuf::str
+    _ZNOSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNKRSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNSt7__cxx1115basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEONS_12basic_stringI[cw]S2_S3_EE;
 
     # basic_[io]stringstream::basic_[io]stringstream(basic_string&&, ios_base::openmode)
     _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EONS_12basic_stringI[cw]S2_S3_EESt13_Ios_Openmode;
@@ -2363,6 +2370,10 @@ GLIBCXX_3.4.29 {
 
     # basic_[io]stringstream::view()
     _ZNKSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE4viewEv;
+    # basic_[io]stringstream::str
+    _ZNOSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNKRSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNSt7__cxx1119basic_[io]stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEONS_12basic_stringI[cw]S2_S3_EE;
 
     # basic_stringstream::basic_stringstream(basic_string&&, ios_base::openmode)
     _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]EONS_12basic_stringI[cw]S2_S3_EESt13_Ios_Openmode;
@@ -2372,6 +2383,10 @@ GLIBCXX_3.4.29 {
 
     # basic_stringstream::view()
     _ZNKSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE4viewEv;
+    # basic_stringstream::str
+    _ZNOSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNKRSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEv;
+    _ZNSt7__cxx1118basic_stringstreamI[cw]St11char_traitsI[cw]ESaI[cw]EE3strEONS_12basic_stringI[cw]S2_S3_EE;
 
     # std::once_flag::_M_activate()
     _ZNSt9once_flag11_M_activateEv;
index 86d8ed221ff8d312aada579600b6543997f1fcc3..467311fc91778c70868c51b687153c67376c3367 100644 (file)
@@ -708,6 +708,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Alloc>
     using _RequireNotAllocator
       = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
+
+#if __cpp_concepts >= 201907L
+  template<typename _Alloc>
+    concept __allocator_like = requires (_Alloc& __a) {
+      typename _Alloc::value_type;
+      __a.deallocate(__a.allocate(1u), 1u);
+    };
+#endif
 #endif // C++11
 
   /**
index 9c50e4e83281d137f7358eec0885155e1f4450a4..8cddda297017ece19d44e5d6400db1f34b3d6ade 100644 (file)
 
 #include <istream>
 #include <ostream>
+#include <bits/alloc_traits.h> // allocator_traits, __allocator_like
+
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+# define _GLIBCXX_LVAL_REF_QUAL &
+#else
+# define _GLIBCXX_LVAL_REF_QUAL
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -65,6 +72,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
     {
       struct __xfer_bufptrs;
+
+#if __cplusplus >= 201103L
+      using allocator_traits = std::allocator_traits<_Alloc>;
+      using _Noexcept_swap
+       = __or_<typename allocator_traits::propagate_on_container_swap,
+               typename allocator_traits::is_always_equal>;
+#endif
+
     public:
       // Types:
       typedef _CharT                                   char_type;
@@ -153,7 +168,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       }
 
       void
-      swap(basic_stringbuf& __rhs)
+      swap(basic_stringbuf& __rhs) noexcept(_Noexcept_swap::value)
       {
        __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)};
        __xfer_bufptrs __r_st{__rhs, this};
@@ -161,9 +176,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        __streambuf_type::swap(__base);
        __rhs.pubimbue(this->pubimbue(__rhs.getloc()));
        std::swap(_M_mode, __rhs._M_mode);
-       std::swap(_M_string, __rhs._M_string);
+       std::swap(_M_string, __rhs._M_string); // XXX not exception safe
       }
-#endif
+#endif // C++11
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
       explicit
@@ -213,7 +228,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       { return _M_string.get_allocator(); }
 #endif
 
-      // Get and set:
+      // Getters and setters:
+
       /**
        *  @brief  Copying out the string buffer.
        *  @return  A copy of one of the underlying sequences.
@@ -223,23 +239,51 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  is equal to the output sequence.</em> [27.7.1.2]/1
       */
       __string_type
-      str() const
+      str() const _GLIBCXX_LVAL_REF_QUAL
       {
        __string_type __ret(_M_string.get_allocator());
-       if (char_type* __pptr = this->pptr())
-         {
-           char_type* __egptr = this->egptr();
-           // The current egptr() may not be the actual string end.
-           if (!__egptr || __pptr > __egptr)
-             __ret.assign(this->pbase(), __pptr);
-           else
-             __ret.assign(this->pbase(), __egptr);
-         }
+       if (char_type* __hi = _M_high_mark())
+         __ret.assign(this->pbase(), __hi);
        else
          __ret = _M_string;
        return __ret;
       }
 
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       basic_string<_CharT, _Traits, _SAlloc>
+       str(const _SAlloc& __sa) const
+       {
+         auto __sv = view();
+         return { __sv.data(), __sv.size(), __sa };
+       }
+#endif
+
+      __string_type
+      str() &&
+      {
+       if (char_type* __hi = _M_high_mark())
+         {
+           // Set length to end of character sequence and add null terminator.
+           _M_string._M_set_length(_M_high_mark() - this->pbase());
+         }
+       auto __str = std::move(_M_string);
+       _M_string.clear();
+       _M_sync(_M_string.data(), 0, 0);
+       return __str;
+      }
+
+      basic_string_view<char_type, traits_type>
+      view() const noexcept
+      {
+       if (char_type* __hi = _M_high_mark())
+         return { this->pbase(), __hi };
+       else
+         return _M_string;
+      }
+#endif
+
       /**
        *  @brief  Setting a new buffer.
        *  @param  __s  The string to use as a new sequence.
@@ -257,21 +301,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-      basic_string_view<char_type, traits_type>
-      view() const noexcept
-      {
-       using __sv_type = basic_string_view<char_type, traits_type>;
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       requires (!is_same_v<_SAlloc, _Alloc>)
+       void
+       str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
+       {
+         _M_string.assign(__s.data(), __s.size());
+         _M_stringbuf_init(_M_mode);
+       }
+#endif
 
-       if (this->pptr())
-         {
-           // The current egptr() may not be the actual string end.
-           if (this->pptr() > this->egptr())
-             return __sv_type(this->pbase(), this->pptr());
-           else
-             return __sv_type(this->pbase(), this->egptr());
-         }
-       else
-         return static_cast<__sv_type>(_M_string);
+      void
+      str(__string_type&& __s)
+      {
+       _M_string = std::move(__s);
+       _M_stringbuf_init(_M_mode);
       }
 #endif
 
@@ -376,6 +421,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off);
 
     private:
+      // Return a pointer to the end of the underlying character sequence.
+      // This might not be the same character as _M_string.end() because
+      // basic_stringbuf::overflow might have written to unused capacity
+      // in _M_string without updating its length.
+      char_type*
+      _M_high_mark() const _GLIBCXX_NOEXCEPT
+      {
+       if (char_type* __pptr = this->pptr())
+         {
+           char_type* __egptr = this->egptr();
+           if (!__egptr || __pptr > __egptr)
+             return __pptr;  // Underlying sequence is [pbase, pptr).
+           else
+             return __egptr; // Underlying sequence is [pbase, egptr).
+         }
+       return 0; // Underlying character sequence is just _M_string.
+      }
+
 #if __cplusplus >= 201103L
 #if _GLIBCXX_USE_CXX11_ABI
       // This type captures the state of the gptr / pptr pointers as offsets
@@ -629,9 +692,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @return  @c rdbuf()->str()
       */
       __string_type
-      str() const
+      str() const _GLIBCXX_LVAL_REF_QUAL
       { return _M_stringbuf.str(); }
 
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       basic_string<_CharT, _Traits, _SAlloc>
+       str(const _SAlloc& __sa) const
+       { return _M_stringbuf.str(__sa); }
+#endif
+
+      __string_type
+      str() &&
+      { return std::move(_M_stringbuf).str(); }
+
+      basic_string_view<char_type, traits_type>
+      view() const noexcept
+      { return _M_stringbuf.view(); }
+#endif
+
       /**
        *  @brief  Setting a new buffer.
        *  @param  __s  The string to use as a new sequence.
@@ -643,9 +723,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       { _M_stringbuf.str(__s); }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-      basic_string_view<char_type, traits_type>
-      view() const noexcept
-      { return _M_stringbuf.view(); }
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       requires (!is_same_v<_SAlloc, _Alloc>)
+       void
+       str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
+       { _M_stringbuf.str(__s); }
+#endif
+
+      void
+      str(__string_type&& __s)
+      { _M_stringbuf.str(std::move(__s)); }
 #endif
     };
 
@@ -825,9 +913,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @return  @c rdbuf()->str()
       */
       __string_type
-      str() const
+      str() const _GLIBCXX_LVAL_REF_QUAL
       { return _M_stringbuf.str(); }
 
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       basic_string<_CharT, _Traits, _SAlloc>
+       str(const _SAlloc& __sa) const
+       { return _M_stringbuf.str(__sa); }
+#endif
+
+      __string_type
+      str() &&
+      { return std::move(_M_stringbuf).str(); }
+
+      basic_string_view<char_type, traits_type>
+      view() const noexcept
+      { return _M_stringbuf.view(); }
+#endif
+
       /**
        *  @brief  Setting a new buffer.
        *  @param  __s  The string to use as a new sequence.
@@ -839,9 +944,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       { _M_stringbuf.str(__s); }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-      basic_string_view<char_type, traits_type>
-      view() const noexcept
-      { return _M_stringbuf.view(); }
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       requires (!is_same_v<_SAlloc, _Alloc>)
+       void
+       str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
+       { _M_stringbuf.str(__s); }
+#endif
+
+      void
+      str(__string_type&& __s)
+      { _M_stringbuf.str(std::move(__s)); }
 #endif
     };
 
@@ -1019,9 +1132,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  @return  @c rdbuf()->str()
       */
       __string_type
-      str() const
+      str() const _GLIBCXX_LVAL_REF_QUAL
       { return _M_stringbuf.str(); }
 
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       basic_string<_CharT, _Traits, _SAlloc>
+       str(const _SAlloc& __sa) const
+       { return _M_stringbuf.str(__sa); }
+#endif
+
+      __string_type
+      str() &&
+      { return std::move(_M_stringbuf).str(); }
+
+      basic_string_view<char_type, traits_type>
+      view() const noexcept
+      { return _M_stringbuf.view(); }
+#endif
+
       /**
        *  @brief  Setting a new buffer.
        *  @param  __s  The string to use as a new sequence.
@@ -1033,9 +1163,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       { _M_stringbuf.str(__s); }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-      basic_string_view<char_type, traits_type>
-      view() const noexcept
-      { return _M_stringbuf.view(); }
+#if __cpp_concepts
+      template<__allocator_like _SAlloc>
+       requires (!is_same_v<_SAlloc, _Alloc>)
+       void
+       str(const basic_string<_CharT, _Traits, _SAlloc>& __s)
+       { _M_stringbuf.str(__s); }
+#endif
+
+      void
+      str(__string_type&& __s)
+      { _M_stringbuf.str(std::move(__s)); }
 #endif
     };
 
@@ -1045,6 +1183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     inline void
     swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x,
         basic_stringbuf<_CharT, _Traits, _Allocator>& __y)
+    noexcept(noexcept(__x.swap(__y)))
     { __x.swap(__y); }
 
   /// Swap specialization for istringstreams.
@@ -1067,12 +1206,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
     swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x,
         basic_stringstream<_CharT, _Traits, _Allocator>& __y)
     { __x.swap(__y); }
-#endif
+#endif // C++11
 
 _GLIBCXX_END_NAMESPACE_CXX11
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
+#undef _GLIBCXX_LVAL_REF_QUAL
+
 #include <bits/sstream.tcc>
 
 #endif /* _GLIBCXX_SSTREAM */
index 7d275de5cc240dbb221f1362130643d100a5a212..9e157d1b1bfbd6148fc9f9259e2e5457265e0552 100644 (file)
@@ -46,29 +46,53 @@ template basic_stringbuf<char>::basic_stringbuf(basic_stringbuf&&,
                                                __xfer_bufptrs&&);
 template basic_stringbuf<char>::allocator_type
 basic_stringbuf<char>::get_allocator() const noexcept;
+template string
+basic_stringbuf<char>::str() const &;
+template string
+basic_stringbuf<char>::str() &&;
 template string_view
 basic_stringbuf<char>::view() const noexcept;
+template void
+basic_stringbuf<char>::str(string&&);
 
 template basic_istringstream<char>::basic_istringstream(ios_base::openmode,
                                                        const allocator_type&);
 template basic_istringstream<char>::basic_istringstream(__string_type&&,
                                                        ios_base::openmode);
+template string
+basic_istringstream<char>::str() const &;
+template string
+basic_istringstream<char>::str() &&;
 template string_view
 basic_istringstream<char>::view() const noexcept;
+template void
+basic_istringstream<char>::str(string&&);
 
 template basic_ostringstream<char>::basic_ostringstream(ios_base::openmode,
                                                        const allocator_type&);
 template basic_ostringstream<char>::basic_ostringstream(__string_type&&,
                                                        ios_base::openmode);
+template string
+basic_ostringstream<char>::str() const &;
+template string
+basic_ostringstream<char>::str() &&;
 template string_view
 basic_ostringstream<char>::view() const noexcept;
+template void
+basic_ostringstream<char>::str(string&&);
 
 template basic_stringstream<char>::basic_stringstream(ios_base::openmode,
                                                      const allocator_type&);
 template basic_stringstream<char>::basic_stringstream(__string_type&&,
                                                      ios_base::openmode);
+template string
+basic_stringstream<char>::str() const &;
+template string
+basic_stringstream<char>::str() &&;
 template string_view
 basic_stringstream<char>::view() const noexcept;
+template void
+basic_stringstream<char>::str(string&&);
 
 #ifdef _GLIBCXX_USE_WCHAR_T
 template basic_stringbuf<wchar_t>::basic_stringbuf(const allocator_type&);
@@ -84,29 +108,53 @@ template basic_stringbuf<wchar_t>::basic_stringbuf(basic_stringbuf&&,
 template basic_stringbuf<wchar_t>::allocator_type
 basic_stringbuf<wchar_t>::get_allocator() const noexcept;
 
+template wstring
+basic_stringbuf<wchar_t>::str() const &;
+template wstring
+basic_stringbuf<wchar_t>::str() &&;
 template wstring_view
 basic_stringbuf<wchar_t>::view() const noexcept;
+template void
+basic_stringbuf<wchar_t>::str(wstring&&);
 
 template basic_istringstream<wchar_t>::basic_istringstream(ios_base::openmode,
                                                           const allocator_type&);
 template basic_istringstream<wchar_t>::basic_istringstream(__string_type&&,
                                                           ios_base::openmode);
+template wstring
+basic_istringstream<wchar_t>::str() const &;
+template wstring
+basic_istringstream<wchar_t>::str() &&;
 template wstring_view
 basic_istringstream<wchar_t>::view() const noexcept;
+template void
+basic_istringstream<wchar_t>::str(wstring&&);
 
 template basic_ostringstream<wchar_t>::basic_ostringstream(ios_base::openmode,
                                                           const allocator_type&);
 template basic_ostringstream<wchar_t>::basic_ostringstream(__string_type&&,
                                                           ios_base::openmode);
+template wstring
+basic_ostringstream<wchar_t>::str() const &;
+template wstring
+basic_ostringstream<wchar_t>::str() &&;
 template wstring_view
 basic_ostringstream<wchar_t>::view() const noexcept;
+template void
+basic_ostringstream<wchar_t>::str(wstring&&);
 
 template basic_stringstream<wchar_t>::basic_stringstream(ios_base::openmode,
                                                         const allocator_type&);
 template basic_stringstream<wchar_t>::basic_stringstream(__string_type&&,
                                                         ios_base::openmode);
+template wstring
+basic_stringstream<wchar_t>::str() const &;
+template wstring
+basic_stringstream<wchar_t>::str() &&;
 template wstring_view
 basic_stringstream<wchar_t>::view() const noexcept;
+template void
+basic_stringstream<wchar_t>::str(wstring&&);
 #endif
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/27_io/basic_istringstream/str/char/2.cc b/libstdc++-v3/testsuite/27_io/basic_istringstream/str/char/2.cc
new file mode 100644 (file)
index 0000000..58ee1d2
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.3.4  basic_istringstream member functions  [istringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::string s0 = "this is not a short string";
+  std::istringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<char>;
+  const Alloc a1(1);
+  std::basic_string<char, std::char_traits<char>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::istringstream ss("123");
+  std::string str = "ABCDEF";
+  ss.str(str);
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::istringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<char>;
+  using Str = std::basic_string<char, std::char_traits<char>, Alloc>;
+  Str s1 = "string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::istringstream ss;
+  const std::string str = "Another quite long string, not at all short";
+  std::string str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_istringstream/str/wchar_t/2.cc b/libstdc++-v3/testsuite/27_io/basic_istringstream/str/wchar_t/2.cc
new file mode 100644 (file)
index 0000000..5958527
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.3.4  basic_istringstream member functions  [istringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::wstring s0 = L"this is not a short string";
+  std::wistringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<wchar_t>;
+  const Alloc a1(1);
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::wistringstream ss(L"123");
+  std::wstring str = L"ABCDEF";
+  ss.str(str);
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::wistringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<wchar_t>;
+  using Str = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc>;
+  Str s1 = L"string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::wistringstream ss;
+  const std::wstring str = L"Another quite long string, not at all short";
+  std::wstring str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
index 091de5f7a797f01f18f60b892c78a5c926677613..c4550702005a441bbd61fab644e611556a2f06c6 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// 27.7.1.1  basic_stringbuf constructors  [lib.stringbuf.cons]
+// 29.8.3.4  basic_istringstream member functions  [istringstream.members]
 
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
@@ -31,5 +31,17 @@ main()
   std::string s("This is a test");
   std::istringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::istringstream&>(stm).view() );
+
+  s = "This is another test with a longer string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  s = "This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  std::string s2;
+  stm >> s2;
+  VERIFY( stm.view() == s );
 }
index f6599643bd90eb56db6db0634660f33d87761a82..8efba06145448b52f894ed4dee9a3513065b1976 100644 (file)
@@ -31,5 +31,17 @@ main()
   std::wstring s(L"This is a test");
   std::wistringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::wistringstream&>(stm).view() );
+
+  s = L"This is another test with a longer string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  s = L"This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  std::wstring s2;
+  stm >> s2;
+  VERIFY( stm.view() == s );
 }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostringstream/str/char/3.cc b/libstdc++-v3/testsuite/27_io/basic_ostringstream/str/char/3.cc
new file mode 100644 (file)
index 0000000..23e961e
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.4.4  basic_ostringstream member functions  [ostringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::string s0 = "this is not a short string";
+  std::ostringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<char>;
+  const Alloc a1(1);
+  std::basic_string<char, std::char_traits<char>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::ostringstream ss("123");
+  std::string str = "ABCDEF";
+  ss << str;
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::ostringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<char>;
+  using Str = std::basic_string<char, std::char_traits<char>, Alloc>;
+  Str s1 = "string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::ostringstream ss;
+  const std::string str = "Another quite long string, not at all short";
+  std::string str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostringstream/str/wchar_t/3.cc b/libstdc++-v3/testsuite/27_io/basic_ostringstream/str/wchar_t/3.cc
new file mode 100644 (file)
index 0000000..7c354cb
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.4.4  basic_ostringstream member functions  [ostringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::wstring s0 = L"this is not a short string";
+  std::wostringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<wchar_t>;
+  const Alloc a1(1);
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::wostringstream ss(L"123");
+  std::wstring str = L"ABCDEF";
+  ss << str;
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::wostringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<wchar_t>;
+  using Str = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc>;
+  Str s1 = L"string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::wostringstream ss;
+  const std::wstring str = L"Another quite long string, not at all short";
+  std::wstring str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
index a366363abb59a8e8d3f314b95577191216c162e0..f072c16f28a804a3f39d64593896b06f9afacf8c 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// 27.7.1.1  basic_stringbuf constructors  [lib.stringbuf.cons]
+// 29.8.4.4  basic_ostringstream member functions  [ostringstream.members]
 
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
@@ -31,5 +31,13 @@ main()
   std::string s("This is a test");
   std::ostringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::ostringstream&>(stm).view() );
+
+  s += " with a longer string";
+  stm << s;
+  VERIFY( stm.view() == s );
+
+  s = "This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
 }
index 1ebf7c505e3062e54d6af7f2c7821aee75e4f00f..3fa2604e1e3163fbfc24f628f64e9a1f501eb677 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// 27.7.1.1  basic_stringbuf constructors  [lib.stringbuf.cons]
+// 29.8.4.4  basic_ostringstream member functions  [ostringstream.members]
 
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
@@ -31,5 +31,13 @@ main()
   std::wstring s(L"This is a test");
   std::wostringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::wostringstream&>(stm).view() );
+
+  s += L" with a longer string";
+  stm << s;
+  VERIFY( stm.view() == s );
+
+  s = L"This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
 }
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/str/char/4.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/str/char/4.cc
new file mode 100644 (file)
index 0000000..3a4b0c7
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.2.4  basic_stringbuf member functions  [stringbuf.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::string s0 = "this is not a short string";
+  std::stringbuf sb;
+  sb.str(s0);
+  VERIFY( sb.str() == s0 );
+  VERIFY( sb.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<char>;
+  const Alloc a1(1);
+  std::basic_string<char, std::char_traits<char>, Alloc> s1 = sb.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( sb.str(a1).get_allocator() == a1 );
+  VERIFY( sb.str(a1) == s1 );
+  VERIFY( std::move(sb).str(a1) == s1 );
+  VERIFY( std::move(sb).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( sb.str(a2).get_allocator() == a2 );
+  VERIFY( sb.str(a2) == s1 );
+
+  VERIFY( std::move(sb).str() == s0 );
+  VERIFY( std::move(sb).str().empty() );
+  VERIFY( sb.str().empty() );
+  VERIFY( sb.str(a1).empty() );
+}
+
+void test02()
+{
+  std::stringbuf sb("123");
+  std::string str = "ABCDEF";
+  sb.sputn(str.c_str(), str.size());
+  VERIFY( sb.str() == str );
+  VERIFY( std::move(sb).str() == str );
+  VERIFY( std::move(sb).str().empty() );
+}
+
+void test03()
+{
+  std::stringbuf sb;
+  using Alloc = __gnu_test::tracker_allocator<char>;
+  using Str = std::basic_string<char, std::char_traits<char>, Alloc>;
+  Str s1("string that is not short, quite long even");
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  sb.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( sb.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::stringbuf sb;
+  const std::string str = "Another quite long string, not at all short";
+  std::string str2 = str;
+  sb.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( sb.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/str/wchar_t/4.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/str/wchar_t/4.cc
new file mode 100644 (file)
index 0000000..5d5187f
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.2.4  basic_stringbuf member functions  [stringbuf.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::wstring s0 = L"this is not a short string";
+  std::wstringbuf sb;
+  sb.str(s0);
+  VERIFY( sb.str() == s0 );
+  VERIFY( sb.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<wchar_t>;
+  const Alloc a1(1);
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc> s1 = sb.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( sb.str(a1).get_allocator() == a1 );
+  VERIFY( sb.str(a1) == s1 );
+  VERIFY( std::move(sb).str(a1) == s1 );
+  VERIFY( std::move(sb).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( sb.str(a2).get_allocator() == a2 );
+  VERIFY( sb.str(a2) == s1 );
+
+  VERIFY( std::move(sb).str() == s0 );
+  VERIFY( std::move(sb).str().empty() );
+  VERIFY( sb.str().empty() );
+  VERIFY( sb.str(a1).empty() );
+}
+
+void test02()
+{
+  std::wstringbuf sb(L"123");
+  std::wstring str = L"ABCDEF";
+  sb.sputn(str.c_str(), str.size());
+  VERIFY( sb.str() == str );
+  VERIFY( std::move(sb).str() == str );
+  VERIFY( std::move(sb).str().empty() );
+}
+
+void test03()
+{
+  std::wstringbuf sb;
+  using Alloc = __gnu_test::tracker_allocator<wchar_t>;
+  using Str = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc>;
+  Str s1 = L"string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  sb.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( sb.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::wstringbuf sb;
+  const std::wstring str = L"Another quite long string, not at all short";
+  std::wstring str2 = str;
+  sb.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( sb.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringstream/str/char/5.cc b/libstdc++-v3/testsuite/27_io/basic_stringstream/str/char/5.cc
new file mode 100644 (file)
index 0000000..917bd21
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.5.4  basic_stringstream member functions  [stringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::string s0 = "this is not a short string";
+  std::stringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<char>;
+  const Alloc a1(1);
+  std::basic_string<char, std::char_traits<char>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::stringstream ss("123");
+  std::string str = "ABCDEF";
+  ss << str;
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::stringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<char>;
+  using Str = std::basic_string<char, std::char_traits<char>, Alloc>;
+  Str s1 = "string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::stringstream ss;
+  const std::string str = "Another quite long string, not at all short";
+  std::string str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_stringstream/str/wchar_t/5.cc.cc b/libstdc++-v3/testsuite/27_io/basic_stringstream/str/wchar_t/5.cc.cc
new file mode 100644 (file)
index 0000000..3a2a26c
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020 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/>.
+
+// 29.8.5.4  basic_stringstream member functions  [stringstream.members]
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  const std::wstring s0 = L"this is not a short string";
+  std::wstringstream ss;
+  ss.str(s0);
+  VERIFY( ss.str() == s0 );
+  VERIFY( ss.str() == s0 );
+
+  using Alloc = __gnu_test::uneq_allocator<wchar_t>;
+  const Alloc a1(1);
+  std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc> s1 = ss.str(a1);
+  VERIFY( s1.get_allocator() == a1 );
+  VERIFY( ss.str(a1).get_allocator() == a1 );
+  VERIFY( ss.str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+  VERIFY( std::move(ss).str(a1) == s1 );
+
+  const Alloc a2(2);
+  VERIFY( ss.str(a2).get_allocator() == a2 );
+  VERIFY( ss.str(a2) == s1 );
+
+  VERIFY( std::move(ss).str() == s0 );
+  VERIFY( std::move(ss).str().empty() );
+  VERIFY( ss.str().empty() );
+  VERIFY( ss.str(a1).empty() );
+}
+
+void test02()
+{
+  std::wstringstream ss(L"123");
+  std::wstring str = L"ABCDEF";
+  ss << str;
+  VERIFY( ss.str() == str );
+  VERIFY( std::move(ss).str() == str );
+  VERIFY( std::move(ss).str().empty() );
+}
+
+void test03()
+{
+  std::wstringstream ss;
+  using Alloc = __gnu_test::tracker_allocator<wchar_t>;
+  using Str = std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc>;
+  Str s1 = L"string that is not short, quite long even";
+  auto count1 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  ss.str(s1);
+  auto count2 = __gnu_test::tracker_allocator_counter::get_allocation_count();
+  VERIFY( count1 == count2 );
+  VERIFY( ss.str() == s1.c_str() );
+}
+
+void test04()
+{
+  std::wstringstream ss;
+  const std::wstring str = L"Another quite long string, not at all short";
+  std::wstring str2 = str;
+  ss.str(std::move(str2));
+  VERIFY( str2.empty() );
+  VERIFY( ss.str() == str );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}
index f47035cf148132385b478c007c9fa0448efedf2a..942db75c0a9ada1a53137d79fde84186586fb44e 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// 27.7.1.1  basic_stringbuf constructors  [lib.stringbuf.cons]
+// 29.8.5.4  basic_stringstream member functions  [stringstream.members]
 
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
@@ -31,5 +31,17 @@ main()
   std::string s("This is a test");
   std::stringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::stringstream&>(stm).view() );
+
+  s += " with a longer string";
+  stm << s;
+  VERIFY( stm.view() == s );
+
+  s = "This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  std::string s2;
+  stm >> s2;
+  VERIFY( stm.view() == s );
 }
index d707cfed2435295747807684b4e068fdbd239afd..7c352993c4f7d6d2a6fc53c2853f32e526d80c36 100644 (file)
@@ -31,5 +31,17 @@ main()
   std::wstring s(L"This is a test");
   std::wstringstream stm(s);
   VERIFY( stm.view() == s );
-  return 0;
+  VERIFY( stm.view() == const_cast<const std::wstringstream&>(stm).view() );
+
+  s += L" with a longer string";
+  stm << s;
+  VERIFY( stm.view() == s );
+
+  s = L"This is a shorter string";
+  stm.str(s);
+  VERIFY( stm.view() == s );
+
+  std::wstring s2;
+  stm >> s2;
+  VERIFY( stm.view() == s );
 }