This patch isn't very useful on its own, but fixes the PR and should be useful when adding move operations to the derived streambufs.
The mem-initializer for basic_streambuf::_M_out_end was initialized from __sb._M_out_cur, which I assume was not intentional. Those initializers were only added to keep -Weffc++ happy, see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12854#c7 It might make sense just to value-initialize all the members, we're not expecting that copy constructor to ever get called in C++03 mode, but I don't plan to change that. The real commit also removes some trailing whitespace not shown in this patch. Tested x86_64-linux, committed to trunk.
commit 8550d85bea18d33f97b546886a0d61a1dc87aea9 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu May 8 14:42:49 2014 +0100 PR libstdc++/57394 * include/bits/ios_base.h (ios_base(const ios_base&)): Define as deleted for C++11. (operator=(const ios_base&)): Likewise. * include/std/streambuf: Remove trailing whitespace. (basic_streambuf(const basic_streambuf&)): Fix initializer for _M_out_end. Define as defaulted for C++11. (operator=(const basic_streambuf&)): Define as defaulted for C++11. (swap(basic_streambuf&)): Define for C++11. * testsuite/27_io/basic_streambuf/cons/57394.cc: New. diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index ae856de..59c5066 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -780,6 +780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: ios_base() throw (); +#if __cplusplus < 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 50. Copy constructor and assignment operator of ios_base private: @@ -787,6 +788,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ios_base& operator=(const ios_base&); +#else + public: + ios_base(const ios_base&) = delete; + + ios_base& + operator=(const ios_base&) = delete; +#endif }; // [27.4.5.1] fmtflags manipulators diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf index 865f26b..0cb609d 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -796,18 +796,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void __safe_pbump(streamsize __n) { _M_out_cur += __n; } +#if __cplusplus < 201103L private: // _GLIBCXX_RESOLVE_LIB_DEFECTS // Side effect of DR 50. basic_streambuf(const basic_streambuf& __sb) : _M_in_beg(__sb._M_in_beg), _M_in_cur(__sb._M_in_cur), _M_in_end(__sb._M_in_end), _M_out_beg(__sb._M_out_beg), - _M_out_cur(__sb._M_out_cur), _M_out_end(__sb._M_out_cur), + _M_out_cur(__sb._M_out_cur), _M_out_end(__sb._M_out_end), _M_buf_locale(__sb._M_buf_locale) { } basic_streambuf& - operator=(const basic_streambuf&) { return *this; }; + operator=(const basic_streambuf&) { return *this; } +#else + protected: + basic_streambuf(const basic_streambuf&) = default; + + basic_streambuf& + operator=(const basic_streambuf&) = default; + + void + swap(basic_streambuf& __sb) + { + std::swap(_M_in_beg, __sb._M_in_beg); + std::swap(_M_in_cur, __sb._M_in_cur); + std::swap(_M_in_end, __sb._M_in_end); + std::swap(_M_out_beg, __sb._M_out_beg); + std::swap(_M_out_cur, __sb._M_out_cur); + std::swap(_M_out_end, __sb._M_out_end); + std::swap(_M_buf_locale, __sb._M_buf_locale); + } +#endif }; // Explicit specialization declarations, defined in src/streambuf.cc. diff --git a/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc b/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc new file mode 100644 index 0000000..f58c545 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc @@ -0,0 +1,113 @@ +// Copyright (C) 2014 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" } +// { dg-require-namedlocale "de_DE" } + +// 27.6.3 template class basic_streambuf + +#include <streambuf> +#include <testsuite_hooks.h> + +struct streambuf : std::streambuf +{ + streambuf() + { + setp(pbuf, std::end(pbuf)); + setg(gbuf, gbuf, gbuf); + } + + streambuf(const std::locale& loc) : streambuf() + { + imbue(loc); + } + + // implement tests as member functions to be able to call protected members + void test_copy() const; + void test_assign() const; + void test_swap() const; + + char gbuf[32]; + char pbuf[32]; +}; + +void streambuf::test_copy() const +{ + bool test __attribute__((unused)) = true; + + streambuf a(*this); + + VERIFY( eback() == a.eback() ); + VERIFY( gptr() == a.gptr() ); + VERIFY( egptr() == a.egptr() ); + VERIFY( pbase() == a.pbase() ); + VERIFY( pptr() == a.pptr() ); + VERIFY( epptr() == a.epptr() ); + VERIFY( getloc() == a.getloc() ); +} + +void streambuf::test_assign() const +{ + bool test __attribute__((unused)) = true; + + streambuf a; + a = *this; + + VERIFY( eback() == a.eback() ); + VERIFY( gptr() == a.gptr() ); + VERIFY( egptr() == a.egptr() ); + VERIFY( pbase() == a.pbase() ); + VERIFY( pptr() == a.pptr() ); + VERIFY( epptr() == a.epptr() ); + VERIFY( getloc() == a.getloc() ); +} + +void streambuf::test_swap() const +{ + bool test __attribute__((unused)) = true; + + streambuf a(*this); + streambuf b; + const streambuf c(b); + + a.swap(b); + + VERIFY( eback() == b.eback() ); + VERIFY( gptr() == b.gptr() ); + VERIFY( egptr() == b.egptr() ); + VERIFY( pbase() == b.pbase() ); + VERIFY( pptr() == b.pptr() ); + VERIFY( epptr() == b.epptr() ); + VERIFY( getloc() == b.getloc() ); + + VERIFY( c.eback() == a.eback() ); + VERIFY( c.gptr() == a.gptr() ); + VERIFY( c.egptr() == a.egptr() ); + VERIFY( c.pbase() == a.pbase() ); + VERIFY( c.pptr() == a.pptr() ); + VERIFY( c.epptr() == a.epptr() ); + VERIFY( c.getloc() == a.getloc() ); +} + +int main() +{ + std::locale loc("de_DE"); + streambuf s(loc); + s.test_copy(); + s.test_assign(); + s.test_swap(); +}