[Patch] Fix libstdc++/9561

Jerry Quinn jlquinn@optonline.net
Tue Feb 25 04:33:00 GMT 2003


http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=9561

The testcase throws an exception foobar, which gets caught here:

  template<typename _CharT, typename _Traits>
    basic_ostream<_CharT, _Traits>&
    basic_ostream<_CharT, _Traits>::
    operator<<(__ios_type& (*__pf)(__ios_type&))
    {
      sentry __cerb(*this);
      if (__cerb)
        {
          try
            { __pf(*this); }
          catch(exception& __fail)
            {
              this->setstate(ios_base::badbit);
              if ((this->exceptions() & ios_base::badbit) != 0)
                __throw_exception_again;
            }
        }
      return *this;
    }


The problem is that the exception mask for badbit is on, and setstate() throws
its own exception rather than rethrowing the one already thrown.

The solution is to provide a non-throwing means of setting the badbit flag in
the formatted output routines.

2003-02-24  Jerry Quinn  <jlquinn@us.ibm.com>

        * include/bits/basic_ios.h (_M_setstate): New.
	* include/bits/ostream.tcc (operator<<): Use it.
	* include/std/std_ostream.h (operator<<): Make friends.

Index: libstdc++-v3/include/bits/basic_ios.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/basic_ios.h,v
retrieving revision 1.17
diff -u -r1.17 basic_ios.h
--- libstdc++-v3/include/bits/basic_ios.h	18 Feb 2003 05:45:06 -0000	1.17
+++ libstdc++-v3/include/bits/basic_ios.h	25 Feb 2003 04:18:19 -0000
@@ -441,6 +441,11 @@
 
       void
       _M_cache_locale(const locale& __loc);
+
+      // Internal state setter that won't throw, only set the state bits.
+      // Used to guarantee we don't throw when setting badbit.
+      void
+      _M_setstate(iostate __state) { _M_streambuf_state |= __state; }
     };
 } // namespace std
 
Index: libstdc++-v3/include/bits/ostream.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/ostream.tcc,v
retrieving revision 1.36
diff -u -r1.36 ostream.tcc
--- libstdc++-v3/include/bits/ostream.tcc	13 Feb 2003 21:39:03 -0000	1.36
+++ libstdc++-v3/include/bits/ostream.tcc	25 Feb 2003 04:18:20 -0000
@@ -70,7 +70,7 @@
 	    {
 	      // 27.6.2.5.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -92,7 +92,7 @@
 	    {
 	      // 27.6.2.5.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -114,7 +114,7 @@
 	    {
 	      // 27.6.2.5.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -138,7 +138,7 @@
 	    {
 	      // 27.6.2.5.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -166,7 +166,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -205,7 +205,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -231,7 +231,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -272,7 +272,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -298,7 +298,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -325,7 +325,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -351,7 +351,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -377,7 +377,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      this->setstate(ios_base::badbit);
+	      this->_M_setstate(ios_base::badbit);
 	      if ((this->exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -499,7 +499,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      __out.setstate(ios_base::badbit);
+	      __out._M_setstate(ios_base::badbit);
 	      if ((__out.exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -535,7 +535,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      __out.setstate(ios_base::badbit);
+	      __out._M_setstate(ios_base::badbit);
 	      if ((__out.exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -570,7 +570,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      __out.setstate(ios_base::badbit);
+	      __out._M_setstate(ios_base::badbit);
 	      if ((__out.exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -619,7 +619,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      __out.setstate(ios_base::badbit);
+	      __out._M_setstate(ios_base::badbit);
 	      if ((__out.exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
@@ -658,7 +658,7 @@
 	    {
 	      // 27.6.1.2.1 Common requirements.
 	      // Turn this on without causing an ios::failure to be thrown.
-	      __out.setstate(ios_base::badbit);
+	      __out._M_setstate(ios_base::badbit);
 	      if ((__out.exceptions() & ios_base::badbit) != 0)
 		__throw_exception_again;
 	    }
Index: libstdc++-v3/include/std/std_ostream.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/std/std_ostream.h,v
retrieving revision 1.7
diff -u -r1.7 std_ostream.h
--- libstdc++-v3/include/std/std_ostream.h	7 Feb 2003 00:26:44 -0000	1.7
+++ libstdc++-v3/include/std/std_ostream.h	25 Feb 2003 04:18:21 -0000
@@ -73,6 +73,10 @@
       typedef num_put<_CharT, __ostreambuf_iter>        __numput_type;
       typedef ctype<_CharT>           			__ctype_type;
 
+      friend __ostream_type& operator<< <>(__ostream_type& __out, _CharT __c);
+      friend __ostream_type& operator<< <>(__ostream_type& __out, const _CharT* __s);
+      friend __ostream_type& operator<< <>(__ostream_type& __out, const char* __s);
+
       // [27.6.2.2] constructor/destructor
       /**
        *  @brief  Base constructor.



More information about the Gcc-patches mailing list