[committed] libstdc++: Fix exception handling in std::ostream seek functions

Jonathan Wakely jwakely@redhat.com
Fri Jun 25 19:54:01 GMT 2021


N3168 added the requirement that the [ostream.seeks] functions create a
sentry object. Nothing in the requirements of those functions says
anything about catching exceptions and setting badbit.

libstdc++-v3/ChangeLog:

	* include/bits/ostream.tcc (sentry): Only set failbit if badbit
	is set, not if eofbit is set.
	(tellp, seekp, seekp): Create sentry object. Do not set badbit
	on exceptions.
	* testsuite/27_io/basic_ostream/seekp/char/exceptions_badbit_throw.cc:
	Adjust expected behaviour.
	* testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc:
	Likewise.
	* testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc:
	Likewise.
	* testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc:
	Likewise.
	* testsuite/27_io/basic_ostream/seekp/char/n3168.cc: New test.
	* testsuite/27_io/basic_ostream/seekp/wchar_t/n3168.cc: New test.
	* testsuite/27_io/basic_ostream/tellp/char/n3168.cc: New test.
	* testsuite/27_io/basic_ostream/tellp/wchar_t/n3168.cc: New test.

Tested powerpc64le-linux. Committed to trunk.

I've just realised that the description in the commit log is wrong.
After I wrote that I changed the sentry constructor to not set failbit,
so that seeking when eofbit is set doesn't set failbit. Sorry for the
bad commit log. The ChangeLog part is correct.


-------------- next part --------------
commit 9b6c65c754f2b2a78f5353219ec62817064e0d24
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jun 25 18:31:23 2021

    libstdc++: Fix exception handling in std::ostream seek functions
    
    N3168 added the requirement that the [ostream.seeks] functions create a
    sentry object. Nothing in the requirements of those functions says
    anything about catching exceptions and setting badbit.
    
    As well as not catching exceptions, this change results in another
    observable behaviour change. Previously seeking on a stream with eofbit
    set would work (as long as badbit and failbit weren't set). The
    construction of a sentry causes failbit to be set when eofbit is set,
    which causes the seek to fail. It is necessary to clear the eofbit
    before seeking now.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/ostream.tcc (sentry): Only set failbit if badbit
            is set, not if eofbit is set.
            (tellp, seekp, seekp): Create sentry object. Do not set badbit
            on exceptions.
            * testsuite/27_io/basic_ostream/seekp/char/exceptions_badbit_throw.cc:
            Adjust expected behaviour.
            * testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc:
            Likewise.
            * testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc:
            Likewise.
            * testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc:
            Likewise.
            * testsuite/27_io/basic_ostream/seekp/char/n3168.cc: New test.
            * testsuite/27_io/basic_ostream/seekp/wchar_t/n3168.cc: New test.
            * testsuite/27_io/basic_ostream/tellp/char/n3168.cc: New test.
            * testsuite/27_io/basic_ostream/tellp/wchar_t/n3168.cc: New test.

diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc
index 76ca28561c1..20585f447ac 100644
--- a/libstdc++-v3/include/bits/ostream.tcc
+++ b/libstdc++-v3/include/bits/ostream.tcc
@@ -53,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       if (__os.good())
 	_M_ok = true;
-      else
+      else if (__os.bad())
 	__os.setstate(ios_base::failbit);
     }
 
@@ -236,19 +236,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_ostream<_CharT, _Traits>::
     tellp()
     {
+      sentry __cerb(*this);
       pos_type __ret = pos_type(-1);
-      __try
-	{
-	  if (!this->fail())
-	    __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
-	}
-      __catch(__cxxabiv1::__forced_unwind&)
-	{
-	  this->_M_setstate(ios_base::badbit);		
-	  __throw_exception_again;
-	}
-      __catch(...)
-	{ this->_M_setstate(ios_base::badbit); }
+      if (!this->fail())
+	__ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
       return __ret;
     }
 
@@ -257,30 +248,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_ostream<_CharT, _Traits>::
     seekp(pos_type __pos)
     {
-      ios_base::iostate __err = ios_base::goodbit;
-      __try
+      sentry __cerb(*this);
+      if (!this->fail())
 	{
-	  if (!this->fail())
-	    {
-	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-	      // 136.  seekp, seekg setting wrong streams?
-	      const pos_type __p = this->rdbuf()->pubseekpos(__pos,
-							     ios_base::out);
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 136.  seekp, seekg setting wrong streams?
+	  const pos_type __p = this->rdbuf()->pubseekpos(__pos, ios_base::out);
 
-	      // 129. Need error indication from seekp() and seekg()
-	      if (__p == pos_type(off_type(-1)))
-		__err |= ios_base::failbit;
-	    }
+	  // 129. Need error indication from seekp() and seekg()
+	  if (__p == pos_type(off_type(-1)))
+	    this->setstate(ios_base::failbit);
 	}
-      __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;
     }
 
