public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* RE: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-25 21:56 Pétur Runólfsson
  0 siblings, 0 replies; 13+ messages in thread
From: Pétur Runólfsson @ 2003-04-25 21:56 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: =?iso-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
To: "Benjamin Kosnik" <bkoz@redhat.com>
Cc: <gcc-bugs@gcc.gnu.org>,
	<gcc-gnats@gcc.gnu.org>
Subject: RE: libstdc++/10132: filebuf destructor throws exceptions
Date: Fri, 25 Apr 2003 21:47:38 -0000

 > Like this.
 
 This looks good.
 
 Petur


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-28 16:00 bkoz
  0 siblings, 0 replies; 13+ messages in thread
From: bkoz @ 2003-04-28 16:00 UTC (permalink / raw)
  To: bkoz, gcc-bugs, gcc-prs, peturr02

Synopsis: filebuf destructor throws exceptions

State-Changed-From-To: feedback->closed
State-Changed-By: bkoz
State-Changed-When: Mon Apr 28 16:00:43 2003
State-Changed-Why:
    Fixed, gcc and gcc-3_3-branch

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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-25 21:46 Pétur Runólfsson
  0 siblings, 0 replies; 13+ messages in thread
From: Pétur Runólfsson @ 2003-04-25 21:46 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: =?iso-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
To: "Benjamin Kosnik" <bkoz@redhat.com>
Cc: <gcc-bugs@gcc.gnu.org>,
	<gcc-gnats@gcc.gnu.org>
