public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
From: "François Dumont" <frs.dumont@gmail.com>
To: libstdc++@gcc.gnu.org, gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] streambuf_iterator: avoid debug-dependent behaviour
Date: Thu, 07 Sep 2017 21:02:00 -0000	[thread overview]
Message-ID: <86fe822c-96c0-1167-68d9-d79729f3dec5@gmail.com> (raw)
In-Reply-To: <20170901091037.GW4582@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2218 bytes --]

Hi

Following this report I had a closer look to this debug-dependent 
behavior which I agree about.

I have added some checks to 2.cc as shown in the patch. Initially the 
test was failing because:
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc:45: 
void test02(): Assertion 'old != istrb_eos' failed.

This was coming from the __old._M_c = _M_sbuf->sbumpc() line in the 
post-increment operator. The post-increment is supposed to return a copy 
of the current iterator which this assignment is compromising. So I try 
to remove the assignment and test failed later:

/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc:104: 
void test02(): Assertion 'c == slit01[i]' failed.

However, run in debug mode, it worked fine.

The test is failing in normal mode because the iterator instantiation 
doesn't read the streambuf and without the previous __old._M_c 
assignment _M_c is still pointing to eos. In debug mode, _M_at_eof() 
initialize the iterator and so it work nicely.

So for those reasons I would like to propose attached patch. 
Additionally it gets rid of the mutable usage. And I also remove a 
useless noexcept qualification on the defaulted copy constructor.

François

On 01/09/2017 11:10, Jonathan Wakely wrote:
> On 24/08/17 12:57 +0300, Petr Ovtchenkov wrote:
>> Explicit do sgetc from associated streambuf. Avoid debug-dependent
>> sgetc (within _M_at_eof()):
>>
>>       __glibcxx_requires_cond(!_M_at_eof(),
>> _M_message(__gnu_debug::__msg_inc_istreambuf)
>>                               ._M_iterator(*this));
>>
>> Increment operators not require not-eof precoditions.
>>
>> Don't unlink associated streambuf if eof detected (in _M_get).
>>
>> Clean logic in postfix increment operator.
>
> I find it very hard to understand the reasons for this patch. What
> you've written above is too terse for me.
>
> Are you fixing a bug? If so, do you have a testcase that demonstrates
> the problem, and is fixed by these changes?
>
> Is this just refactoring, without changing behaviour?
>
> Finally, and very importantly, do you have a copyright assignment for
> changes to GCC? See https://gcc.gnu.org/contribute.html#legal
>
>
>


[-- Attachment #2: istreambuf_iterator.patch --]
[-- Type: text/x-patch, Size: 5166 bytes --]

diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index f0451b1..27d0725 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -94,8 +94,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // the "end of stream" iterator value.
       // NB: This implementation assumes the "end of stream" value
       // is EOF, or -1.
-      mutable streambuf_type*	_M_sbuf;
-      mutable int_type		_M_c;
+      streambuf_type*	_M_sbuf;
+      int_type		_M_c;
 
     public:
       ///  Construct end of input stream iterator.
@@ -103,18 +103,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_sbuf(0), _M_c(traits_type::eof()) { }
 
 #if __cplusplus >= 201103L
-      istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
+      istreambuf_iterator(const istreambuf_iterator&) = default;
 
       ~istreambuf_iterator() = default;
 #endif
 
       ///  Construct start of input stream iterator.
       istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
-      : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
+      : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof())
+      {
+	if (_M_sbuf)
+	  _M_get();
+      }
 
       ///  Construct start of streambuf iterator.
       istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
-      : _M_sbuf(__s), _M_c(traits_type::eof()) { }
+      : _M_sbuf(__s), _M_c(traits_type::eof())
+      {
+	if (_M_sbuf)
+	  _M_get();
+      }
 
       ///  Return the current character pointed to by iterator.  This returns
       ///  streambuf.sgetc().  It cannot be assigned.  NB: The result of