@@ -289,30 +267,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_ostream<_CharT, _Traits>::
     seekp(off_type __off, ios_base::seekdir __dir)
     {
-      ios_base::iostate __err = ios_base::goodbit;
-      __try
+      sentry __cerb(*this);
+      if (!this->fail())
 	{
-	  if (!this->fail())
-	    {
-	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-	      // 136.  seekp, seekg setting wrong streams?
-	      const pos_type __p = this->rdbuf()->pubseekoff(__off, __dir,
-							     ios_base::out);
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 136.  seekp, seekg setting wrong streams?
+	  const pos_type __p = this->rdbuf()->pubseekoff(__off, __dir,
+							 ios_base::out);
 
-	      // 129. Need error indication from seekp() and seekg()
-	      if (__p == pos_type(off_type(-1)))
-		__err |= ios_base::failbit;
-	    }
+	  // 129. Need error indication from seekp() and seekg()
+	  if (__p == pos_type(off_type(-1)))
+	    this->setstate(ios_base::failbit);
 	}
-      __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/seekp/char/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/exceptions_badbit_throw.cc
index a5a95fd872d..bc59578bfa1 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/exceptions_badbit_throw.cc
@@ -28,7 +28,6 @@ void test01()
 
   __gnu_test::fail_streambuf bib;
   ostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   ostream::pos_type pos = ostream::pos_type();
 
@@ -37,14 +36,11 @@ void test01()
       stream.seekp(pos);
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY( false );
     }
@@ -56,7 +52,6 @@ void test02()
 
   __gnu_test::fail_streambuf bib;
   ostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   ostream::off_type off(5);
 
@@ -65,14 +60,11 @@ void test02()
       stream.seekp(off, ios_base::cur);
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY( false );
     }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/n3168.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/n3168.cc
