+2017-07-10 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81338
+ * include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI] (basic_string):
+ Declare basic_stringbuf to be a friend.
+ * include/bits/sstream.tcc (basic_stringbuf::overflow)
+ [_GLIBCXX_USE_CXX11_ABI]: Use unused capacity before reallocating.
+ * include/std/sstream (basic_stringbuf::__xfer_bufptrs): Update string
+ length to buffer length.
+ * testsuite/27_io/basic_stringstream/assign/81338.cc: New.
+
2017-07-06 Jonathan Wakely <jwakely@redhat.com>
* testsuite/20_util/specialized_algorithms/memory_management_tools/
int
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const;
- };
+
+ // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
+ template<typename, typename, typename> friend class basic_stringbuf;
+ };
_GLIBCXX_END_NAMESPACE_CXX11
#else // !_GLIBCXX_USE_CXX11_ABI
// Reference-counted COW string implentation
return traits_type::not_eof(__c);
const __size_type __capacity = _M_string.capacity();
+
+#if _GLIBCXX_USE_CXX11_ABI
+ if ((this->epptr() - this->pbase()) < __capacity)
+ {
+ // There is additional capacity in _M_string that can be used.
+ char_type* __base = const_cast<char_type*>(_M_string.data());
+ _M_pbump(__base, __base + __capacity, this->pptr() - this->pbase());
+ if (_M_mode & ios_base::in)
+ {
+ const __size_type __nget = this->gptr() - this->eback();
+ const __size_type __eget = this->egptr() - this->eback();
+ this->setg(__base, __base + __nget, __base + __eget + 1);
+ }
+ *this->pptr() = traits_type::to_char_type(__c);
+ this->pbump(1);
+ return __c;
+ }
+#endif
+
const __size_type __max_size = _M_string.max_size();
const bool __testput = this->pptr() < this->epptr();
if (__builtin_expect(!__testput && __capacity == __max_size, false))
__xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
: _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
{
- const _CharT* __str = __from._M_string.data();
+ const _CharT* const __str = __from._M_string.data();
+ const _CharT* __end = nullptr;
if (__from.eback())
{
- _M_goff[0] = __from.eback() - __str;
- _M_goff[1] = __from.gptr() - __str;
- _M_goff[2] = __from.egptr() - __str;
+ _M_goff[0] = __from.eback() - __str;
+ _M_goff[1] = __from.gptr() - __str;
+ _M_goff[2] = __from.egptr() - __str;
+ __end = __from.egptr();
}
if (__from.pbase())
{
_M_poff[0] = __from.pbase() - __str;
_M_poff[1] = __from.pptr() - __from.pbase();
_M_poff[2] = __from.epptr() - __str;
+ if (__from.pptr() > __end)
+ __end = __from.pptr();
+ }
+
+ // Set _M_string length to the greater of the get and put areas.
+ if (__end)
+ {
+ // The const_cast avoids changing this constructor's signature,
+ // because it is exported from the dynamic library.
+ auto& __mut_from = const_cast<basic_stringbuf&>(__from);
+ __mut_from._M_string._M_length(__end - __str);
}
}
--- /dev/null
+// Copyright (C) 2017 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 run { target c++11 } }
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::stringstream ss;
+ for (int i = 0; i < 100; ++i)
+ {
+ ss << 'a';
+ VERIFY( static_cast<bool>(ss) );
+ VERIFY( ss.str() == "a" );
+ ss = std::stringstream();
+ }
+}
+
+int
+main()
+{
+ test01();
+}