Subject: RE: libstdc++/10132: filebuf destructor throws exceptions
Date: Fri, 25 Apr 2003 21:36:55 -0000

 > >Also, what's the rationale behind rethrowing some but not all
 > >exceptions?
 >=20
 > Why would you propogate when the the exception can be cleaned=20
 > up at the
 > point of failure? If something that this function is not prepared to
 > deal with happens, then it can rethrow.
 
 I don't see that filebuf members can in general handle exceptions
 thrown by codecvt members. The best they can reasonably do is to
 catch the exception and return an error value.
 
 > >I don't think that basic_filebuf should catch exceptions thrown
 > >by use_facet or codecvt members.=20
 >=20
 > Why?
 
 1. Consistency with the rest of the library, which allows
    exceptions to propagate.
 
 2. basic_istream and basic_ostream allow the caller to decide
    on the exception handling policy.
 
 3. When codecvt operations throw exceptions the filebuf is in
    general unreadable and left in an indeterminate state. This
    indicates that badbit should be set in rdstate(). For
    underflow(), this will only happen if an exception is
    thrown.
 
 > 1) make non-virtual codecvt MF's throw(), wrap all virtual calls with
 > try, and in the catch block return codecvt_base::error.
 
 I don't like this. It decides the exception handling policy for all
 users of codecvt, not just filebuf.
 
 > 2) try/catch in filebuf::~filebuf. The problem with this is that the
 > "cleanups" are quite difficult to do in ~filebuf if filebuf::close
 > fails, and we will end up either duplicating a bunch of filbuf::close,
 > or leaking memory.
 
 If filebuf::close() frees all resources, even when exceptions are
 thrown, ~filebuf won't have to do any cleanup.
 
 > 3) try to deal with the codecvt errors at the point of usage, ie in
 > underflow/overflow. I think this makes the most sense.
 
 If codecvt::in throws an exception, underflow can't produce any
 characters and hence must fail, so I don't see that this is
 possible.
 
 Petur


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-25  0:56 Benjamin Kosnik
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Kosnik @ 2003-04-25  0:56 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 19:48:40 -0500

 Like this.
 
 2003-04-24  Benjamin Kosnik  <bkoz@redhat.com>
 
 	PR libstdc++/10132
 	* include/std/std_fstream.h (basic_filebuf::is_open): Add throw()
 	exception specifications.
 	(basic_filebuf::close): Same.
 	(basic_filebuf::_M_pback_destroy): Same.
 	(basic_filebuf::_M_destroy_internal_buffer): Same.
 	(basic_filebuf): Remove __res_type typedef.=09
 	* src/fstream.cc: Same.
 	* include/bits/fstream.tcc
 	(basic_filebuf::_M_convert_to_external): Simplify.
 	(basic_filebuf::seekoff): Use has_facet	before use_facet.
 	(basic_filebuf::close): Add exception specification of throw().
 	* testsuite/27_io/basic_filebuf/cons: New.
 	* testsuite/27_io/basic_filebuf/cons/wchar_t: New.=09
 	* testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc: New.=09
 	* testsuite/27_io/basic_filebuf/seekoff/10132-2.cc: New.
 	* testsuite/27_io/basic_filebuf/seekpos/10132-3.cc: New.
 
 Index: include/bits/fstream.tcc
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
 retrieving revision 1.65
 diff -c -p -r1.65 fstream.tcc
 *** include/bits/fstream.tcc	22 Apr 2003 17:32:25 -0000	1.65
 --- include/bits/fstream.tcc	24 Apr 2003 23:57:52 -0000
 *************** namespace std
 *** 60,66 ****
     template<typename _CharT, typename _Traits>
       void
       basic_filebuf<_CharT, _Traits>::
 !     _M_destroy_internal_buffer()
       {
         if (_M_buf_allocated)
   	{
 --- 60,66 ----
     template<typename _CharT, typename _Traits>
       void
       basic_filebuf<_CharT, _Traits>::
 !     _M_destroy_internal_buffer() throw()
       {
         if (_M_buf_allocated)
   	{
 *************** namespace std
 *** 114,153 ****
     template<typename _CharT, typename _Traits>
       typename basic_filebuf<_CharT, _Traits>::__filebuf_type*=20
       basic_filebuf<_CharT, _Traits>::
 !     close()
       {
         __filebuf_type* __ret =3D NULL;
         if (this->is_open())
   	{
   	  bool __testfail =3D false;
 ! 	  const int_type __eof =3D traits_type::eof();
 ! 	  const bool __testput =3D this->_M_out_beg < this->_M_out_lim;
  =20
 ! 	  if (__testput=20
 ! 	      && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
 ! 	    __testfail =3D true;
  =20
   #if 0
 ! 	  // XXX not done
 ! 	  if (_M_last_overflowed)
   	    {
 ! 	      _M_output_unshift();
 ! 	      _M_really_overflow(__eof);
   	    }
 ! #endif
 !=20
   	  // NB: Do this here so that re-opened filebufs will be cool...
   	  this->_M_mode =3D ios_base::openmode(0);
   	  _M_destroy_internal_buffer();
   	  _M_pback_destroy();
 !=20
   	  if (!_M_file.close())
   	    __testfail =3D true;
  =20
   	  if (!__testfail)
   	    __ret =3D this;
   	}
 !       _M_last_overflowed =3D false;=09
         return __ret;
       }
  =20
 --- 114,161 ----
     template<typename _CharT, typename _Traits>
       typename basic_filebuf<_CharT, _Traits>::__filebuf_type*=20
       basic_filebuf<_CharT, _Traits>::
 !     close() throw()
       {
         __filebuf_type* __ret =3D NULL;
         if (this->is_open())
   	{
   	  bool __testfail =3D false;
 ! 	  try
 ! 	    {
 ! 	      const int_type __eof =3D traits_type::eof();
 ! 	      const bool __testput =3D this->_M_out_beg < this->_M_out_lim;
  =20
 ! 	      if (__testput=20
 ! 		  && traits_type::eq_int_type(_M_really_overflow(__eof),=20
 ! 					      __eof))
 ! 		__testfail =3D true;
  =20
   #if 0
 ! 	      // XXX not done
 ! 	      if (_M_last_overflowed)
 ! 		{
 ! 		  _M_output_unshift();
 ! 		  _M_really_overflow(__eof);
 ! 		}
 ! #endif
 ! 	    }
 ! 	  catch(...)
   	    {
 ! 	      __testfail =3D true;
   	    }
 ! 	     =20
   	  // NB: Do this here so that re-opened filebufs will be cool...
   	  this->_M_mode =3D ios_base::openmode(0);
   	  _M_destroy_internal_buffer();
   	  _M_pback_destroy();
 ! 	 =20
   	  if (!_M_file.close())
   	    __testfail =3D true;
  =20
   	  if (!__testfail)
   	    __ret =3D this;
   	}
 !       _M_last_overflowed =3D false;
         return __ret;
       }
  =20
 *************** namespace std
 *** 160,167 ****
         const bool __testin =3D this->_M_mode & ios_base::in;
         const locale __loc =3D this->getloc();
         const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);
 !       // Sync with stdio.
 !       const bool __sync =3D this->_M_buf_size <=3D 1;
  =20
         if (__testin && this->is_open())
   	{
 --- 168,174 ----
         const bool __testin =3D this->_M_mode & ios_base::in;
         const locale __loc =3D this->getloc();
         const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);
 !       const bool __testsync =3D this->_M_buf_size <=3D 1;
  =20
         if (__testin && this->is_open())
   	{
 *************** namespace std
 *** 170,176 ****
   	  // For a stateful encoding (-1) the pending sequence might be just
   	  // shift and unshift prefixes with no actual character.
   	  if (__cvt.encoding() >=3D 0)
 ! 	    __ret +=3D _M_file.showmanyc_helper(__sync) / __cvt.max_length();
   	}
  =20
         _M_last_overflowed =3D false;=09
 --- 177,183 ----
   	  // For a stateful encoding (-1) the pending sequence might be just
   	  // shift and unshift prefixes with no actual character.
   	  if (__cvt.encoding() >=3D 0)
 ! 	    __ret +=3D _M_file.showmanyc_helper(__testsync) / __cvt.max_length();
   	}
  =20
         _M_last_overflowed =3D false;=09
 *************** namespace std
 *** 283,297 ****
       _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
   			   streamsize& __elen, streamsize& __plen)
       {
         const locale __loc =3D this->getloc();
         const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);
 -       // Sync with stdio.
 -       const bool __sync =3D this->_M_buf_size <=3D 1;
  =20
         if (__cvt.always_noconv() && __ilen)
   	{
 ! 	  __elen +=3D
 ! 	    _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen, __sync);
   	  __plen +=3D __ilen;
   	}
         else
 --- 290,303 ----
       _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
   			   streamsize& __elen, streamsize& __plen)
       {
 +       const bool __testsync =3D this->_M_buf_size <=3D 1;
         const locale __loc =3D this->getloc();
         const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);
  =20
         if (__cvt.always_noconv() && __ilen)
   	{
 ! 	  __elen +=3D _M_file.xsputn(reinterpret_cast<char*>(__ibuf),=20
 ! 				   __ilen, __testsync);
   	  __plen +=3D __ilen;
   	}
         else
 *************** namespace std
 *** 304,330 ****
   	  char* __buf =3D static_cast<char*>(__builtin_alloca(__blen));
   	  char* __bend;
   	  const char_type* __iend;
 ! 	  __res_type __r =3D __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,=20
 ! 		 		     __iend, __buf, __buf + __blen, __bend);
 !=20
   	  if (__r =3D=3D codecvt_base::ok || __r =3D=3D codecvt_base::partial)
   	    __blen =3D __bend - __buf;
 - 	  // Similarly to the always_noconv case above.
   	  else if (__r =3D=3D codecvt_base::noconv)
   	    {
   	      __buf =3D reinterpret_cast<char*>(__ibuf);
   	      __blen =3D __ilen;
   	    }
 ! 	  // Result =3D=3D error
 ! 	  else=20
 ! 	    __blen =3D 0;
   	 =20
   	  if (__blen)
   	    {
 ! 	      __elen +=3D _M_file.xsputn(__buf, __blen, __sync);
   	      __plen +=3D __blen;
   	    }
 !=20
   	  // Try once more for partial conversions.
   	  if (__r =3D=3D codecvt_base::partial)
   	    {
 --- 310,339 ----
   	  char* __buf =3D static_cast<char*>(__builtin_alloca(__blen));
   	  char* __bend;
   	  const char_type* __iend;
 ! 	  codecvt_base::result __r;
 ! 	  __r =3D __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
 ! 			  __iend, __buf, __buf + __blen, __bend);
 ! 	 =20
   	  if (__r =3D=3D codecvt_base::ok || __r =3D=3D codecvt_base::partial)
   	    __blen =3D __bend - __buf;
   	  else if (__r =3D=3D codecvt_base::noconv)
   	    {
 + 	      // Same as the always_noconv case above.
   	      __buf =3D reinterpret_cast<char*>(__ibuf);
   	      __blen =3D __ilen;
   	    }
 ! 	  else
 ! 	    {
 ! 	      // Result =3D=3D error=20
 ! 	      __blen =3D 0;
 ! 	    }
   	 =20
   	  if (__blen)
   	    {
 ! 	      __elen +=3D _M_file.xsputn(__buf, __blen, __testsync);
   	      __plen +=3D __blen;
   	    }
 ! 	 =20
   	  // Try once more for partial conversions.
   	  if (__r =3D=3D codecvt_base::partial)
   	    {
 *************** namespace std
 *** 333,349 ****
   	      __r =3D __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,=20
   			      __iend, __buf, __buf + __blen, __bend);
   	      if (__r !=3D codecvt_base::error)
 - 		__rlen =3D __bend - __buf;
 - 	      else
 - 		{
 - 		  __rlen =3D 0;
 - 		  // Signal to the caller (_M_really_overflow) that
 - 		  // codecvt::out eventually failed.
 - 		  __elen =3D 0;		 =20
 - 		}
 - 	      if (__rlen)
   		{
 ! 		  __elen +=3D _M_file.xsputn(__buf, __rlen, __sync);
   		  __plen +=3D __rlen;
   		}
   	    }
 --- 342,350 ----
   	      __r =3D __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,=20
   			      __iend, __buf, __buf + __blen, __bend);
   	      if (__r !=3D codecvt_base::error)
   		{
 ! 		  __rlen =3D __bend - __buf;
 ! 		  __elen +=3D _M_file.xsputn(__buf, __rlen, __testsync);
   		  __plen +=3D __rlen;
   		}
   	    }
 *************** namespace std
 *** 358,365 ****
         int_type __ret =3D traits_type::eof();
         const bool __testput =3D this->_M_out_beg < this->_M_out_lim;
         const bool __testunbuffered =3D _M_file.is_open() && !this->_M_buf_=
 size;
 !       // Sync with stdio.
 !       const bool __sync =3D this->_M_buf_size <=3D 1;
  =20
         if (__testput || __testunbuffered)
   	{
 --- 359,365 ----
         int_type __ret =3D traits_type::eof();
         const bool __testput =3D this->_M_out_beg < this->_M_out_lim;
         const bool __testunbuffered =3D _M_file.is_open() && !this->_M_buf_=
 size;
 !       const bool __testsync =3D this->_M_buf_size <=3D 1;
  =20
         if (__testput || __testunbuffered)
   	{
 *************** namespace std
 *** 373,379 ****
   	  if (_M_filepos && _M_filepos !=3D this->_M_out_beg)
   	    {
   	      off_type __off =3D this->_M_out_beg - _M_filepos;
 ! 	      _M_file.seekoff(__off, ios_base::cur, __sync);
   	    }
  =20
   	  // Convert internal buffer to external representation, output.
 --- 373,379 ----
   	  if (_M_filepos && _M_filepos !=3D this->_M_out_beg)
   	    {
   	      off_type __off =3D this->_M_out_beg - _M_filepos;
 ! 	      _M_file.seekoff(__off, ios_base::cur, __testsync);
   	    }
  =20
   	  // Convert internal buffer to external representation, output.
 *************** namespace std
 *** 394,400 ****
   		  char_type __pending =3D traits_type::to_char_type(__c);
   		  _M_convert_to_external(&__pending, 1, __elen, __plen);
  =20
 ! 		  // User code must flush when switching modes (thus don't sync).
   		  if (__elen =3D=3D __plen && __elen)
   		    {
   		      _M_set_indeterminate();
 --- 394,401 ----
   		  char_type __pending =3D traits_type::to_char_type(__c);
   		  _M_convert_to_external(&__pending, 1, __elen, __plen);
  =20
 ! 		  // User code must flush when switching modes (thus
 ! 		  // don't sync).
   		  if (__elen =3D=3D __plen && __elen)
   		    {
   		      _M_set_indeterminate();
 *************** namespace std
 *** 446,460 ****
         pos_type __ret =3D  pos_type(off_type(-1));=20
         const bool __testin =3D (ios_base::in & this->_M_mode & __mode) !=
 =3D 0;
         const bool __testout =3D (ios_base::out & this->_M_mode & __mode) !=
 =3D 0;
 !       // Sync with stdio.
 !       const bool __sync =3D this->_M_buf_size <=3D 1;
        =20
 !       // Should probably do has_facet checks here.
 !       int __width =3D use_facet<__codecvt_type>(this->_M_buf_locale).enco=
 ding();
         if (__width < 0)
   	__width =3D 0;
 !       const bool __testfail =3D __off !=3D 0 && __width <=3D 0;
 !      =20
         if (this->is_open() && !__testfail && (__testin || __testout))=20
   	{
   	  // Ditch any pback buffers to avoid confusion.
 --- 447,461 ----
         pos_type __ret =3D  pos_type(off_type(-1));=20
         const bool __testin =3D (ios_base::in & this->_M_mode & __mode) !=
 =3D 0;
         const bool __testout =3D (ios_base::out & this->_M_mode & __mode) !=
 =3D 0;
 !       const bool __testsync =3D this->_M_buf_size <=3D 1;
        =20
 !       int __width =3D 0;
 !       if (has_facet<__codecvt_type>(this->_M_buf_locale))
 ! 	  __width =3D use_facet<__codecvt_type>(this->_M_buf_locale).encoding();
         if (__width < 0)
   	__width =3D 0;
 !=20
 !       const bool __testfail =3D __off !=3D 0 && __width <=3D 0;     =20
         if (this->is_open() && !__testfail && (__testin || __testout))=20
   	{
   	  // Ditch any pback buffers to avoid confusion.
 *************** namespace std
 *** 480,501 ****
   		__computed_off +=3D this->_M_in_cur - _M_filepos;
  =20
   	      // Return pos_type(off_type(-1)) in case of failure.
 ! 	      __ret =3D _M_file.seekoff(__computed_off, __way, __sync, __mode);
   	      _M_set_indeterminate();
   	    }
   	  // NB: Need to do this in case _M_file in indeterminate
   	  // state, ie _M_file._offset =3D=3D -1
   	  else
   	    {
 ! 	      pos_type __tmp =3D
 ! 		_M_file.seekoff(__off, ios_base::cur,
 ! 				__sync, __mode);
   	      if (__tmp >=3D 0)
   		{
   		  // Seek successful.
   		  __ret =3D __tmp;
 ! 		  __ret +=3D
 ! 		    std::max(this->_M_out_cur, this->_M_in_cur) - _M_filepos;
   		}
   	    }
   	}
 --- 481,502 ----
   		__computed_off +=3D this->_M_in_cur - _M_filepos;
  =20
   	      // Return pos_type(off_type(-1)) in case of failure.
 ! 	      __ret =3D _M_file.seekoff(__computed_off, __way, __testsync,=20
 ! 				      __mode);
   	      _M_set_indeterminate();
   	    }
   	  // NB: Need to do this in case _M_file in indeterminate
   	  // state, ie _M_file._offset =3D=3D -1
   	  else
   	    {
 ! 	      pos_type __tmp =3D _M_file.seekoff(__off, ios_base::cur,=20
 ! 					       __testsync, __mode);
   	      if (__tmp >=3D 0)
   		{
   		  // Seek successful.
   		  __ret =3D __tmp;
 ! 		  __ret +=3D std::max(this->_M_out_cur, this->_M_in_cur)=20
 ! 		           - _M_filepos;
   		}
   	    }
   	}
 Index: include/std/std_fstream.h
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_fstream.h,v
 retrieving revision 1.29
 diff -c -p -r1.29 std_fstream.h
 *** include/std/std_fstream.h	22 Apr 2003 17:32:25 -0000	1.29
 --- include/std/std_fstream.h	24 Apr 2003 23:57:53 -0000
 *************** namespace std
 *** 81,87 ****
         typedef __basic_file<char>		        __file_type;
         typedef typename traits_type::state_type          __state_type;
         typedef codecvt<char_type, char, __state_type>    __codecvt_type;
 -       typedef typename __codecvt_type::result 	        __res_type;
         typedef ctype<char_type>                          __ctype_type;
         //@}
  =20
 --- 81,86 ----
 *************** namespace std
 *** 171,177 ****
         // Assumptions:
         // The pback buffer has only moved forward.
         void
 !       _M_pback_destroy()
         {
   	if (_M_pback_init)
   	  {
 --- 170,176 ----
         // Assumptions:
         // The pback buffer has only moved forward.
         void
 !       _M_pback_destroy() throw()
         {
   	if (_M_pback_init)
   	  {
 *************** namespace std
 *** 218,224 ****
          *  @brief  Returns true if the external file is open.
         */
         bool
 !       is_open() const { return _M_file.is_open(); }
  =20
         /**
          *  @brief  Opens an external file.
 --- 217,223 ----
          *  @brief  Returns true if the external file is open.
         */
         bool
 !       is_open() const throw() { return _M_file.is_open(); }
  =20
         /**
          *  @brief  Opens an external file.
 *************** namespace std
 *** 248,254 ****
          *  If any operations fail, this function also fails.
         */
         __filebuf_type*
 !       close();
  =20
       protected:
         /**
 --- 247,253 ----
          *  If any operations fail, this function also fails.
         */
         __filebuf_type*
 !       close() throw();
  =20
       protected:
         /**
 *************** namespace std
 *** 265,271 ****
          *  @endif
         */
         void
 !       _M_destroy_internal_buffer();
  =20
         // [27.8.1.4] overridden virtual functions
         // [documentation is inherited]
 --- 264,270 ----
          *  @endif
         */
         void
 !       _M_destroy_internal_buffer() throw();
  =20
         // [27.8.1.4] overridden virtual functions
         // [documentation is inherited]
 Index: src/fstream.cc
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/gcc/gcc/libstdc++-v3/src/fstream.cc,v
 retrieving revision 1.8
 diff -c -p -r1.8 fstream.cc
 *** src/fstream.cc	20 Apr 2003 13:54:45 -0000	1.8
 --- src/fstream.cc	24 Apr 2003 23:57:53 -0000
 *************** namespace std=20
 *** 43,50 ****
         int_type __ret =3D traits_type::eof();
         const bool __testin =3D _M_mode & ios_base::in;
         const bool __testout =3D _M_mode & ios_base::out;
 !       // Sync with stdio.
 !       const bool __sync =3D _M_buf_size <=3D 1;
  =20
         if (__testin)
   	{
 --- 43,49 ----
         int_type __ret =3D traits_type::eof();
         const bool __testin =3D _M_mode & ios_base::in;
         const bool __testout =3D _M_mode & ios_base::out;
 !       const bool __testsync =3D _M_buf_size <=3D 1;
  =20
         if (__testin)
   	{
 *************** namespace std=20
 *** 72,78 ****
   		_M_really_overflow();
   	      else if (_M_in_cur !=3D _M_filepos)
   		_M_file.seekoff(_M_in_cur - _M_filepos,
 ! 				ios_base::cur, __sync, ios_base::in);
   	    }
  =20
   	  if (__testinit || __testget)
 --- 71,77 ----
   		_M_really_overflow();
   	      else if (_M_in_cur !=3D _M_filepos)
   		_M_file.seekoff(_M_in_cur - _M_filepos,
 ! 				ios_base::cur, __testsync, ios_base::in);
   	    }
  =20
   	  if (__testinit || __testget)
 *************** namespace std=20
 *** 81,87 ****
   	      streamsize __ilen =3D 0;
  =20
   	      __elen =3D _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),=20
 ! 				      _M_buf_size, __sync);
   	      __ilen =3D __elen;
  =20
   	      if (0 < __ilen)
 --- 80,86 ----
   	      streamsize __ilen =3D 0;
  =20
   	      __elen =3D _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),=20
 ! 				      _M_buf_size, __testsync);
   	      __ilen =3D __elen;
  =20
   	      if (0 < __ilen)
 *************** namespace std=20
 *** 92,98 ****
   		  __ret =3D traits_type::to_int_type(*_M_in_cur);
   		  if (__bump)
   		    _M_in_cur_move(1);
 ! 		  else if (__sync)
   		    {
   		      // If we are synced with stdio, we have to unget the
   		      // character we just read so that the file pointer
 --- 91,97 ----
   		  __ret =3D traits_type::to_int_type(*_M_in_cur);
   		  if (__bump)
   		    _M_in_cur_move(1);
 ! 		  else if (__testsync)
   		    {
   		      // If we are synced with stdio, we have to unget the
   		      // character we just read so that the file pointer
 *************** namespace std=20
 *** 125,132 ****
         int_type __ret =3D traits_type::eof();
         const bool __testin =3D _M_mode & ios_base::in;
         const bool __testout =3D _M_mode & ios_base::out;
 !       // Sync with stdio.
 !       const bool __sync =3D _M_buf_size <=3D 1;
  =20
         if (__testin)
   	{
 --- 124,130 ----
         int_type __ret =3D traits_type::eof();
         const bool __testin =3D _M_mode & ios_base::in;
         const bool __testout =3D _M_mode & ios_base::out;
 !       const bool __testsync =3D _M_buf_size <=3D 1;
  =20
         if (__testin)
   	{
 *************** namespace std=20
 *** 154,192 ****
   		_M_really_overflow();
   	      else if (_M_in_cur !=3D _M_filepos)
   		_M_file.seekoff(_M_in_cur - _M_filepos,
 ! 				  ios_base::cur, __sync, ios_base::in);
   	    }
  =20
   	  if (__testinit || __testget)
   	    {
 - 	      const locale __loc =3D this->getloc();
 - 	      const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);=
 =20
 -=20
   	      streamsize __elen =3D 0;
   	      streamsize __ilen =3D 0;
   	      if (__cvt.always_noconv())
   		{
   		  __elen =3D _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),=20
 ! 					  _M_buf_size, __sync);
   		  __ilen =3D __elen;
   		}
   	      else
   		{
   		  char* __buf =3D static_cast<char*>(__builtin_alloca(_M_buf_size));
 ! 		  __elen =3D _M_file.xsgetn(__buf, _M_buf_size, __sync);
 !=20
   		  const char* __eend;
   		  char_type* __iend;
 ! 		  __res_type __r =3D __cvt.in(_M_state_cur, __buf,=20
 ! 					    __buf + __elen, __eend, _M_in_beg,=20
 ! 					    _M_in_beg + _M_buf_size, __iend);
   		  if (__r =3D=3D codecvt_base::ok)
   		    __ilen =3D __iend - _M_in_beg;
   		  else=20
   		    {
   		      // Unwind.
   		      __ilen =3D 0;
 ! 		      _M_file.seekoff(-__elen, ios_base::cur, __sync, ios_base::in);
   		    }
   		}
  =20
 --- 152,190 ----
   		_M_really_overflow();
   	      else if (_M_in_cur !=3D _M_filepos)
   		_M_file.seekoff(_M_in_cur - _M_filepos,
 ! 				ios_base::cur, __testsync, ios_base::in);
   	    }
  =20
   	  if (__testinit || __testget)
   	    {
   	      streamsize __elen =3D 0;
   	      streamsize __ilen =3D 0;
 + 	      const locale __loc =3D this->getloc();
 + 	      const __codecvt_type& __cvt =3D use_facet<__codecvt_type>(__loc);
   	      if (__cvt.always_noconv())
   		{
   		  __elen =3D _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),=20
 ! 					  _M_buf_size, __testsync);
   		  __ilen =3D __elen;
   		}
   	      else
   		{
   		  char* __buf =3D static_cast<char*>(__builtin_alloca(_M_buf_size));
 ! 		  __elen =3D _M_file.xsgetn(__buf, _M_buf_size, __testsync);
 ! 		 =20
   		  const char* __eend;
   		  char_type* __iend;
 ! 		  codecvt_base::result __r;
 ! 		  __r =3D __cvt.in(_M_state_cur, __buf, __buf + __elen, __eend,=20
 ! 				 _M_in_beg, _M_in_beg + _M_buf_size, __iend);
   		  if (__r =3D=3D codecvt_base::ok)
   		    __ilen =3D __iend - _M_in_beg;
   		  else=20
   		    {
   		      // Unwind.
   		      __ilen =3D 0;
 ! 		      _M_file.seekoff(-__elen, ios_base::cur, __testsync,=20
 ! 				      ios_base::in);
   		    }
   		}
  =20
 *************** namespace std=20
 *** 198,204 ****
   		  __ret =3D traits_type::to_int_type(*_M_in_cur);
   		  if (__bump)
   		    _M_in_cur_move(1);
 ! 		  else if (__sync)
   		    {
   		      // If we are synced with stdio, we have to unget the
   		      // character we just read so that the file pointer
 --- 196,202 ----
   		  __ret =3D traits_type::to_int_type(*_M_in_cur);
   		  if (__bump)
   		    _M_in_cur_move(1);
 ! 		  else if (__testsync)
   		    {
   		      // If we are synced with stdio, we have to unget the
   		      // character we just read so that the file pointer
 Index: testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc
 diff -N testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc
 *** /dev/null	1 Jan 1970 00:00:00 -0000
 --- testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc	24 Apr 2003 23:57=
 :56 -0000
 ***************
 *** 0 ****
 --- 1,54 ----
 + // 2003-04-24 P=E9tur Run=F3lfsson <peturr02@ru.is>
 + // Copyright (C) 2003 Free Software Foundation, Inc.
 + //
 + // This file is part of the GNU ISO C++ Library.  This library is free
 + // software; you can redistribute it and/or modify it under the
 + // terms of the GNU General Public License as published by the
 + // Free Software Foundation; either version 2, or (at your option)
 + // any later version.
 +=20
 + // This library is distributed in the hope that it will be useful,
 + // but WITHOUT ANY WARRANTY; without even the implied warranty of
 + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + // GNU General Public License for more details.
 +=20
 + // You should have received a copy of the GNU General Public License along
 + // with this library; see the file COPYING.  If not, write to the Free
 + // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-130=
 7,
 + // USA.
 +=20
 + #include <fstream>
 + #include <locale>
 + #include <stdexcept>
 + #include <testsuite_hooks.h>
 +=20
 + class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
 + {
 + protected:
 +   virtual std::codecvt_base::result
 +   do_out(std::mbstate_t&, const wchar_t*, const wchar_t*, const wchar_t*&=
 ,=20
 + 	 char*, char*, char*&) const
 +   { throw std::runtime_error("codecvt failed"); }
 + };
 +=20
 + int main()
 + {
 +   using namespace std;
 +   bool test =3D true;
 +=20
 +   locale loc =3D locale(locale::classic(), new Cvt);
 +   wfilebuf* fb =3D new wfilebuf;
 +   fb->pubimbue(loc);
 +   fb->open("tmp_10132", ios_base::out);
 +   fb->sputc(L'a');
 +  =20
 +   try
 +     {
 +       delete fb;
 +     }
 +   catch(exception& obj)
 +     {
 +       VERIFY( false );=20
 +     }
 +   return 0;
 + }
 Index: testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
 diff -N testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
 *** /dev/null	1 Jan 1970 00:00:00 -0000
 --- testsuite/27_io/basic_filebuf/seekoff/10132-2.cc	24 Apr 2003 23:57:56 -=
 0000
 ***************
 *** 0 ****
 --- 1,147 ----
 + // 2003-04-24 bkoz
 +=20
 + // Copyright (C) 2003 Free Software Foundation, Inc.
 + //
 + // This file is part of the GNU ISO C++ Library.  This library is free
 + // software; you can redistribute it and/or modify it under the
 + // terms of the GNU General Public License as published by the
 + // Free Software Foundation; either version 2, or (at your option)
 + // any later version.
 +=20
 + // This library is distributed in the hope that it will be useful,
 + // but WITHOUT ANY WARRANTY; without even the implied warranty of
 + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + // GNU General Public License for more details.
 +=20
 + // You should have received a copy of the GNU General Public License along
 + // with this library; see the file COPYING.  If not, write to the Free
 + // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-130=
 7,
 + // USA.
 +=20
 + // 27.8.1.1 - Template class basic_filebuf=20
 + // NB: This file is for testing basic_filebuf with NO OTHER INCLUDES.
 +=20
 + #include <fstream>
 + #include <testsuite_hooks.h>
 +=20
 + // libstdc++/10132, add on
 + class gnu_char_type
 + {
 +   unsigned long character;
 + public:
 +   // operator =3D=3D
 +   bool
 +   operator=3D=3D(const gnu_char_type& __lhs)=20
 +   { return character =3D=3D __lhs.character; }
 +=20
 +   // operator <
 +   bool
 +   operator<(const gnu_char_type& __lhs)=20
 +   { return character < __lhs.character; }
 +=20
 +   // default ctor
 +   gnu_char_type() { }
 +=20
 +   // to_char_type
 +   gnu_char_type(const unsigned long& __l) : character(__l) { }=20
 +=20
 +   // to_int_type
 +   operator unsigned long() const { return character; }
 + };
 +=20
 + // char_traits specialization
 + struct gnu_char_traits
 + {
 +   typedef gnu_char_type	char_type;
 +   typedef long  		int_type;
 +   typedef long 		pos_type;
 +   typedef unsigned long 	off_type;
 +   typedef long   		state_type;
 +  =20
 +   static void=20
 +   assign(char_type& __c1, const char_type& __c2) { }
 +  =20
 +   static bool=20
 +   eq(const char_type& __c1, const char_type& __c2) { return true; }
 +  =20
 +   static bool=20
 +   lt(const char_type& __c1, const char_type& __c2) { return true; }
 +  =20
 +   static int=20
 +   compare(const char_type* __s1, const char_type* __s2, size_t __n)
 +   { return 0; }
 +  =20
 +   static size_t
 +   length(const char_type* __s) { return 0; }
 +  =20
 +   static const char_type*=20
 +   find(const char_type* __s, size_t __n, const char_type& __a)
 +   { return __s; }
 +  =20
 +   static char_type*=20
 +   move(char_type* __s1, const char_type* __s2, size_t __n)
 +   { return __s1; }
 +  =20
 +   static char_type*=20
 +   copy(char_type* __s1, const char_type* __s2, size_t __n)
 +   { return __s1; }
 +  =20
 +   static char_type*=20
 +   assign(char_type* __s, size_t __n, char_type __a)
 +   { return __s; }
 +  =20
 +   static char_type=20
 +   to_char_type(const int_type& __c)
 +   { return char_type(); }
 +  =20
 +   static int_type=20
 +   to_int_type(const char_type& __c)
 +   { return int_type(); }
 +  =20
 +   static bool=20
 +   eq_int_type(const int_type& __c1, const int_type& __c2)
 +   { return true; }
 +  =20
 +   static int_type=20
 +   eof()
 +   { return int_type(); }
 +  =20
 +   static int_type=20
 +   not_eof(const int_type& __c)
 +   { return int_type(); }
 + };
 +=20
 + void test07()
 + {
 +   bool test =3D true;
 +   typedef std::basic_filebuf<gnu_char_type, gnu_char_traits> gnu_filebuf;
 +  =20
 +   try
 +     {=20
 +       // Need codecvt facet for width argument in seekoff.
 +       gnu_filebuf obj;
 +       obj.pubseekoff(2, std::ios_base::beg);
 +     }
 +   catch(std::exception& obj)
 +     {=20
 +       test =3D false;=20
 +       VERIFY( test );
 +     }
 + }
 +=20
 + #if !__GXX_WEAK__
 + // Explicitly instantiate for systems with no COMDAT or weak support.
 + template=20
 +   std::basic_filebuf<gnu_char_type>::int_type
 +   std::basic_filebuf<gnu_char_type>::_S_pback_size;
 + #endif
 +=20
 + int main()=20
 + {
 +   test07();
 +   return 0;
 + }
 +=20
 +=20
 +=20
 + // more surf!!!
 Index: testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
 diff -N testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
 *** /dev/null	1 Jan 1970 00:00:00 -0000
 --- testsuite/27_io/basic_filebuf/seekpos/10132-3.cc	24 Apr 2003 23:57:56 -=
 0000
 ***************
 *** 0 ****
 --- 1,147 ----
 + // 2003-04-24 bkoz
 +=20
 + // Copyright (C) 2003 Free Software Foundation, Inc.
 + //
 + // This file is part of the GNU ISO C++ Library.  This library is free
 + // software; you can redistribute it and/or modify it under the
 + // terms of the GNU General Public License as published by the
 + // Free Software Foundation; either version 2, or (at your option)
 + // any later version.
 +=20
 + // This library is distributed in the hope that it will be useful,
 + // but WITHOUT ANY WARRANTY; without even the implied warranty of
 + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + // GNU General Public License for more details.
 +=20
 + // You should have received a copy of the GNU General Public License along
 + // with this library; see the file COPYING.  If not, write to the Free
 + // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-130=
 7,
 + // USA.
 +=20
 + // 27.8.1.1 - Template class basic_filebuf=20
 + // NB: This file is for testing basic_filebuf with NO OTHER INCLUDES.
 +=20
 + #include <fstream>
 + #include <testsuite_hooks.h>
 +=20
 + // libstdc++/10132, add on
 + class gnu_char_type
 + {
 +   unsigned long character;
 + public:
 +   // operator =3D=3D
 +   bool
 +   operator=3D=3D(const gnu_char_type& __lhs)=20
 +   { return character =3D=3D __lhs.character; }
 +=20
 +   // operator <
 +   bool
 +   operator<(const gnu_char_type& __lhs)=20
 +   { return character < __lhs.character; }
 +=20
 +   // default ctor
 +   gnu_char_type() { }
 +=20
 +   // to_char_type
 +   gnu_char_type(const unsigned long& __l) : character(__l) { }=20
 +=20
 +   // to_int_type
 +   operator unsigned long() const { return character; }
 + };
 +=20
 + // char_traits specialization
 + struct gnu_char_traits
 + {
 +   typedef gnu_char_type	char_type;
 +   typedef long  		int_type;
 +   typedef long 		pos_type;
 +   typedef unsigned long 	off_type;
 +   typedef long   		state_type;
 +  =20
 +   static void=20
 +   assign(char_type& __c1, const char_type& __c2) { }
 +  =20
 +   static bool=20
 +   eq(const char_type& __c1, const char_type& __c2) { return true; }
 +  =20
 +   static bool=20
 +   lt(const char_type& __c1, const char_type& __c2) { return true; }
 +  =20
 +   static int=20
 +   compare(const char_type* __s1, const char_type* __s2, size_t __n)
 +   { return 0; }
 +  =20
 +   static size_t
 +   length(const char_type* __s) { return 0; }
 +  =20
 +   static const char_type*=20
 +   find(const char_type* __s, size_t __n, const char_type& __a)
 +   { return __s; }
 +  =20
 +   static char_type*=20
 +   move(char_type* __s1, const char_type* __s2, size_t __n)
 +   { return __s1; }
 +  =20
 +   static char_type*=20
 +   copy(char_type* __s1, const char_type* __s2, size_t __n)
 +   { return __s1; }
 +  =20
 +   static char_type*=20
 +   assign(char_type* __s, size_t __n, char_type __a)
 +   { return __s; }
 +  =20
 +   static char_type=20
 +   to_char_type(const int_type& __c)
 +   { return char_type(); }
 +  =20
 +   static int_type=20
 +   to_int_type(const char_type& __c)
 +   { return int_type(); }
 +  =20
 +   static bool=20
 +   eq_int_type(const int_type& __c1, const int_type& __c2)
 +   { return true; }
 +  =20
 +   static int_type=20
 +   eof()
 +   { return int_type(); }
 +  =20
 +   static int_type=20
 +   not_eof(const int_type& __c)
 +   { return int_type(); }
 + };
 +=20
 + void test07()
 + {
 +   bool test =3D true;
 +   typedef std::basic_filebuf<gnu_char_type, gnu_char_traits> gnu_filebuf;
 +  =20
 +   try
 +     {=20
 +       // Need codecvt facet for width argument in seekpos.
 +       gnu_filebuf obj;
 +       obj.pubseekpos(0);
 +     }
 +   catch(std::exception& obj)
 +     {=20
 +       test =3D false;=20
 +       VERIFY( test );
 +     }
 + }
 +=20
 + #if !__GXX_WEAK__
 + // Explicitly instantiate for systems with no COMDAT or weak support.
 + template=20
 +   std::basic_filebuf<gnu_char_type>::int_type
 +   std::basic_filebuf<gnu_char_type>::_S_pback_size;
 + #endif
 +=20
 + int main()=20
 + {
 +   test07();
 +   return 0;
 + }
 +=20
 +=20
 +=20
 + // more surf!!!


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-24 22:26 Benjamin Kosnik
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Kosnik @ 2003-04-24 22:26 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 17:23:48 -0500

 Actually, principle of least surprise/simplicity probably rules here. I
 suppose the library streambufs should not get in the way of possible
 exceptions, should prevent resource leaks and should instead let io bits
 or user try/catch deal with this.
 
 Let me implement 3, and come up with a filebuf::_M_close throw(). 
 
 -benjamin


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-24 22:06 Benjamin Kosnik
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Kosnik @ 2003-04-24 22:06 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 16:58:33 -0500

 >> Here's something to think about. I think this is pretty good. 
 >> Something like it will have to be done for the corresponding 
 >> underflow bits.
 >
 >Maybe I'm missing something, but how does this fix the bug if
 >some exceptions are rethrown?
 
 In that exceptional case, there would still be a bug. It's still better
 than what's going on now.
 
 >Also, what's the rationale behind rethrowing some but not all
 >exceptions?
 
 Why would you propogate when the the exception can be cleaned up at the
 point of failure? If something that this function is not prepared to
 deal with happens, then it can rethrow.
 
 >I don't think that basic_filebuf should catch exceptions thrown
 >by use_facet or codecvt members. 
 
 Why?
 
 >It is clear from 27.6.2.1 etc. that streambuf members may throw;
 
 Yes. That's not what the issue is, however.
 
 I see three ways to fix this.
 
 1) make non-virtual codecvt MF's throw(), wrap all virtual calls with
 try, and in the catch block return codecvt_base::error.
 
 2) try/catch in filebuf::~filebuf. The problem with this is that the
 "cleanups" are quite difficult to do in ~filebuf if filebuf::close
 fails, and we will end up either duplicating a bunch of filbuf::close,
 or leaking memory.
 
 3) try to deal with the codecvt errors at the point of usage, ie in
 underflow/overflow. I think this makes the most sense.
 
 -benjamin


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-24 18:56 Pétur Runólfsson
  0 siblings, 0 replies; 13+ messages in thread
