Commit 93ef155b by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/81338 correctly manage string capacity

	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.

From-SVN: r250100
parent b1938888
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/
......
......@@ -2918,7 +2918,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
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
......
......@@ -88,6 +88,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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))
......
......@@ -302,18 +302,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__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);
}
}
......
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment