mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
libstdc++: Fix std::basic_stringbuf::str()&& [PR123100]
When basic_stringbuf::setbuf has been called we need to copy the contents of the buffer into _M_string first, before returning that. libstdc++-v3/ChangeLog: PR libstdc++/123100 * include/std/sstream (basic_stringbuf::str()&&): Handle the case where _M_string is not being used for the buffer. * testsuite/27_io/basic_stringbuf/str/char/123100.cc: New test. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
committed by
Jonathan Wakely
parent
a6c853112d
commit
a94bd31fd8
@@ -298,7 +298,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
#if __cplusplus > 201703L
|
||||
#if _GLIBCXX_USE_CXX11_ABI
|
||||
#if __cpp_concepts
|
||||
// P0407 Allocator-aware basic_streambuf
|
||||
// P0407 Allocator-aware basic_streambuf
|
||||
template<__allocator_like _SAlloc>
|
||||
_GLIBCXX_NODISCARD
|
||||
basic_string<_CharT, _Traits, _SAlloc>
|
||||
@@ -315,8 +315,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
{
|
||||
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());
|
||||
if (_M_string.data() == this->pbase()) [[likely]]
|
||||
// Set length to end of sequence and add null terminator.
|
||||
_M_string._M_set_length(__hi - this->pbase());
|
||||
else
|
||||
_M_string.assign(this->pbase(), __hi);
|
||||
}
|
||||
auto __str = std::move(_M_string);
|
||||
_M_string.clear();
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// { dg-do run }
|
||||
|
||||
#include <sstream>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
const int n = 20;
|
||||
const char data[n] = "abcde";
|
||||
char buf[n] = "0123456789";
|
||||
std::string expected("abcde56789\0\0\0\0\0\0\0\0\0\0", n);
|
||||
|
||||
std::ostringstream out;
|
||||
out.rdbuf()->pubsetbuf(buf, n);
|
||||
out << data;
|
||||
VERIFY( out.str() == expected );
|
||||
VERIFY( out.str() == expected );
|
||||
#if __cplusplus >= 201103L
|
||||
VERIFY( std::move(out).str() == expected );
|
||||
#if __cplusplus >= 202002L && _GLIBCXX_USE_CXX11_ABI
|
||||
expected.clear();
|
||||
#endif
|
||||
VERIFY( out.str() == expected );
|
||||
VERIFY( std::move(out).str() == expected );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
const int n = 20;
|
||||
const char data[n] = "abcde";
|
||||
char buf[n] = "0123456789";
|
||||
std::string expected("abcde56789\0\0\0\0\0\0\0\0\0\0", n);
|
||||
|
||||
std::ostringstream out;
|
||||
out << std::string(n * 2, 'a');
|
||||
VERIFY( out.str() == std::string(n * 2, 'a') );
|
||||
out.rdbuf()->pubsetbuf(buf, n);
|
||||
out << data; // writes 6 chars
|
||||
VERIFY( out.str() == expected );
|
||||
VERIFY( out.str() == expected );
|
||||
#if __cplusplus >= 201103L
|
||||
VERIFY( std::move(out).str() == expected );
|
||||
#if __cplusplus >= 202002L && _GLIBCXX_USE_CXX11_ABI
|
||||
expected.clear();
|
||||
#endif
|
||||
VERIFY( out.str() == expected );
|
||||
VERIFY( std::move(out).str() == expected );
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
||||
Reference in New Issue
Block a user