@@ -122,28 +130,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       char_type
       operator*() const
       {
+	int_type __c = _M_get();
+
 #ifdef _GLIBCXX_DEBUG_PEDANTIC
 	// Dereferencing a past-the-end istreambuf_iterator is a
 	// libstdc++ extension
-	__glibcxx_requires_cond(!_M_at_eof(),
+	__glibcxx_requires_cond(!_S_at_eof(__c),
 				_M_message(__gnu_debug::__msg_deref_istreambuf)
 				._M_iterator(*this));
 #endif
-	return traits_type::to_char_type(_M_get());
+	return traits_type::to_char_type(__c);
       }
 
       /// Advance the iterator.  Calls streambuf.sbumpc().
       istreambuf_iterator&
       operator++()
       {
-	__glibcxx_requires_cond(!_M_at_eof(),
+	__glibcxx_requires_cond(_M_sbuf,
 				_M_message(__gnu_debug::__msg_inc_istreambuf)
 				._M_iterator(*this));
-	if (_M_sbuf)
-	  {
-	    _M_sbuf->sbumpc();
-	    _M_c = traits_type::eof();
-	  }
+	_M_sbuf->sbumpc();
+	_M_get();
 	return *this;
       }
 
@@ -151,16 +158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       istreambuf_iterator
       operator++(int)
       {
-	__glibcxx_requires_cond(!_M_at_eof(),
-				_M_message(__gnu_debug::__msg_inc_istreambuf)
-				._M_iterator(*this));
-
 	istreambuf_iterator __old = *this;
-	if (_M_sbuf)
-	  {
-	    __old._M_c = _M_sbuf->sbumpc();
-	    _M_c = traits_type::eof();
-	  }
+	++(*this);
 	return __old;
       }
 
@@ -176,26 +175,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       int_type
       _M_get() const
       {
-	const int_type __eof = traits_type::eof();
-	int_type __ret = __eof;
+	if (!_S_at_eof(_M_c))
+	  return _M_c;
+
 	if (_M_sbuf)
-	  {
-	    if (!traits_type::eq_int_type(_M_c, __eof))
-	      __ret = _M_c;
-	    else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
-					       __eof))
-	      _M_c = __ret;
-	    else
-	      _M_sbuf = 0;
-	  }
-	return __ret;
+	  return _M_sbuf->sgetc();
+	return _M_c;
+      }
+
+      void
+      _M_get()
+      {
+	_M_c = _M_sbuf->sgetc();
+	if (_S_at_eof(_M_c))
+	  _M_sbuf = 0;
       }
 
       bool
       _M_at_eof() const
+      { return _S_at_eof(_M_get()); }
+
+      static bool
+      _S_at_eof(int_type __c)
       {
 	const int_type __eof = traits_type::eof();
-	return traits_type::eq_int_type(_M_get(), __eof);
+	return traits_type::eq_int_type(__c, __eof);
       }
     };
 