new file mode 100644
index 00000000000..12da0b1f011
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/char/n3168.cc
@@ -0,0 +1,103 @@
+#include <ostream>
+#include <testsuite_hooks.h>
+#include <testsuite_io.h>
+
+// C++11 27.7.3.5 basic_ostream seek members [ostream.seeks]
+
+// Verify [ostream.seeks] functions use a sentry, as per N3168.
+
+void
+test01()
+{
+  // Check that the sentry sets failbit when seeking on a bad stream.
+  // The standard doesn't guarantee this, but it is true for libstdc++.
+
+  std::ostream os(0);
+  VERIFY( os.rdstate() == std::ios_base::badbit );
+
+  std::ostream::pos_type pos = std::ostream::pos_type();
+  os.seekp(pos);
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+  std::ostream::off_type off(5);
+  os.seekp(off, std::ios_base::cur);
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+  os.exceptions(std::ios_base::failbit);
+
+  try
+  {
+    os.clear();
+    os.seekp(pos);
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+
+  try
+  {
+    os.clear();
+    os.seekp(off, std::ios_base::cur);
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+}
+
+void
+test02()
+{
+  // Check that the sentry flushes a tied stream when seeking.
+
+  {
+    __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);
+
+    std::ostream::pos_type pos = std::ostream::pos_type();
+    os.seekp(pos);
+
+    VERIFY( ! buf.sync_called() );
+    VERIFY( buf_tie.sync_called() );
+  }
+
+  {
+    __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);
+
+    std::ostream::off_type off(0);
+    os.seekp(off, std::ios_base::cur);
+
+    VERIFY( ! buf.sync_called() );
+    VERIFY( buf_tie.sync_called() );
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc
index 499389b332b..2daa959532d 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/exceptions_badbit_throw.cc
@@ -28,7 +28,6 @@ void test01()
 
   __gnu_test::fail_wstreambuf bib;
   wostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   wostream::pos_type pos = wostream::pos_type();
 
@@ -37,14 +36,11 @@ void test01()
       stream.seekp(pos);
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY( false );
     }
@@ -53,10 +49,9 @@ void test01()
 void test02()
 {
   using namespace std;
- 
+
   __gnu_test::fail_wstreambuf bib;
   wostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   wostream::off_type off(5);
 
@@ -65,14 +60,11 @@ void test02()
       stream.seekp(off, ios_base::cur);
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY( false );
     }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/n3168.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/n3168.cc
new file mode 100644
index 00000000000..652f46f615c
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/seekp/wchar_t/n3168.cc
@@ -0,0 +1,101 @@
+#include <ostream>
+#include <testsuite_hooks.h>
+#include <testsuite_io.h>
+
+// C++11 27.7.3.5 basic_ostream seek members [ostream.seeks]
+
+// Verify [ostream.seeks] functions use a sentry, as per N3168.
+
+void
+test01()
+{
+  // Check that the sentry sets failbit when seeking on a bad stream.
+  // The standard doesn't guarantee this, but it is true for libstdc++.
+
+  std::wostream os(0);
+  VERIFY( os.rdstate() == std::ios_base::badbit );
+
+  std::wostream::pos_type pos = std::wostream::pos_type();
+  os.seekp(pos);
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+  std::wostream::off_type off(5);
+  os.seekp(off, std::ios_base::cur);
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+  os.exceptions(std::ios_base::failbit);
+
+  try
+  {
+    os.clear();
+    os.seekp(pos);
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+
+  try
+  {
+    os.clear();
+    os.seekp(off, std::ios_base::cur);
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+}
+
+void
+test02()
+{
+  // Check that the sentry flushes a tied stream when seeking.
+
+  {
+    __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);
+
+    std::wostream::pos_type pos = std::wostream::pos_type();
+    os.seekp(pos);
+
+    VERIFY( buf_tie.sync_called() );
+  }
+
+  {
+    __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);
+
+    std::wostream::off_type off(0);
+    os.seekp(off, std::ios_base::cur);
+
+    VERIFY( buf_tie.sync_called() );
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc
index c6b7a8a58e0..7ddddeccc65 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/exceptions_badbit_throw.cc
@@ -28,21 +28,17 @@ void test01()
 {
   __gnu_test::fail_streambuf bib;
   ostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   try
     {
       stream.tellp();
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY(false);
     }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/n3168.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/n3168.cc
new file mode 100644
index 00000000000..8c2fe85db36
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/char/n3168.cc
@@ -0,0 +1,64 @@
+#include <ostream>
+#include <testsuite_hooks.h>
+#include <testsuite_io.h>
+
+// C++11 27.7.3.5 basic_ostream seek members [ostream.seeks]
+
+// Verify [ostream.seeks] functions use a sentry, as per N3168.
+
+void
+test01()
+{
+  // Check that the sentry sets failbit when seeking on a bad stream.
+  // The standard doesn't guarantee this, but it is true for libstdc++.
+
+  std::ostream os(0);
+  VERIFY( os.rdstate() == std::ios_base::badbit );
+
+  os.tellp();
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+
+  os.exceptions(std::ios_base::failbit);
+
+  try
+  {
+    os.clear();
+    os.tellp();
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+}
+
+void
+test02()
+{
+  // Check that the sentry flushes a tied stream when seeking.
+
+  __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.tellp();
+
+  VERIFY( ! buf.sync_called() );
+  VERIFY( buf_tie.sync_called() );
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc
index 6bdeeeb4028..803c45abe11 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/exceptions_badbit_throw.cc
@@ -28,21 +28,17 @@ void test01()
 {
   __gnu_test::fail_wstreambuf bib;
   wostream stream(&bib);
-  stream.exceptions(ios_base::badbit);
 
   try
     {
       stream.tellp();
       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.good() );
     }
-  catch (...) 
+  catch (...)
     {
       VERIFY(false);
     }
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/n3168.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/n3168.cc
new file mode 100644
index 00000000000..887a9a773d1
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/tellp/wchar_t/n3168.cc
@@ -0,0 +1,64 @@
+#include <ostream>
+#include <testsuite_hooks.h>
+#include <testsuite_io.h>
+
+// C++11 27.7.3.5 basic_ostream seek members [ostream.seeks]
+
+// Verify [ostream.seeks] functions use a sentry, as per N3168.
+
+void
+test01()
+{
+  // Check that the sentry sets failbit when seeking on a bad stream.
+  // The standard doesn't guarantee this, but it is true for libstdc++.
+
+  std::wostream os(0);
+  VERIFY( os.rdstate() == std::ios_base::badbit );
+
+  os.tellp();
+  VERIFY( os.rdstate() & std::ios_base::failbit );
+
+  os.clear();
+
+  os.exceptions(std::ios_base::failbit);
+
+  try
+  {
+    os.clear();
+    os.tellp();
+    VERIFY( false );
+  }
+  catch (const std::ios_base::failure&)
+  {
+    VERIFY( os.rdstate() & std::ios_base::failbit );
+  }
+  catch (...)
+  {
+    VERIFY( false );
+  }
+}
+
+void
+test02()
+{
+  // Check that the sentry flushes a tied stream when seeking.
+
+  __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.tellp();
+
+  VERIFY( ! buf.sync_called() );
+  VERIFY( buf_tie.sync_called() );
+}
+
+int main()
+{
+  test01();
+  test02();
+}


More information about the Gcc-patches mailing list