* [committed] libstdc++: Implement LWG 581 for std:ostream::flush()
@ 2021-06-25 19:54 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-06-25 19:54 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 714 bytes --]
LWG 581 changed ostream::flush() to an unformatted output function for
C++11, but it was never implemented in libstdc++.
libstdc++-v3/ChangeLog:
* doc/xml/manual/intro.xml: Document LWG 581 change.
* doc/html/manual/bugs.html: Regenerate.
* include/bits/basic_ios.tcc: Whitespace.
* include/bits/ostream.tcc (basic_ostream::flush()): Construct
sentry.
* testsuite/27_io/basic_ostream/flush/char/2.cc: Check
additional cases.
* testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc:
Likewise.
* testsuite/27_io/basic_ostream/flush/wchar_t/2.cc: Likewise.
* testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc:
Likewise.
Tested powerpc64le-linux. Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 10747 bytes --]
commit f8c5b542f6cb6a947600e34420565ac67486ea14
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Jun 25 18:31:23 2021
libstdc++: Implement LWG 581 for std:ostream::flush()
LWG 581 changed ostream::flush() to an unformatted output function for
C++11, but it was never implemented in libstdc++.
libstdc++-v3/ChangeLog:
* doc/xml/manual/intro.xml: Document LWG 581 change.
* doc/html/manual/bugs.html: Regenerate.
* include/bits/basic_ios.tcc: Whitespace.
* include/bits/ostream.tcc (basic_ostream::flush()): Construct
sentry.
* testsuite/27_io/basic_ostream/flush/char/2.cc: Check
additional cases.
* testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc:
Likewise.
* testsuite/27_io/basic_ostream/flush/wchar_t/2.cc: Likewise.
* testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc:
Likewise.
diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml
index 3e7843f58c1..45762caa711 100644
--- a/libstdc++-v3/doc/xml/manual/intro.xml
+++ b/libstdc++-v3/doc/xml/manual/intro.xml
@@ -743,6 +743,12 @@ requirements of the license of GCC.
<listitem><para>In C++11 mode, remove the pow(float,int), etc., signatures.
</para></listitem></varlistentry>
+ <varlistentry xml:id="manual.bugs.dr581"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#581">581</link>:
+ <emphasis><code>flush()</code> not unformatted function</emphasis>
+ </term>
+ <listitem><para>Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions).
+ </para></listitem></varlistentry>
+
<varlistentry xml:id="manual.bugs.dr586"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#586">586</link>:
<emphasis>string inserter not a formatted function</emphasis>
</term>
diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc
index 6285f734031..664a9f22759 100644
--- a/libstdc++-v3/include/bits/basic_ios.tcc
+++ b/libstdc++-v3/include/bits/basic_ios.tcc
@@ -43,7 +43,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (this->rdbuf())
_M_streambuf_state = __state;
else
- _M_streambuf_state = __state | badbit;
+ _M_streambuf_state = __state | badbit;
if (this->exceptions() & this->rdstate())
__throw_ios_failure(__N("basic_ios::clear"));
}
diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc
index 20585f447ac..d3220e8034b 100644
--- a/libstdc++-v3/include/bits/ostream.tcc
+++ b/libstdc++-v3/include/bits/ostream.tcc
@@ -213,21 +213,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// basic_ostream::flush() is *not* an unformatted output function.
- ios_base::iostate __err = ios_base::goodbit;
- __try
+ // 581. flush() not unformatted function
+ // basic_ostream::flush() *is* an unformatted output function.
+ if (__streambuf_type* __buf = this->rdbuf())
{
- if (this->rdbuf() && this->rdbuf()->pubsync() == -1)
- __err |= ios_base::badbit;
+ sentry __cerb(*this);
+ if (__cerb)
+ {
+ ios_base::iostate __err = ios_base::goodbit;
+ __try
+ {
+ if (this->rdbuf()->pubsync() == -1)
+ __err |= ios_base::badbit;
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ this->_M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { this->_M_setstate(ios_base::badbit); }
+ if (__err)
+ this->setstate(__err);
+ }
}
- __catch(__cxxabiv1::__forced_unwind&)
- {
- this->_M_setstate(ios_base::badbit);
- __throw_exception_again;
- }
- __catch(...)
- { this->_M_setstate(ios_base::badbit); }
- if (__err)
- this->setstate(__err);
return *this;
}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/2.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/2.cc
index 0b33e60bd08..96969debca7 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/2.cc
@@ -22,42 +22,70 @@
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// basic_ostream::flush() does not behave as an unformatted output function.
+// But wait ...
+// 581. flush() not unformatted function
+// So now basic_ostream::flush() *is* an unformatted output function.
#include <ostream>
#include <testsuite_hooks.h>
#include <testsuite_io.h>
+void
+test01()
+{
+ std::ostream os(0);
+ VERIFY( os.bad() );
+
+ // Nothing should happen if os.rdbuf() is null. No sentry is constructed.
+ os.flush();
+ VERIFY( os.rdstate() == std::ios_base::badbit ); // no failbit
+
+ os.exceptions(std::ios_base::failbit);
+ os.flush();
+}
+
void test02()
{
__gnu_test::sync_streambuf buf;
std::ostream os(&buf);
-
+
__gnu_test::sync_streambuf buf_tie;
std::ostream os_tie(&buf_tie);
- // No sentry should be constructed so os.tie()->flush() should not be
- // called.
+ // A sentry should be constructed so os.tie()->flush() should be called.
os.tie(&os_tie);
-
+
os.flush();
VERIFY( os.good() );
VERIFY( buf.sync_called() );
- VERIFY( !buf_tie.sync_called() );
+ VERIFY( buf_tie.sync_called() );
+}
- // os.rdbuf()->pubsync() should be called even if !os.good().
+void
+test03()
+{
+ __gnu_test::sync_streambuf buf;
+ std::ostream os(&buf);
+
+ __gnu_test::sync_streambuf buf_tie;
+ std::ostream os_tie(&buf_tie);
+
+ os.tie(&os_tie);
+
+ // os.rdbuf()->pubsync() should not be called if !os.good().
os.setstate(std::ios_base::eofbit);
os.flush();
- VERIFY( os.rdstate() == std::ios_base::eofbit );
- VERIFY( buf.sync_called() );
+ VERIFY( os.rdstate() & std::ios_base::eofbit );
+ VERIFY( !buf.sync_called() );
VERIFY( !buf_tie.sync_called() );
}
int main()
{
+ test01();
test02();
- return 0;
+ test03();
}
-
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc
index bba5fb0baa2..115b00478a7 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc
@@ -28,21 +28,23 @@ void test01()
{
__gnu_test::fail_streambuf bib;
ostream stream(&bib);
+
+ stream.flush(); // should catch exception and set badbit
+ VERIFY( stream.rdstate() == ios_base::badbit );
+
+ stream.clear();
stream.exceptions(ios_base::badbit);
try
{
- stream.flush();
+ stream.flush(); // should catch exception and set badbit and rethrow
VERIFY( false );
}
- catch (const __gnu_test::positioning_error&)
+ catch (const __gnu_test::positioning_error&)
{
- // stream should set badbit and rethrow facet_error.
- VERIFY( stream.bad() );
- VERIFY( (stream.rdstate() & ios_base::failbit) == 0 );
- VERIFY( !stream.eof() );
+ VERIFY( stream.rdstate() == ios_base::badbit );
}
- catch (...)
+ catch (...)
{
VERIFY( false );
}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/2.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/2.cc
index 3711fdedcd5..4403fd3cdf5 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/2.cc
@@ -20,42 +20,70 @@
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// basic_ostream::flush() does not behave as an unformatted output function.
+// But wait ...
+// 581. flush() not unformatted function
+// So now basic_ostream::flush() *is* an unformatted output function.
#include <ostream>
#include <testsuite_hooks.h>
#include <testsuite_io.h>
+void
+test01()
+{
+ std::wostream os(0);
+ VERIFY( os.bad() );
+
+ // Nothing should happen if os.rdbuf() is null. No sentry is constructed.
+ os.flush();
+ VERIFY( os.rdstate() == std::ios_base::badbit ); // no failbit
+
+ os.exceptions(std::ios_base::failbit);
+ os.flush();
+}
+
void test02()
{
__gnu_test::sync_wstreambuf buf;
std::wostream os(&buf);
-
+
__gnu_test::sync_wstreambuf buf_tie;
std::wostream os_tie(&buf_tie);
- // No sentry should be constructed so os.tie()->flush() should not be
- // called.
+ // A sentry should be constructed so os.tie()->flush() should be called.
os.tie(&os_tie);
-
+
os.flush();
VERIFY( os.good() );
VERIFY( buf.sync_called() );
- VERIFY( !buf_tie.sync_called() );
+ VERIFY( buf_tie.sync_called() );
+}
- // os.rdbuf()->pubsync() should be called even if !os.good().
+void
+test03()
+{
+ __gnu_test::sync_wstreambuf buf;
+ std::wostream os(&buf);
+
+ __gnu_test::sync_wstreambuf buf_tie;
+ std::wostream os_tie(&buf_tie);
+
+ os.tie(&os_tie);
+
+ // os.rdbuf()->pubsync() should not be called if !os.good().
os.setstate(std::ios_base::eofbit);
os.flush();
- VERIFY( os.rdstate() == std::ios_base::eofbit );
- VERIFY( buf.sync_called() );
+ VERIFY( os.rdstate() & std::ios_base::eofbit );
+ VERIFY( !buf.sync_called() );
VERIFY( !buf_tie.sync_called() );
}
int main()
{
+ test01();
test02();
- return 0;
+ test03();
}
-
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc
index 86440e14f6f..d88f385a6c3 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc
@@ -28,21 +28,23 @@ void test01()
{
__gnu_test::fail_wstreambuf bib;
wostream stream(&bib);
+
+ stream.flush(); // should catch exception and set badbit
+ VERIFY( stream.rdstate() == ios_base::badbit );
+
+ stream.clear();
stream.exceptions(ios_base::badbit);
try
{
- stream.flush();
+ stream.flush(); // should catch exception and set badbit and rethrow
VERIFY( false );
}
- catch (const __gnu_test::positioning_error&)
+ catch (const __gnu_test::positioning_error&)
{
- // stream should set badbit and rethrow facet_error.
- VERIFY( stream.bad() );
- VERIFY( (stream.rdstate() & ios_base::failbit) == 0 );
- VERIFY( !stream.eof() );
+ VERIFY( stream.rdstate() == ios_base::badbit );
}
- catch (...)
+ catch (...)
{
VERIFY( false );
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-06-25 19:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-25 19:54 [committed] libstdc++: Implement LWG 581 for std:ostream::flush() Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).