diff mbox

libstdc++/57394 - copy operations for basic_streambuf

Message ID 20140508171715.GA1450@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely May 8, 2014, 5:17 p.m. UTC
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.
diff mbox

Patch

commit 8550d85bea18d33f97b546886a0d61a1dc87aea9
Author: Jonathan Wakely <jwakely@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();
+}