From: Pétur Runólfsson @ 2003-04-24 18:56 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: =?iso-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
To: "Benjamin Kosnik" <bkoz@redhat.com>
Cc: <gcc-bugs@gcc.gnu.org>,
	<gcc-gnats@gcc.gnu.org>
Subject: RE: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 18:48:06 -0000

 > Here's something to think about. I think this is pretty good.=20
 > Something like it will have to be done for the corresponding=20
 > underflow bits.
 
 Maybe I'm missing something, but how does this fix the bug if
 some exceptions are rethrown?
 
 Also, what's the rationale behind rethrowing some but not all
 exceptions?
 
 I don't think that basic_filebuf should catch exceptions thrown
 by use_facet or codecvt members. It is clear from 27.6.2.1 etc.
 that streambuf members may throw; if underflow() fails because
 an exception is thrown badbit, not eofbit, should be set in
 rdstate(); and if badbit is set in exceptions() the original
 exception should be rethrown.
 
 Petur
 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-24  6:06 Benjamin Kosnik
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Kosnik @ 2003-04-24  6:06 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 01:05:21 -0500

 Here's something to think about. I think this is pretty good. Something
 like it will have to be done for the corresponding underflow bits.
 
 -benjamin
 
 2003-04-24  Benjamin Kosnik  <bkoz@redhat.com>
 
 	PR libstdc++/10132
 	* include/std/std_fstream.h (basic_filebuf): Remove __res_type
 	typedef.	
 	* src/fstream.cc: Same.
 	* include/bits/fstream.tcc
 	(basic_filebuf::_M_convert_to_external): Simplify. Add try/catch
 	blocks.
 
 Index: include/bits/fstream.tcc
 ===================================================================
 RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
 retrieving revision 1.65
 diff -c -p -r1.65 fstream.tcc
 *** include/bits/fstream.tcc	22 Apr 2003 17:32:25 -0000	1.65
 --- include/bits/fstream.tcc	24 Apr 2003 05:59:23 -0000
 *************** namespace std
 *** 283,353 ****
       _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
   			   streamsize& __elen, streamsize& __plen)
       {
 !       const locale __loc = this->getloc();
 !       const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
 !       // Sync with stdio.
 !       const bool __sync = this->_M_buf_size <= 1;
 ! 
 !       if (__cvt.always_noconv() && __ilen)
 ! 	{
 ! 	  __elen +=
 ! 	    _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen, __sync);
 ! 	  __plen += __ilen;
 ! 	}
 !       else
   	{
 ! 	  // Worst-case number of external bytes needed.
 ! 	  int __ext_multiplier = __cvt.encoding();
 ! 	  if (__ext_multiplier ==  -1 || __ext_multiplier == 0)
 ! 	    __ext_multiplier = sizeof(char_type);
 ! 	  streamsize __blen = __ilen * __ext_multiplier;
 ! 	  char* __buf = static_cast<char*>(__builtin_alloca(__blen));
 ! 	  char* __bend;
 ! 	  const char_type* __iend;
 ! 	  __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, 
 ! 		 		     __iend, __buf, __buf + __blen, __bend);
 ! 
 ! 	  if (__r == codecvt_base::ok || __r == codecvt_base::partial)
 ! 	    __blen = __bend - __buf;
 ! 	  // Similarly to the always_noconv case above.
 ! 	  else if (__r == codecvt_base::noconv)
 ! 	    {
 ! 	      __buf = reinterpret_cast<char*>(__ibuf);
 ! 	      __blen = __ilen;
 ! 	    }
 ! 	  // Result == error
 ! 	  else 
 ! 	    __blen = 0;
 ! 	  
 ! 	  if (__blen)
   	    {
 ! 	      __elen += _M_file.xsputn(__buf, __blen, __sync);
 ! 	      __plen += __blen;
   	    }
 ! 
 ! 	  // Try once more for partial conversions.
 ! 	  if (__r == codecvt_base::partial)
   	    {
 ! 	      const char_type* __iresume = __iend;
 ! 	      streamsize __rlen = this->_M_out_lim - __iend;
 ! 	      __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, 
   			      __iend, __buf, __buf + __blen, __bend);
 ! 	      if (__r != codecvt_base::error)
 ! 		__rlen = __bend - __buf;
   	      else
   		{
 ! 		  __rlen = 0;
 ! 		  // Signal to the caller (_M_really_overflow) that
 ! 		  // codecvt::out eventually failed.
 ! 		  __elen = 0;		  
   		}
 ! 	      if (__rlen)
   		{
 ! 		  __elen += _M_file.xsputn(__buf, __rlen, __sync);
 ! 		  __plen += __rlen;
   		}
   	    }
   	}
       }
   
     template<typename _CharT, typename _Traits>
 --- 283,357 ----
       _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
   			   streamsize& __elen, streamsize& __plen)
       {
 !       try
   	{
 ! 	  // Sync with stdio.
 ! 	  const bool __sync = this->_M_buf_size <= 1;
 ! 	  const locale __loc = this->getloc();
 ! 	  const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
 ! 
 ! 	  if (__cvt.always_noconv() && __ilen)
   	    {
 ! 	      __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), 
 ! 				       __ilen, __sync);
 ! 	      __plen += __ilen;
   	    }
 ! 	  else
   	    {
 ! 	      // Worst-case number of external bytes needed.
 ! 	      int __ext_multiplier = __cvt.encoding();
 ! 	      if (__ext_multiplier ==  -1 || __ext_multiplier == 0)
 ! 		__ext_multiplier = sizeof(char_type);
 ! 	      streamsize __blen = __ilen * __ext_multiplier;
 ! 	      char* __buf = static_cast<char*>(__builtin_alloca(__blen));
 ! 	      char* __bend;
 ! 	      const char_type* __iend;
 ! 	      codecvt_base::result __r;
 ! 	      __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
   			      __iend, __buf, __buf + __blen, __bend);
 ! 
 ! 	      if (__r == codecvt_base::ok || __r == codecvt_base::partial)
 ! 		__blen = __bend - __buf;
 ! 	      else if (__r == codecvt_base::noconv)
 ! 		{
 ! 		  // Same as the always_noconv case above.
 ! 		  __buf = reinterpret_cast<char*>(__ibuf);
 ! 		  __blen = __ilen;
 ! 		}
   	      else
   		{
 ! 		  // Result == error 
 ! 		  __blen = 0;
   		}
 ! 	  
 ! 	      if (__blen)
   		{
 ! 		  __elen += _M_file.xsputn(__buf, __blen, __sync);
 ! 		  __plen += __blen;
 ! 		}
 ! 
 ! 	      // Try once more for partial conversions.
 ! 	      if (__r == codecvt_base::partial)
 ! 		{
 ! 		  const char_type* __iresume = __iend;
 ! 		  streamsize __rlen = this->_M_out_lim - __iend;
 ! 		  __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, 
 ! 				  __iend, __buf, __buf + __blen, __bend);
 ! 		  if (__r != codecvt_base::error)
 ! 		    {
 ! 		      __rlen = __bend - __buf;
 ! 		      __elen += _M_file.xsputn(__buf, __rlen, __sync);
 ! 		      __plen += __rlen;
 ! 		    }
   		}
   	    }
   	}
 +       catch(...)
 + 	{
 + 	  // Something went wrong with the conversion.
 + 	  if (__elen && __elen == __plen)
 + 	    __throw_exception_again;
 + 	}
       }
   
     template<typename _CharT, typename _Traits>
 *************** namespace std
 *** 394,400 ****
   		  char_type __pending = traits_type::to_char_type(__c);
   		  _M_convert_to_external(&__pending, 1, __elen, __plen);
   
 ! 		  // User code must flush when switching modes (thus don't sync).
   		  if (__elen == __plen && __elen)
   		    {
   		      _M_set_indeterminate();
 --- 398,405 ----
   		  char_type __pending = traits_type::to_char_type(__c);
   		  _M_convert_to_external(&__pending, 1, __elen, __plen);
   
 ! 		  // User code must flush when switching modes (thus
 ! 		  // don't sync).
   		  if (__elen == __plen && __elen)
   		    {
   		      _M_set_indeterminate();
 Index: include/std/std_fstream.h
 ===================================================================
 RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_fstream.h,v
 retrieving revision 1.29
 diff -c -p -r1.29 std_fstream.h
 *** include/std/std_fstream.h	22 Apr 2003 17:32:25 -0000	1.29
 --- include/std/std_fstream.h	24 Apr 2003 05:59:24 -0000
 *************** namespace std
 *** 81,87 ****
         typedef __basic_file<char>		        __file_type;
         typedef typename traits_type::state_type          __state_type;
         typedef codecvt<char_type, char, __state_type>    __codecvt_type;
 -       typedef typename __codecvt_type::result 	        __res_type;
         typedef ctype<char_type>                          __ctype_type;
         //@}
   
 --- 81,86 ----
 Index: src/fstream.cc
 ===================================================================
 RCS file: /cvs/gcc/gcc/libstdc++-v3/src/fstream.cc,v
 retrieving revision 1.8
 diff -c -p -r1.8 fstream.cc
 *** src/fstream.cc	20 Apr 2003 13:54:45 -0000	1.8
 --- src/fstream.cc	24 Apr 2003 05:59:25 -0000
 *************** namespace std 
 *** 177,192 ****
   
   		  const char* __eend;
   		  char_type* __iend;
 ! 		  __res_type __r = __cvt.in(_M_state_cur, __buf, 
 ! 					    __buf + __elen, __eend, _M_in_beg, 
 ! 					    _M_in_beg + _M_buf_size, __iend);
   		  if (__r == codecvt_base::ok)
   		    __ilen = __iend - _M_in_beg;
   		  else 
   		    {
   		      // Unwind.
   		      __ilen = 0;
 ! 		      _M_file.seekoff(-__elen, ios_base::cur, __sync, ios_base::in);
   		    }
   		}
   
 --- 177,194 ----
   
   		  const char* __eend;
   		  char_type* __iend;
 ! 		  codecvt_base::result __r;
 ! 		  __r = __cvt.in(_M_state_cur, 
 ! 				 __buf, __buf + __elen, __eend, 
 ! 				 _M_in_beg, _M_in_beg + _M_buf_size, __iend);
   		  if (__r == codecvt_base::ok)
   		    __ilen = __iend - _M_in_beg;
   		  else 
   		    {
   		      // Unwind.
   		      __ilen = 0;
 ! 		      _M_file.seekoff(-__elen, ios_base::cur, __sync, 
 ! 				      ios_base::in);
   		    }
   		}
   


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-24  6:06 Benjamin Kosnik
  0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Kosnik @ 2003-04-24  6:06 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 01:04:02 -0500

 >This is disallowed by the resolution to DR 119. It won't
 >fix the problem either since the destructor calls other
 >functions that may throw (use_facet).
 
 Right.
 
 >I believe user-defined facets are allowed to throw anything
 >they choose, whenever they choose from those members
 >without throw specs, and that the iostream library should
 >be prepared to deal with this.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-23  8:56 Pétur Runólfsson
  0 siblings, 0 replies; 13+ messages in thread
