From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9042 invoked by alias); 24 Apr 2003 06:06:02 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 8951 invoked by uid 71); 24 Apr 2003 06:06:02 -0000 Date: Thu, 24 Apr 2003 06:06:00 -0000 Message-ID: <20030424060602.8949.qmail@sources.redhat.com> To: bkoz@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org, From: Benjamin Kosnik Subject: Re: libstdc++/10132: filebuf destructor throws exceptions Reply-To: Benjamin Kosnik X-SW-Source: 2003-04/txt/msg01021.txt.bz2 List-Id: The following reply was made to PR libstdc++/10132; it has been noted by GNATS. From: Benjamin Kosnik To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= 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 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(__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(__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(__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 --- 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(__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(__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(__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 *************** 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 __file_type; typedef typename traits_type::state_type __state_type; typedef codecvt __codecvt_type; - typedef typename __codecvt_type::result __res_type; typedef ctype __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); } }