This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] libstdc++/5280, take two
- From: Benjamin Kosnik <bkoz at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 29 Apr 2002 23:57:26 -0700
- Subject: [v3] libstdc++/5280, take two
Ouch. std::istreambuf_iterators weren't invalidating on eof().
tested x86/linux
tested alpha/linux
gcc
gcc-3_1-branch
2002-04-29 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/5280
* include/bits/fstream.tcc (basic_filebuf::_M_underflow_common):
Check for eof.
* include/bits/streambuf_iterator.h: Match stream_iterator.h.
(istreambuf_iterator::operator++): Invalidate on eof.
(istreambuf_iterator::operator++(int)): Same.
(istreambuf_iterator::operator*): Same.
Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.34
diff -c -p -r1.34 fstream.tcc
*** include/bits/fstream.tcc 29 Apr 2002 07:00:46 -0000 1.34
--- include/bits/fstream.tcc 30 Apr 2002 06:48:26 -0000
*************** namespace std
*** 227,237 ****
// Check for unbuffered stream.
if (_M_buf_size == 1)
{
! __ret = _M_file.sys_getc();
! *_M_in_cur = traits_type::to_char_type(__ret);
! _M_set_determinate(1);
! if (__testout)
! _M_out_cur = _M_in_cur;
return __ret;
}
--- 227,241 ----
// Check for unbuffered stream.
if (_M_buf_size == 1)
{
! int_type __c = _M_file.sys_getc();
! if (__c != __ret)
! {
! __ret = __c;
! *_M_in_cur = traits_type::to_char_type(__c);
! _M_set_determinate(1);
! if (__testout)
! _M_out_cur = _M_in_cur;
! }
return __ret;
}
Index: include/bits/streambuf_iterator.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/streambuf_iterator.h,v
retrieving revision 1.5
diff -c -p -r1.5 streambuf_iterator.h
*** include/bits/streambuf_iterator.h 16 Jan 2002 19:57:31 -0000 1.5
--- include/bits/streambuf_iterator.h 30 Apr 2002 06:48:26 -0000
***************
*** 1,6 ****
// Streambuf iterators
! // Copyright (C) 1997, 1998, 1999, 2000, 2001 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
--- 1,7 ----
// Streambuf iterators
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
! // 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
***************
*** 41,100 ****
namespace std
{
- template<typename _CharT, typename _Traits>
- class ostreambuf_iterator
- : public iterator<output_iterator_tag, void, void, void, void>
- {
- public:
- // Types:
- typedef _CharT char_type;
- typedef _Traits traits_type;
- typedef basic_streambuf<_CharT, _Traits> streambuf_type;
- typedef basic_ostream<_CharT, _Traits> ostream_type;
-
- private:
- streambuf_type* _M_sbuf;
- bool _M_failed;
-
- public:
- inline
- ostreambuf_iterator(ostream_type& __s) throw ()
- : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
-
- ostreambuf_iterator(streambuf_type* __s) throw ()
- : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
-
- ostreambuf_iterator&
- operator=(_CharT __c);
-
- ostreambuf_iterator&
- operator*() throw()
- { return *this; }
-
- ostreambuf_iterator&
- operator++(int) throw()
- { return *this; }
-
- ostreambuf_iterator&
- operator++() throw()
- { return *this; }
-
- bool
- failed() const throw()
- { return _M_failed; }
- };
-
- template<typename _CharT, typename _Traits>
- inline ostreambuf_iterator<_CharT, _Traits>&
- ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c)
- {
- if (!_M_failed &&
- _Traits::eq_int_type(_M_sbuf->sputc(__c),_Traits::eof()))
- _M_failed = true;
- return *this;
- }
-
-
// 24.5.3 Template class istreambuf_iterator
template<typename _CharT, typename _Traits>
class istreambuf_iterator
--- 42,47 ----
*************** namespace std
*** 117,128 ****
// the "end of stream" iterator value.
// NB: This implementation assumes the "end of stream" value
// is EOF, or -1.
! streambuf_type* _M_sbuf;
int_type _M_c;
public:
istreambuf_iterator() throw()
! : _M_sbuf(NULL), _M_c(-2) { }
istreambuf_iterator(istream_type& __s) throw()
: _M_sbuf(__s.rdbuf()), _M_c(-2) { }
--- 64,75 ----
// the "end of stream" iterator value.
// NB: This implementation assumes the "end of stream" value
// is EOF, or -1.
! mutable streambuf_type* _M_sbuf;
int_type _M_c;
public:
istreambuf_iterator() throw()
! : _M_sbuf(0), _M_c(-2) { }
istreambuf_iterator(istream_type& __s) throw()
: _M_sbuf(__s.rdbuf()), _M_c(-2) { }
*************** namespace std
*** 137,158 ****
operator*() const
{
// The result of operator*() on an end of stream is undefined.
! char_type __ret;
! if (_M_sbuf && _M_c != static_cast<int_type>(-2))
! __ret = _M_c;
! else if (_M_sbuf)
! __ret = traits_type::to_char_type(_M_sbuf->sgetc());
! else
! __ret = static_cast<char_type>(traits_type::eof());
! return __ret;
}
istreambuf_iterator&
operator++()
{
! if (_M_sbuf)
! _M_sbuf->sbumpc();
! _M_c = -2;
return *this;
}
--- 84,108 ----
operator*() const
{
// The result of operator*() on an end of stream is undefined.
! int_type __ret = traits_type::eof();
! if (_M_sbuf)
! {
! if (_M_c != static_cast<int_type>(-2))
! __ret = _M_c;
! else
! if ((__ret = _M_sbuf->sgetc()) == traits_type::eof())
! _M_sbuf = 0;
! }
! return traits_type::to_char_type(__ret);
}
istreambuf_iterator&
operator++()
{
! if (_M_sbuf && _M_sbuf->sbumpc() == traits_type::eof())
! _M_sbuf = 0;
! else
! _M_c = -2;
return *this;
}
*************** namespace std
*** 160,189 ****
operator++(int)
{
istreambuf_iterator __old = *this;
! if (_M_sbuf)
! __old._M_c = _M_sbuf->sbumpc();
! _M_c = -2;
return __old;
}
- bool
- equal(const istreambuf_iterator& __b)
- {
- int_type __eof = traits_type::eof();
- bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
- bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
- return (__thiseof && __beof || (!__thiseof && !__beof));
- }
-
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 110 istreambuf_iterator::equal not const
// NB: there is also number 111 (NAD, Future) pending on this function.
bool
equal(const istreambuf_iterator& __b) const
{
! int_type __eof = traits_type::eof();
! bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
! bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
return (__thiseof && __beof || (!__thiseof && !__beof));
}
#endif
--- 110,131 ----
operator++(int)
{
istreambuf_iterator __old = *this;
! if (_M_sbuf && (__old._M_c = _M_sbuf->sbumpc()) == traits_type::eof())
! _M_sbuf = 0;
! else
! _M_c = -2;
return __old;
}
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 110 istreambuf_iterator::equal not const
// NB: there is also number 111 (NAD, Future) pending on this function.
bool
equal(const istreambuf_iterator& __b) const
{
! const int_type __eof = traits_type::eof();
! bool __thiseof = traits_type::eq_int_type(this->operator*(), __eof);
! bool __beof = traits_type::eq_int_type(__b.operator*(), __eof);
return (__thiseof && __beof || (!__thiseof && !__beof));
}
#endif
*************** namespace std
*** 200,204 ****
--- 142,199 ----
operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
const istreambuf_iterator<_CharT, _Traits>& __b)
{ return !__a.equal(__b); }
+
+ template<typename _CharT, typename _Traits>
+ class ostreambuf_iterator
+ : public iterator<output_iterator_tag, void, void, void, void>
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+ typedef basic_streambuf<_CharT, _Traits> streambuf_type;
+ typedef basic_ostream<_CharT, _Traits> ostream_type;
+
+ private:
+ streambuf_type* _M_sbuf;
+ bool _M_failed;
+
+ public:
+ inline
+ ostreambuf_iterator(ostream_type& __s) throw ()
+ : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
+
+ ostreambuf_iterator(streambuf_type* __s) throw ()
+ : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
+
+ ostreambuf_iterator&
+ operator=(_CharT __c);
+
+ ostreambuf_iterator&
+ operator*() throw()
+ { return *this; }
+
+ ostreambuf_iterator&
+ operator++(int) throw()
+ { return *this; }
+
+ ostreambuf_iterator&
+ operator++() throw()
+ { return *this; }
+
+ bool
+ failed() const throw()
+ { return _M_failed; }
+ };
+
+ template<typename _CharT, typename _Traits>
+ inline ostreambuf_iterator<_CharT, _Traits>&
+ ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c)
+ {
+ if (!_M_failed &&
+ _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
+ _M_failed = true;
+ return *this;
+ }
} // namespace std
#endif