aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2018-05-02 17:25:44 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2018-05-02 17:25:44 +0100
commitc6d425797207908bb9468d79ac170c3f51c7a565 (patch)
treec33075a951b6f896c60ca570ab7134d33c8d292f /libstdc++-v3
parentd6476f90da4bfcb8644da32d3b4c4685a72bc84e (diff)
downloadgcc-c6d425797207908bb9468d79ac170c3f51c7a565.zip
gcc-c6d425797207908bb9468d79ac170c3f51c7a565.tar.gz
gcc-c6d425797207908bb9468d79ac170c3f51c7a565.tar.bz2
PR libstdc++/69608 Move semantics for strstreambuf
In libstdc++ the deprecated char* streams are non-copyable, as was required pre-C++11. Since C++11 the standard implies that those streams should be copyable, but doesn't specify the effects of copying them. This is surely a defect, so for consistency with other implementations this change makes them movable, but not copyable. PR libstdc++/69608 * include/backward/strstream (strstreambuf): Define move constructor and move assignment operator. (istrstream, ostrstream, strstream): Likewise. * testsuite/backward/strstream_move.cc: New. From-SVN: r259842
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog8
-rw-r--r--libstdc++-v3/include/backward/strstream54
-rw-r--r--libstdc++-v3/testsuite/backward/strstream_move.cc244
3 files changed, 305 insertions, 1 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9ef88a8..c53c068 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,11 @@
+2018-05-02 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/69608
+ * include/backward/strstream (strstreambuf): Define move constructor
+ and move assignment operator.
+ (istrstream, ostrstream, strstream): Likewise.
+ * testsuite/backward/strstream_move.cc: New.
+
2018-05-01 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
PR libstdc++/84654
diff --git a/libstdc++-v3/include/backward/strstream b/libstdc++-v3/include/backward/strstream
index 0f0ede4..0429c28 100644
--- a/libstdc++-v3/include/backward/strstream
+++ b/libstdc++-v3/include/backward/strstream
@@ -81,6 +81,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
virtual ~strstreambuf();
+#if __cplusplus >= 201103L
+ strstreambuf(strstreambuf&& __rhs) noexcept
+ : _Base(__rhs), _M_alloc_fun(__rhs._M_alloc_fun),
+ _M_free_fun(__rhs._M_free_fun), _M_dynamic(__rhs._M_dynamic),
+ _M_frozen(__rhs._M_frozen), _M_constant(__rhs._M_constant)
+ {
+ __rhs.setg(nullptr, nullptr, nullptr);
+ __rhs.setp(nullptr, nullptr);
+ }
+
+ strstreambuf&
+ operator=(strstreambuf&& __rhs) noexcept
+ {
+ if (_M_dynamic && !_M_frozen)
+ _M_free(eback());
+ _Base::operator=(static_cast<const _Base&>(__rhs));
+ _M_alloc_fun = __rhs._M_alloc_fun;
+ _M_free_fun = __rhs._M_free_fun;
+ _M_dynamic = __rhs._M_dynamic;
+ _M_frozen = __rhs._M_frozen;
+ _M_constant = __rhs._M_constant;
+ __rhs.setg(nullptr, nullptr, nullptr);
+ __rhs.setp(nullptr, nullptr);
+ return *this;
+ }
+#endif
+
public:
void freeze(bool = true) throw ();
char* str() throw ();
@@ -98,10 +125,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= ios_base::in | ios_base::out);
private:
+#if __cplusplus < 201103L
strstreambuf&
operator=(const strstreambuf&);
strstreambuf(const strstreambuf&);
+#endif
// Dynamic allocation, possibly using _M_alloc_fun and _M_free_fun.
char* _M_alloc(size_t);
@@ -110,7 +139,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Helper function used in constructors.
void _M_setup(char* __get, char* __put, streamsize __n) throw ();
- private:
// Data members.
void* (*_M_alloc_fun)(size_t);
void (*_M_free_fun)(void*);
@@ -130,6 +158,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
istrstream(const char*, streamsize);
virtual ~istrstream();
+#if __cplusplus >= 201103L
+ istrstream(istrstream&& __rhs)
+ : istream(std::move(__rhs)), _M_buf(std::move(__rhs._M_buf))
+ { set_rdbuf(&_M_buf); }
+
+ istrstream& operator=(istrstream&&) = default;
+#endif
+
_GLIBCXX_CONST strstreambuf* rdbuf() const throw ();
char* str() throw ();
@@ -145,6 +181,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
ostrstream(char*, int, ios_base::openmode = ios_base::out);
virtual ~ostrstream();
+#if __cplusplus >= 201103L
+ ostrstream(ostrstream&& __rhs)
+ : ostream(std::move(__rhs)), _M_buf(std::move(__rhs._M_buf))
+ { set_rdbuf(&_M_buf); }
+
+ ostrstream& operator=(ostrstream&&) = default;
+#endif
+
_GLIBCXX_CONST strstreambuf* rdbuf() const throw ();
void freeze(bool = true) throw();
char* str() throw ();
@@ -167,6 +211,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
strstream(char*, int, ios_base::openmode = ios_base::in | ios_base::out);
virtual ~strstream();
+#if __cplusplus >= 201103L
+ strstream(strstream&& __rhs)
+ : iostream(std::move(__rhs)), _M_buf(std::move(__rhs._M_buf))
+ { set_rdbuf(&_M_buf); }
+
+ strstream& operator=(strstream&&) = default;
+#endif
+
_GLIBCXX_CONST strstreambuf* rdbuf() const throw ();
void freeze(bool = true) throw ();
_GLIBCXX_PURE int pcount() const throw ();
diff --git a/libstdc++-v3/testsuite/backward/strstream_move.cc b/libstdc++-v3/testsuite/backward/strstream_move.cc
new file mode 100644
index 0000000..7dfbd33
--- /dev/null
+++ b/libstdc++-v3/testsuite/backward/strstream_move.cc
@@ -0,0 +1,244 @@
+// Copyright (C) 2018 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 "-Wno-deprecated" }
+// { dg-do run { target c++11 } }
+
+#include <strstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::istrstream is("15 16");
+ std::istrstream is2 = std::move(is);
+ int a;
+ is >> a;
+ VERIFY( !is );
+ is2 >> a;
+ VERIFY( is2 );
+ VERIFY( a == 15 );
+ std::istrstream is3 = std::move(is2);
+ int b;
+ is2 >> b;
+ VERIFY( !is2 );
+ is3 >> b;
+ VERIFY( is3 );
+ VERIFY( b == 16 );
+}
+
+void
+test02()
+{
+ std::istrstream is("");
+ int a;
+ is >> a;
+ VERIFY( !is );
+ is = std::istrstream("17 18");
+ is >> a;
+ VERIFY( is );
+ VERIFY( a == 17 );
+ is = std::istrstream("");
+ int b;
+ is >> b;
+ VERIFY( !is );
+}
+
+void
+test03()
+{
+ std::ostrstream os;
+ os << "a few chars"; // fits in initial allocation
+ char* s = os.str(); // os now frozen
+ std::ostrstream os2 = std::move(os);
+ VERIFY( os2.str() == s );
+ VERIFY( os.str() == nullptr );
+ os2.freeze(false);
+
+ os2 << "enough additional chars to force a reallocation";
+ VERIFY( os2 );
+ s = os2.str(); // os2 now frozen
+ std::ostrstream os3 = std::move(os2);
+ VERIFY( os3.str() == s );
+ VERIFY( os2.str() == nullptr );
+ delete[] s;
+}
+
+void
+test04()
+{
+ char buf[16];
+ std::ostrstream os(buf, sizeof(buf));
+ os << "a few chars";
+ char* s = os.str(); // os now frozen
+ VERIFY( s == buf );
+ std::ostrstream os2 = std::move(os);
+ VERIFY( os2.str() == s );
+ VERIFY( os.str() == nullptr );
+ os2.freeze(false);
+
+ os2 << "enough additional chars to force a reallocation";
+ VERIFY( !os2 );
+ s = os2.str(); // os2 now frozen
+ VERIFY( s == buf );
+ std::ostrstream os3 = std::move(os2);
+ VERIFY( os3.str() == s );
+ VERIFY( os2.str() == nullptr );
+}
+
+void
+test05()
+{
+ char buf[] = "0123456789";
+ std::ostrstream os(buf, 1);
+ os << "aa";
+ VERIFY( !os );
+ os = std::ostrstream(buf, 10);
+ os << "some chars";
+ VERIFY( os );
+ VERIFY( os.pcount() == 10 );
+ os << "a";
+ VERIFY( !os );
+ os = std::ostrstream();
+ os << "a";
+ VERIFY( os );
+ VERIFY( os.pcount() == 1 );
+ char* s = os.str(); // os now frozen
+ os = std::ostrstream();
+ os.freeze(false); // no effect
+ delete[] s;
+}
+
+void
+test06()
+{
+ char buf[] = "15 16";
+ std::strstream ss(buf, 5, std::ios::in|std::ios::app);
+ std::strstream ss2 = std::move(ss);
+ int a;
+ ss >> a;
+ VERIFY( !ss );
+ ss2 >> a;
+ VERIFY( ss2 );
+ VERIFY( a == 15 );
+ std::strstream ss3 = std::move(ss2);
+ int b;
+ ss2 >> b;
+ VERIFY( !ss2 );
+ ss3 >> b;
+ VERIFY( ss3 );
+ VERIFY( b == 16 );
+}
+
+void
+test07()
+{
+ std::strstream ss;
+ int a;
+ ss >> a;
+ VERIFY( !ss );
+ char buf[] = "17 18";
+ ss = std::strstream(buf, 5, std::ios::in|std::ios::app);
+ ss >> a;
+ VERIFY( ss );
+ VERIFY( a == 17 );
+ ss = std::strstream();
+ int b;
+ ss >> b;
+ VERIFY( !ss );
+}
+
+void
+test08()
+{
+ std::strstream ss;
+ ss << "a few chars"; // fits in initial allocation
+ char* s = ss.str(); // ss now frozen
+ std::strstream ss2 = std::move(ss);
+ VERIFY( ss2.str() == s );
+ VERIFY( ss.str() == nullptr );
+ ss2.freeze(false);
+
+ ss2 << "enough additional chars to force a reallocation";
+ VERIFY( ss2 );
+ s = ss2.str(); // ss2 now frozen
+ std::strstream ss3 = std::move(ss2);
+ VERIFY( ss3.str() == s );
+ VERIFY( ss2.str() == nullptr );
+ delete[] s;
+}
+
+void
+test09()
+{
+ char buf[16];
+ std::strstream ss(buf, sizeof(buf));
+ ss << "a few chars";
+ char* s = ss.str(); // ss now frozen
+ VERIFY( s == buf );
+ std::strstream ss2 = std::move(ss);
+ VERIFY( ss2.str() == s );
+ VERIFY( ss.str() == nullptr );
+ ss2.freeze(false);
+
+ ss2 << "enough additional chars to force a reallocation";
+ VERIFY( !ss2 );
+ s = ss2.str(); // ss2 now frozen
+ VERIFY( s == buf );
+ std::strstream ss3 = std::move(ss2);
+ VERIFY( ss3.str() == s );
+ VERIFY( ss2.str() == nullptr );
+}
+
+void
+test10()
+{
+ char buf[] = "0123456789";
+ std::strstream ss(buf, 1);
+ ss << "aa";
+ VERIFY( !ss );
+ ss = std::strstream(buf, 10);
+ ss << "some chars";
+ VERIFY( ss );
+ VERIFY( ss.pcount() == 10 );
+ ss << "a";
+ VERIFY( !ss );
+ ss = std::strstream();
+ ss << "a";
+ VERIFY( ss );
+ VERIFY( ss.pcount() == 1 );
+ char* s = ss.str(); // ss now frozen
+ ss = std::strstream();
+ ss.freeze(false); // no effect
+ delete[] s;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+ test05();
+ test06();
+ test07();
+ test08();
+ test09();
+ test10();
+}