diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2021-06-25 18:31:23 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2021-06-25 18:47:39 +0100 |
commit | f8c5b542f6cb6a947600e34420565ac67486ea14 (patch) | |
tree | 3ee5720da4b8c7603daaee139f3caa2fc378f43b | |
parent | 9b6c65c754f2b2a78f5353219ec62817064e0d24 (diff) | |
download | gcc-f8c5b542f6cb6a947600e34420565ac67486ea14.zip gcc-f8c5b542f6cb6a947600e34420565ac67486ea14.tar.gz gcc-f8c5b542f6cb6a947600e34420565ac67486ea14.tar.bz2 |
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.
8 files changed, 126 insertions, 48 deletions
diff --git a/libstdc++-v3/doc/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html index 7e08373..7b49e4a 100644 --- a/libstdc++-v3/doc/html/manual/bugs.html +++ b/libstdc++-v3/doc/html/manual/bugs.html @@ -303,6 +303,9 @@ </p></dd><dt><a id="manual.bugs.dr550"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#550" target="_top">550</a>: <span class="emphasis"><em>What should the return type of pow(float,int) be?</em></span> </span></dt><dd><p>In C++11 mode, remove the pow(float,int), etc., signatures. + </p></dd><dt><a id="manual.bugs.dr581"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#581" target="_top">581</a>: + <span class="emphasis"><em><code class="code">flush()</code> not unformatted function</em></span> + </span></dt><dd><p>Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions). </p></dd><dt><a id="manual.bugs.dr586"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#586" target="_top">586</a>: <span class="emphasis"><em>string inserter not a formatted function</em></span> </span></dt><dd><p>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 3e7843f..45762ca 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 6285f73..664a9f2 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 20585f4..d3220e8 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 0b33e60..96969de 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 bba5fb0..115b004 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 3711fde..4403fd3 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 86440e1..d88f385 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 ); } |