https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81964
On Thu, 24 Aug 2017 11:55:58 +0300 Petr Ovtchenkov <p...@void-ptr.info> wrote: > istream_iterator do unexpected read from stream > when initialized by istream&. > > It is not required from increment operators of istream_iterator > that _M_ok will be true as precondition. > --- > libstdc++-v3/include/bits/stream_iterator.h | 19 +++++----- > .../24_iterators/istream_iterator/81964.cc | 42 > ++++++++++++++++++++++ > 2 files changed, 50 insertions(+), 11 deletions(-) > create mode 100644 > libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc > > diff --git a/libstdc++-v3/include/bits/stream_iterator.h > b/libstdc++-v3/include/bits/stream_iterator.h index f9c6ba6..26959ce 100644 > --- a/libstdc++-v3/include/bits/stream_iterator.h > +++ b/libstdc++-v3/include/bits/stream_iterator.h > @@ -56,8 +56,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > private: > istream_type* _M_stream; > - _Tp _M_value; > - bool _M_ok; > + mutable _Tp _M_value; > + mutable bool _M_ok; > > public: > /// Construct end of input stream iterator. > @@ -66,8 +66,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > /// Construct start of input stream iterator. > istream_iterator(istream_type& __s) > - : _M_stream(&__s) > - { _M_read(); } > + : _M_stream(&__s), _M_value(), _M_ok(false) > + { } > > istream_iterator(const istream_iterator& __obj) > : _M_stream(__obj._M_stream), _M_value(__obj._M_value), > @@ -77,6 +77,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > const _Tp& > operator*() const > { > + if (!_M_ok) { > + _M_read(); > + } > __glibcxx_requires_cond(_M_ok, > _M_message(__gnu_debug::__msg_deref_istream) > ._M_iterator(*this)); > @@ -89,9 +92,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > istream_iterator& > operator++() > { > - __glibcxx_requires_cond(_M_ok, > - _M_message(__gnu_debug::__msg_inc_istream) > - ._M_iterator(*this)); > _M_read(); > return *this; > } > @@ -99,9 +99,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > istream_iterator > operator++(int) > { > - __glibcxx_requires_cond(_M_ok, > - _M_message(__gnu_debug::__msg_inc_istream) > - ._M_iterator(*this)); > istream_iterator __tmp = *this; > _M_read(); > return __tmp; > @@ -113,7 +110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > private: > void > - _M_read() > + _M_read() const > { > _M_ok = (_M_stream && *_M_stream) ? true : false; > if (_M_ok) > diff --git a/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc > b/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc new file mode > 100644 > index 0000000..f58fc87 > --- /dev/null > +++ b/libstdc++-v3/testsuite/24_iterators/istream_iterator/81964.cc > @@ -0,0 +1,42 @@ > +// { dg-options "-std=gnu++11" } > + > +// Copyright (C) 2017 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 3, or (at your option) > +// any later version. > + > +// 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. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > +#include <sstream> > +#include <iterator> > +#include <testsuite_hooks.h> > + > +// libstdc++/81964 > +void test0x() > +{ > + using namespace std; > + bool test __attribute__((unused)) = true; > + > + std::istringstream s("1 2"); > + std::istream_iterator<int> ii1(s); > + std::istream_iterator<int> ii2(s); > + > + VERIFY( *ii2 == 1 ); > + VERIFY( *ii1 == 2 ); > +} > + > +int main() > +{ > + test0x(); > + return 0; > +} > -- > 2.10.1 >