From: Jonathan Wakely Date: Mon, 4 Sep 2017 17:09:01 +0000 (+0100) Subject: PR libstdc++/53984 handle exceptions in basic_istream::sentry X-Git-Tag: releases/gcc-5.5.0~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a3b7ea2654a1881da415ea016a22f715e2eb159;p=thirdparty%2Fgcc.git PR libstdc++/53984 handle exceptions in basic_istream::sentry Backport from mainline 2017-07-25 Jonathan Wakely PR libstdc++/53984 * include/bits/basic_ios.h (basic_ios::_M_setstate): Adjust comment. * include/bits/istream.tcc (basic_istream::sentry): Handle exceptions during construction. * include/std/istream: Adjust comments for formatted input functions and unformatted input functions. * testsuite/27_io/basic_fstream/53984.cc: New. * testsuite/27_io/basic_istream/sentry/char/53984.cc: New. From-SVN: r251679 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 465f996e967b..ade7cb179e13 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,17 @@ 2017-09-04 Jonathan Wakely + Backport from mainline + 2017-07-25 Jonathan Wakely + + PR libstdc++/53984 + * include/bits/basic_ios.h (basic_ios::_M_setstate): Adjust comment. + * include/bits/istream.tcc (basic_istream::sentry): Handle exceptions + during construction. + * include/std/istream: Adjust comments for formatted input functions + and unformatted input functions. + * testsuite/27_io/basic_fstream/53984.cc: New. + * testsuite/27_io/basic_istream/sentry/char/53984.cc: New. + Backport from mainline 2017-06-08 Jonathan Wakely diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index 8bea1761fc8e..0e4509903d4c 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -157,8 +157,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION setstate(iostate __state) { this->clear(this->rdstate() | __state); } - // Flip the internal state on for the proper state bits, then re - // throws the propagated exception if bit also set in + // Flip the internal state on for the proper state bits, then + // rethrows the propagated exception if bit also set in // exceptions(). void _M_setstate(iostate __state) diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index e8cbb261b8a9..904d40d0cd6f 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -48,28 +48,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { ios_base::iostate __err = ios_base::goodbit; if (__in.good()) - { - if (__in.tie()) - __in.tie()->flush(); - if (!__noskip && bool(__in.flags() & ios_base::skipws)) - { - const __int_type __eof = traits_type::eof(); - __streambuf_type* __sb = __in.rdbuf(); - __int_type __c = __sb->sgetc(); - - const __ctype_type& __ct = __check_facet(__in._M_ctype); - while (!traits_type::eq_int_type(__c, __eof) - && __ct.is(ctype_base::space, - traits_type::to_char_type(__c))) - __c = __sb->snextc(); + __try + { + if (__in.tie()) + __in.tie()->flush(); + if (!__noskip && bool(__in.flags() & ios_base::skipws)) + { + const __int_type __eof = traits_type::eof(); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); + + const __ctype_type& __ct = __check_facet(__in._M_ctype); + while (!traits_type::eq_int_type(__c, __eof) + && __ct.is(ctype_base::space, + traits_type::to_char_type(__c))) + __c = __sb->snextc(); - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 195. Should basic_istream::sentry's constructor ever - // set eofbit? - if (traits_type::eq_int_type(__c, __eof)) - __err |= ios_base::eofbit; - } - } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 195. Should basic_istream::sentry's constructor ever + // set eofbit? + if (traits_type::eq_int_type(__c, __eof)) + __err |= ios_base::eofbit; + } + } + __catch(__cxxabiv1::__forced_unwind&) + { + __in._M_setstate(ios_base::badbit); + __throw_exception_again; + } + __catch(...) + { __in._M_setstate(ios_base::badbit); } if (__in.good() && __err == ios_base::goodbit) _M_ok = true; diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index 74c0d81e0a37..deb50d31ea83 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -150,9 +150,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * whatever data is appropriate for the type of the argument. * * If an exception is thrown during extraction, ios_base::badbit - * will be turned on in the stream's error state without causing an - * ios_base::failure to be thrown. The original exception will then - * be rethrown. + * will be turned on in the stream's error state (without causing an + * ios_base::failure to be thrown) and the original exception will + * be rethrown if badbit is set in the exceptions mask. */ //@{ @@ -286,9 +286,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * by gcount(). * * If an exception is thrown during extraction, ios_base::badbit - * will be turned on in the stream's error state without causing an - * ios_base::failure to be thrown. The original exception will then - * be rethrown. + * will be turned on in the stream's error state (without causing an + * ios_base::failure to be thrown) and the original exception will + * be rethrown if badbit is set in the exceptions mask. */ /** diff --git a/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc b/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc new file mode 100644 index 000000000000..a319aff1c62b --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_fstream/53984.cc @@ -0,0 +1,64 @@ +// 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 +// . + +// { dg-require-fileio "" } + +// PR libstdc++/53984 + +#include +#include + +void +test01() +{ + std::ifstream in("."); + if (in) + { + char c; + if (in.get(c)) + { + // Reading a directory doesn't produce an error on this target + // so the formatted input functions below wouldn't fail anyway + // (see PR libstdc++/81808). + return; + } + int x; + in.clear(); + // Formatted input function should set badbit, but not throw: + in >> x; + VERIFY( in.bad() ); + + in.clear(); + in.exceptions(std::ios::badbit); + try + { + // Formatted input function should set badbit, and throw: + in >> x; + VERIFY( false ); + } + catch (const std::exception&) + { + VERIFY( in.bad() ); + } + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc new file mode 100644 index 000000000000..9c08c7236dac --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/53984.cc @@ -0,0 +1,41 @@ +// 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 +// . + +#include +#include +#include + +struct SB : std::streambuf +{ + virtual int_type underflow() { throw 1; } +}; + +void +test01() +{ + SB sb; + std::istream is(&sb); + int i; + is >> i; + VERIFY( is.bad() ); +} + +int +main() +{ + test01(); +}