From: Pétur Runólfsson @ 2003-04-23  8:56 UTC (permalink / raw)
  To: bkoz; +Cc: gcc-prs

The following reply was made to PR libstdc++/10132; it has been noted by GNATS.

From: =?iso-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
To: <bkoz@gcc.gnu.org>,
	<gcc-bugs@gcc.gnu.org>,
	=?iso-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>,
	<gcc-gnats@gcc.gnu.org>
Cc:  
Subject: RE: libstdc++/10132: filebuf destructor throws exceptions
Date: Wed, 23 Apr 2003 08:48:52 -0000

 >     This is in violation of 17.4.4.8.
 
 Yes.
 
 >     I'm thinking about adding throw() exception=20
 > specifications to codecvt member funtions. This could be=20
 > considered a tightening of exception specs, which is allowed=20
 > in 17.4.4.8 p1 (although I remember some noise when the=20
 > proposal to add throw() to dtors was suggested.)
 
 This is disallowed by the resolution to DR 119. It won't
 fix the problem either since the destructor calls other
 functions that may throw (use_facet).
 
 > That should=20
 > at least make the locale::facet policy on error reporting=20
 > (22.2 - Standard locale categories p 2) clear, even though it=20
 > won't necessarily remove the issue.
 
 It is clear, facets may throw any exceptions (except from those
 members with throw() specs).
 
 >     To remove it completely, I'd have to do a try around the=20
 > close() call in basic_filebuf::~basic_filebuf(). And what=20
 > should happen in the catch?=20
 
 Probably just clean up and return.
 
 >     I believe the theory of error handling in the design of=20
 > the io classes is that basic_ios/basic_istream/basic_ostream=20
 > throw, catch, and propogate exceptions. The streambuf classes=20
 > just return eof/-1 (showmanyc, pbackfail, seekoff, seekpos)=20
 > or NULL (open, close) to report errors.
 
 See 17.4.4.8 p3. All streambuf/filebuf members except the
 destructor may throw exceptions of any type. Since the
 standard doesn't require streambuf/filebuf members to catch
 exceptions, I would expect them to propagate.
 
 >     The problem is the intersection of std::locale, which can=20
 > throw on construction (locale(const char*), combine) and=20
 > whenever a use_facet is used. Facets, as above, in practice=20
 > use iostate or some other mechanism to report errors.
 
 Some facets do. Others (like codecvt or the *_put facets)
 don't.
 
 > Although, nothing (except exception-saftey paradoxes) keeps=20
 > derived/user-defined classes from doing this.
 
 I believe user-defined facets are allowed to throw anything
 they choose, whenever they choose from those members
 without throw specs, and that the iostream library should
 be prepared to deal with this.
 
 Petur


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-23  3:47 bkoz
  0 siblings, 0 replies; 13+ messages in thread
