[v3] 9371/9546/10093/10095

Pétur Runólfsson peturr02@ru.is
Thu Nov 27 21:09:00 GMT 2003


Benjamin Kosnik wrote:
> Fixes for longstanding exception handling bugs. No doubt there are more,
> but this at least clears the way for them to be considered. There is
> associated documentation that is unfinished but that I intend to check
> in at a later date.

I'm not sure about this hunk:

       void 
       setstate(iostate __state) 
-      { this->clear(this->rdstate() | __state); }
+      {
+	if (__state != ios_base::goodbit)
+	  this->clear(this->rdstate() | __state); 
+      }

Why is it needed? It seems that basic_istream and basic_ostream will
only call setstate() if good().

ostream os(...);
try {
  os.setstate(ios::failbit);
  os.exceptions(ios::failbit);
} catch (...) {
}

os.setstate(ios::goodbit);

The effects clause for setstate() seems to require that the second
call call to setstate() should call clear(), which should throw an
exception. Am I missing something?

> I think the inserters and extractors for streambufs are correct now, but
> the new tests diverge from what is in 9371. Petur, you should probably
> double check these.

I'm not sure about the error handling in this:

  template<typename _CharT, typename _Traits>
    basic_ostream<_CharT, _Traits>& 
    basic_ostream<_CharT, _Traits>::
    operator<<(__streambuf_type* __sbin)
    {
      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
      sentry __cerb(*this);
      if (__cerb && __sbin)
        {
          try
            {
              if (!__copy_streambufs(__sbin, this->rdbuf()))
                __err |= ios_base::failbit;
            }
          catch(...)
            { this->_M_setstate(ios_base::failbit); }
        }
      else if (!__sbin)
        __err |= ios_base::badbit;
      this->setstate(__err);
      return *this;
    }

27.6.2.5.3 p8 says that if an exception is thrown "while extracting
a character" failbit should be set. I read this as "from
sb->underflow()", and that exceptions thrown from rdbuf()->overflow()
should be handled like in other formatted output functions, that is,
by setting badbit, so I think the test cases in PR 10093 are correct
here.

basic_istream::operator>>(basic_streambuf* sb) is a different can of
worms. First, the resolution of DR 64 is obviously broken (DR 413).
Second, 27.6.1.2.3 p13 (modified by DR 64) only says that if no
characters have been copied, then caught exceptions should be rethrown.
Since p12 requires that all exceptions should be caught, it seems that
exceptions after at least one character has been copied should simply
be ignored. Note that p12 does not say what exceptions should be
caught, so it seems that this function should treat exceptions thrown
from rdbuf()->underflow() like exceptions thrown from sb->overflow().

This means that given:
istream& is = ...;
streambuf* sb = ...;
is >> sb;
is.rdstate() == eofbit means the call succeeded, but any other value
(including goodbit!) means it failed :-)

So the testcases in PR 10093 for this function seem to be wrong.

Petur



More information about the Gcc-patches mailing list