From: Jonathan Wakely
Date: Fri, 25 Jun 2021 17:31:23 +0000 (+0100)
Subject: libstdc++: Implement LWG 581 for std:ostream::flush()
X-Git-Tag: basepoints/gcc-13~6496
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8c5b542f6cb6a947600e34420565ac67486ea14;p=thirdparty%2Fgcc.git
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/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html
index 7e0837322e59..7b49e4ab87cf 100644
--- a/libstdc++-v3/doc/html/manual/bugs.html
+++ b/libstdc++-v3/doc/html/manual/bugs.html
@@ -303,6 +303,9 @@
550:
What should the return type of pow(float,int) be?
In C++11 mode, remove the pow(float,int), etc., signatures.
+
581:
+ flush()
not unformatted function
+ Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions).
586:
string inserter not a formatted function
Change it to be a formatted output function (i.e. catch exceptions).
diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml
index 3e7843f58c1c..45762caa711d 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.
In C++11 mode, remove the pow(float,int), etc., signatures.
+ 581:
+ flush()
not unformatted function
+
+ Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions).
+
+
586:
string inserter not a formatted function
diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc
index 6285f734031c..664a9f22759a 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 20585f447ac2..d3220e8034ba 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
- {
- if (this->rdbuf() && this->rdbuf()->pubsync() == -1)
- __err |= ios_base::badbit;
- }
- __catch(__cxxabiv1::__forced_unwind&)
+ // 581. flush() not unformatted function
+ // basic_ostream::flush() *is* an unformatted output function.
+ if (__streambuf_type* __buf = this->rdbuf())
{
- this->_M_setstate(ios_base::badbit);
- __throw_exception_again;
+ 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(...)
- { 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 0b33e60bd087..96969debca71 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
#include
#include
+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 bba5fb0baa2f..115b00478a76 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 3711fdedcd54..4403fd3cdf57 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
#include
#include
+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 86440e14f6f6..d88f385a6c3c 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 );
}