From: bkoz @ 2003-04-23  3:47 UTC (permalink / raw)
  To: bkoz, gcc-bugs, gcc-prs, peturr02

Synopsis: filebuf destructor throws exceptions

State-Changed-From-To: analyzed->feedback
State-Changed-By: bkoz
State-Changed-When: Wed Apr 23 03:47:05 2003
State-Changed-Why:
    This is in violation of 17.4.4.8.
    
    I'm thinking about adding throw() exception specifications to codecvt member funtions. This could be considered a tightening of exception specs, which is allowed in 17.4.4.8 p1 (although I remember some noise when the proposal to add throw() to dtors was suggested.) That should at least make the locale::facet policy on error reporting (22.2 - Standard locale categories p 2) clear, even though it won't necessarily remove the issue.
    
    To remove it completely, I'd have to do a try around the close() call in basic_filebuf::~basic_filebuf(). And what should happen in the catch? 
    
    I believe the theory of error handling in the design of the io classes is that basic_ios/basic_istream/basic_ostream throw, catch, and propogate exceptions. The streambuf classes just return eof/-1 (showmanyc, pbackfail, seekoff, seekpos) or NULL (open, close) to report errors. 
    
    The problem is the intersection of std::locale, which can throw on construction (locale(const char*), combine) and whenever a use_facet is used. Facets, as above, in practice use iostate or some other mechanism to report errors. Although, nothing (except exception-saftey paradoxes) keeps derived/user-defined classes from doing this.
    
    -benjamin

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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: libstdc++/10132: filebuf destructor throws exceptions
@ 2003-04-22  1:08 bkoz
  0 siblings, 0 replies; 13+ messages in thread