diff --git a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc
index b81f4d4..498dc1b 100644
--- a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc
+++ b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/2.cc
@@ -25,9 +25,7 @@
 
 void test02(void)
 {
-
   typedef std::istreambuf_iterator<char> cistreambuf_iter;
-  typedef cistreambuf_iter::streambuf_type cstreambuf_type;
   const char slit01[] = "playa hermosa, liberia, guanacaste";
   std::string str01(slit01);
   std::istringstream istrs00(str01);
@@ -35,10 +33,18 @@ void test02(void)
 
   // ctor sanity checks
   cistreambuf_iter istrb_it01(istrs00);
-  cistreambuf_iter istrb_it02;
-  std::string tmp(istrb_it01, istrb_it02); 
+  cistreambuf_iter istrb_eos;
+  VERIFY( istrb_it01 != istrb_eos );
+
+  std::string tmp(istrb_it01, istrb_eos);
   VERIFY( tmp == str01 );
 
+  VERIFY( istrb_it01 != istrb_eos );
+  VERIFY( *istrb_it01 == 'p' );
+  cistreambuf_iter old = istrb_it01++;
+  VERIFY( old != istrb_eos );
+  VERIFY( istrb_it01 == istrb_eos );
+
   cistreambuf_iter istrb_it03(0);
   cistreambuf_iter istrb_it04;
   VERIFY( istrb_it03 == istrb_it04 );

  reply	other threads:[~2017-09-07 21:02 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-24 11:27 Petr Ovtchenkov
2017-08-29 20:02 ` François Dumont
2017-08-30  5:05   ` Petr Ovtchenkov
2017-08-31 20:30     ` François Dumont
2017-09-01  9:10 ` Jonathan Wakely
2017-09-07 21:02   ` François Dumont [this message]
2017-09-08  5:47     ` Petr Ovtchenkov
2017-09-08  6:15       ` François Dumont
2017-09-09 20:17       ` François Dumont
2017-09-21  5:46         ` François Dumont
2017-09-28 10:50           ` Jonathan Wakely
2017-09-28 10:58             ` Jonathan Wakely
2017-09-21 18:23   ` Petr Ovtchenkov
2017-09-25  9:34     ` Petr Ovtchenkov
2017-09-23  7:10 [PATCH] libstdc++: istreambuf_iterator keep attached streambuf Petr Ovtchenkov
2017-09-25 13:46 ` Jonathan Wakely
2017-09-28 10:34 ` Jonathan Wakely
2017-09-28 12:06   ` Petr Ovtchenkov
2017-09-28 12:38     ` Jonathan Wakely
2017-10-03 20:39       ` Petr Ovtchenkov
2017-10-04  5:04         ` [PATCH v2] " Petr Ovtchenkov
2017-10-06 16:01         ` [PATCH] libstdc++: istreambuf_iterator proxy (was: keep attached streambuf) François Dumont
2017-10-06 18:00           ` Petr Ovtchenkov
2017-10-08 14:59             ` [PATCH] libstdc++: istreambuf_iterator proxy François Dumont
2017-10-09 19:32               ` Petr Ovtchenkov
2017-10-10  5:52               ` Petr Ovtchenkov
2017-10-10 14:21           ` [PATCH] libstdc++: istreambuf_iterator proxy (was: keep attached streambuf) Jonathan Wakely
2017-09-27 20:16 Make tests less istreambuf_iterator implementation dependent François Dumont
2017-09-28 12:12 ` Jonathan Wakely
2017-09-28 19:59   ` François Dumont
2017-09-28 21:56     ` Jonathan Wakely
2017-10-02  5:43       ` François Dumont
2017-10-03 14:20         ` Jonathan Wakely
2017-10-04 16:21           ` François Dumont
2017-10-04 23:23             ` Jonathan Wakely
2017-11-15 20:52             ` [PATCH 1/4] Revert "2017-10-04 Petr Ovtchenkov <ptr@void-ptr.info>" Petr Ovtchenkov
2017-11-15 20:52               ` [PATCH 2/4] libstdc++: istreambuf_iterator keep attached streambuf Petr Ovtchenkov
2017-11-15 20:52                 ` [PATCH 3/4] libstdc++: avoid character accumulation in istreambuf_iterator Petr Ovtchenkov
2017-11-15 20:52                   ` [PATCH 4/4] libstdc++: immutable _M_sbuf " Petr Ovtchenkov
2017-11-15 21:31                   ` [PATCH 3/4] libstdc++: avoid character accumulation " Paolo Carlini
2017-11-16  5:32                     ` Petr Ovtchenkov
2017-11-16  9:39                       ` Paolo Carlini
2017-11-16 11:03                         ` Petr Ovtchenkov
2017-11-16 11:29                           ` Paolo Carlini
2017-11-16 11:41                             ` Petr Ovtchenkov
2017-11-16 11:51                               ` Paolo Carlini
2017-11-16 10:56               ` [PATCH 1/4] Revert "2017-10-04 Petr Ovtchenkov <ptr@void-ptr.info>" Jonathan Wakely
2017-11-16 11:35                 ` Petr Ovtchenkov
2017-11-16 11:39                   ` Jonathan Wakely
2017-11-16 11:40                     ` Jonathan Wakely
2017-11-16 11:57                     ` Petr Ovtchenkov
2017-10-13 17:14 Make istreambuf_iterator::_M_sbuf immutable and add debug checks François Dumont
2017-10-23 19:08 ` François Dumont
2017-11-06 21:19   ` François Dumont
2017-11-16  5:52     ` Petr Ovtchenkov
2017-11-16 10:57       ` Jonathan Wakely
2017-11-16 11:46         ` Jonathan Wakely
2017-11-16 12:08           ` Petr Ovtchenkov
2017-11-16 17:40           ` François Dumont
2017-11-16 18:12             ` Petr Ovtchenkov
2017-11-16 21:31               ` François Dumont

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86fe822c-96c0-1167-68d9-d79729f3dec5@gmail.com \
    --to=frs.dumont@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=libstdc++@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).