[llvm-bugs] [Bug 15949] no exceptions are thrown for stringstream

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Aug 29 10:24:52 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=15949

Tanzinul Islam <tanzinul.islam at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
                 CC|                            |tanzinul.islam at gmail.com
         Resolution|INVALID                     |---

--- Comment #2 from Tanzinul Islam <tanzinul.islam at gmail.com> ---
I believe the issue here is slightly more subtle.

First of all, as has been discussed in the comments of Howard's answer in the
Stack Overflow question (http://stackoverflow.com/a/16473878/1433768), the
issue being asked about isn't in basic_istream::operator>>(unsigned &), but in
the use of the std::getline(basic_istream<...>&, std::basic_string<...>&, char)
function a couple of lines above it.

According to the Standard (I'm using the N4606 draft that Howard kindly
supplied),

§21.3.2.9 [string.io]/p7 says that such a getline() function:
"Behaves as an unformatted input function (27.7.2.3)...".

§27.7.2.3 [istream.unformatted]/p1 says:
"Each unformatted input function begins execution by constructing an object of
class sentry with the default argument noskipws (second) argument true. If the
sentry object returns true, when converted to a value of type bool, the
function endeavors to obtain the requested input. Otherwise, if the sentry
constructor exits by throwing an exception or if the sentry object returns
false, when converted to a value of type bool, the function returns without
attempting to obtain any input."

So although the sentry object may equate to false or may have thrown an
exception as part of its construction, an unformatted input function is
commonly supposed to return (and not propagate that exception). However, if we
return to the specific requirements on std::getline(), §21.3.2.9 [string.io]/p9
says:

"If the function extracts no characters, it calls
is.setstate(ios_base::failbit) which may throw ios_base::failure (27.5.5.4)."

This is a blanket requirement on std::getline() regardless of exception during
sentry-construction or an actual failure during extraction from the stream.

With that in mind, on the 4th invocation of the std::getline() inside the
user's getvalue() function,

- eofbit should already have been set from the previous (3rd) invocation,
because the source string in main() had three comma-delimited parts and no
trailing whitespace.

- So the sentry object constructor should have detected is.good() to be false
and called is.setstate(failbit) as required by §27.7.2.1.3
[istream::sentry]/p2:
"Effects: If is.good() is false, calls is.setstate(failbit)."

- This would have thrown an exception (because the user had enabled exception
on failbit), which would be caught/detected by std::getline() because it is an
unformatted input function.

However, std::getline() should now **itself** call
is.setstate(ios_base::failbit) as required by §21.3.2.9 [string.io]/p9, because
it did not extract any input in this 4th invocation. This should cause an
ios_base::failure exception to be propagated to the user's code -- eventually
getting caught in main() and showing "Fail". This isn't being done with libc++,
so I am reopening this bug.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160829/5bcd37f7/attachment-0001.html>


More information about the llvm-bugs mailing list