From: bkoz @ 2003-04-22  1:08 UTC (permalink / raw)
  To: bkoz, gcc-bugs, gcc-prs, nobody, peturr02

Synopsis: filebuf destructor throws exceptions

Responsible-Changed-From-To: unassigned->bkoz
Responsible-Changed-By: bkoz
Responsible-Changed-When: Tue Apr 22 01:08:17 2003
Responsible-Changed-Why:
    Mine.
State-Changed-From-To: open->analyzed
State-Changed-By: bkoz
State-Changed-When: Tue Apr 22 01:08:17 2003
State-Changed-Why:
    confirmed.

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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* libstdc++/10132: filebuf destructor throws exceptions
@ 2003-03-18 12:16 peturr02
  0 siblings, 0 replies; 13+ messages in thread
From: peturr02 @ 2003-03-18 12:16 UTC (permalink / raw)
  To: gcc-gnats


>Number:         10132
>Category:       libstdc++
>Synopsis:       filebuf destructor throws exceptions
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Mar 18 12:16:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     peturr02@ru.is
>Release:        gcc-3.2.2
>Organization:
>Environment:
Red Hat Linux 8.0
>Description:
The destructor of basic_filebuf calls basic_filebuf::close() without handling exceptions thrown by that function (close() calls use_facet and codecvt::out(), both of which may throw).
>How-To-Repeat:
See attachment.
>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="dtorbug.cc"
Content-Disposition: inline; filename="dtorbug.cc"

