]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Implement LWG 581 for std:ostream::flush()
authorJonathan Wakely <jwakely@redhat.com>
Fri, 25 Jun 2021 17:31:23 +0000 (18:31 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 25 Jun 2021 17:47:39 +0000 (18:47 +0100)
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.

libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/basic_ios.tcc
libstdc++-v3/include/bits/ostream.tcc
libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/2.cc
libstdc++-v3/testsuite/27_io/basic_ostream/flush/char/exceptions_badbit_throw.cc
libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/2.cc
libstdc++-v3/testsuite/27_io/basic_ostream/flush/wchar_t/exceptions_badbit_throw.cc

index 7e0837322e5989e5151d31367f2b8523078a5bfc..7b49e4ab87cf491e2df2ec6bbe23a4c0e9c0f555 100644 (file)
     </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).
index 3e7843f58c1c5a6cb651cee10edd586abb25d9c7..45762caa711da3ecf46f89aae320585814f56c60 100644 (file)
@@ -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>
index 6285f734031c2cb5139cc2d81d996da46904efe9..664a9f22759a1ebdc8d7812535862994f8b879d6 100644 (file)
@@ -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"));
     }
index 20585f447ac27d42e140b101564b0a797059ed0d..d3220e8034ba1959ca60c6338f26696f5ffd4c1b 100644 (file)
@@ -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;
     }
 
index 0b33e60bd0875ef3a3dcea5b77b726462d6c0605..96969debca711d56f4c7e17d51ac130c3735a274 100644 (file)
 // _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();
 }
-
index bba5fb0baa2fa6134007049035ebd15b396b26b2..115b00478a76f8505589b4062bca1c0b4162e7ba 100644 (file)
@@ -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 );
     }
index 3711fdedcd54865924237f48bca2afcf69447558..4403fd3cdf5723231cc9604214fa9630bd963ad5 100644 (file)
 // _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();
 }
-
index 86440e14f6f6f413a8c3c51c48fe3dc04a2c2f27..d88f385a6c3c31f3b43c6636308b60703c5ecf3f 100644 (file)
@@ -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 );
     }