#include <fstream>
#include <locale>
#include <cwchar>

#undef NDEBUG
#include <cassert>

class MyEx
{
};

class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
{
protected:
	virtual std::codecvt_base::result
	do_out(std::mbstate_t&, const wchar_t*, const wchar_t*,
	       const wchar_t*&, char*, char*, char*&) const
		{
			throw MyEx();
		}
};

int main()
{
	using namespace std;

	locale loc;
	loc = locale(loc, new Cvt);
	
	wfilebuf* fb = new wfilebuf;
	fb->pubimbue(loc);
	fb->open("tmp", ios_base::out);
	fb->sputc(L'a');
	
	try
	{
		delete fb;
	}
	catch (...)
	{
		assert(false);
	}

	return 0;
}


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2003-04-28 16:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-25 21:56 libstdc++/10132: filebuf destructor throws exceptions Pétur Runólfsson
  -- strict thread matches above, loose matches on Subject: below --
2003-04-28 16:00 bkoz
2003-04-25 21:46 Pétur Runólfsson
2003-04-25  0:56 Benjamin Kosnik
2003-04-24 22:26 Benjamin Kosnik
2003-04-24 22:06 Benjamin Kosnik
2003-04-24 18:56 Pétur Runólfsson
2003-04-24  6:06 Benjamin Kosnik
2003-04-24  6:06 Benjamin Kosnik
2003-04-23  8:56 Pétur Runólfsson
2003-04-23  3:47 bkoz
2003-04-22  1:08 bkoz
2003-03-18 12:16 peturr02

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).