diff options
author | Phil Edwards <pme@gcc.gnu.org> | 2002-12-27 00:03:17 +0000 |
---|---|---|
committer | Phil Edwards <pme@gcc.gnu.org> | 2002-12-27 00:03:17 +0000 |
commit | 3bbfb3d91dd6137f419c9d85ce7c75bb96e860b0 (patch) | |
tree | aeb9947904387c32a63d66db431bc706d6280a23 | |
parent | 9795acc64a1e348ebe9b32d21311d6cae6b20088 (diff) | |
download | gcc-3bbfb3d91dd6137f419c9d85ce7c75bb96e860b0.zip gcc-3bbfb3d91dd6137f419c9d85ce7c75bb96e860b0.tar.gz gcc-3bbfb3d91dd6137f419c9d85ce7c75bb96e860b0.tar.bz2 |
std_bitset.h (_Base_bitset::_M_do_left_shift, [...]): Expect a non-zero shift.
2002-12-26 Phil Edwards <pme@gcc.gnu.org>
* include/std/std_bitset.h (_Base_bitset::_M_do_left_shift,
_Base_bitset::_M_do_right_shift): Expect a non-zero shift.
(bitset::operator<<=, bitset::operator>>=): When shifting more bits
than are in the bitset, zero memory rather than segfault.
(operator>>(basic_istream,bitset): Only call setstate once, after
all work has been done.
* testsuite/23_containers/bitset_members.cc (test03): New test.
* testsuite/23_containers/bitset_shift.cc (test02): New test.
From-SVN: r60533
-rw-r--r-- | libstdc++-v3/ChangeLog | 12 | ||||
-rw-r--r-- | libstdc++-v3/include/std/std_bitset.h | 43 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/bitset_members.cc | 18 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/bitset_shift.cc | 16 |
4 files changed, 75 insertions, 14 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d6cd004..f613267 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,17 @@ 2002-12-26 Phil Edwards <pme@gcc.gnu.org> + * include/std/std_bitset.h (_Base_bitset::_M_do_left_shift, + _Base_bitset::_M_do_right_shift): Expect a non-zero shift. + (bitset::operator<<=, bitset::operator>>=): When shifting more bits + than are in the bitset, zero memory rather than segfault. + (operator>>(basic_istream,bitset): Only call setstate once, after + all work has been done. + + * testsuite/23_containers/bitset_members.cc (test03): New test. + * testsuite/23_containers/bitset_shift.cc (test02): New test. + +2002-12-26 Phil Edwards <pme@gcc.gnu.org> + * libsupc++/vterminate.cc (writestr): Use __builtin_strlen. 2002-12-26 Phil Edwards <pme@gcc.gnu.org> diff --git a/libstdc++-v3/include/std/std_bitset.h b/libstdc++-v3/include/std/std_bitset.h index f2fde31..83693f5 100644 --- a/libstdc++-v3/include/std/std_bitset.h +++ b/libstdc++-v3/include/std/std_bitset.h @@ -219,7 +219,7 @@ namespace std void _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) { - if (__shift != 0) + if (__builtin_expect(__shift != 0, 1)) { const size_t __wshift = __shift / _GLIBCPP_BITSET_BITS_PER_WORD; const size_t __offset = __shift % _GLIBCPP_BITSET_BITS_PER_WORD; @@ -244,7 +244,7 @@ namespace std void _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) { - if (__shift != 0) + if (__builtin_expect(__shift != 0, 1)) { const size_t __wshift = __shift / _GLIBCPP_BITSET_BITS_PER_WORD; const size_t __offset = __shift % _GLIBCPP_BITSET_BITS_PER_WORD; @@ -581,9 +581,11 @@ namespace std * The template argument, @a _Nb, may be any non-negative number of type * size_t. * - * A %bitset of size N has N % (sizeof(unsigned long) * CHAR_BIT) unused - * bits. (They are the high-order bits in the highest word.) It is - * a class invariant that those unused bits are always zero. + * A %bitset of size N uses U bits, where + * U = (N % (sizeof(unsigned long) * CHAR_BIT)). + * Thus, N - U bits are unused. (They are the high-order bits in the + * highest word.) It is a class invariant that those unused bits are + * always zero. * * If you think of %bitset as "a simple array of bits," be aware that * your mental picture is reversed: a %bitset behaves the same way as @@ -805,16 +807,26 @@ namespace std bitset<_Nb>& operator<<=(size_t __pos) { - this->_M_do_left_shift(__pos); - this->_M_do_sanitize(); + if (__builtin_expect(__pos < _Nb, 1)) + { + this->_M_do_left_shift(__pos); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); return *this; } bitset<_Nb>& operator>>=(size_t __pos) { - this->_M_do_right_shift(__pos); - this->_M_do_sanitize(); + if (__builtin_expect(__pos < _Nb, 1)) + { + this->_M_do_right_shift(__pos); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); return *this; } //@} @@ -1183,6 +1195,7 @@ namespace std typename basic_istream<_CharT, _Traits>::sentry __sentry(__is); if (__sentry) { + ios_base::iostate __state = ios_base::goodbit; basic_streambuf<_CharT, _Traits>* __buf = __is.rdbuf(); for (size_t __i = 0; __i < _Nb; ++__i) { @@ -1191,7 +1204,7 @@ namespace std typename _Traits::int_type __c1 = __buf->sbumpc(); if (_Traits::eq_int_type(__c1, __eof)) { - __is.setstate(ios_base::eofbit); + __state |= ios_base::eofbit; break; } else @@ -1201,19 +1214,21 @@ namespace std if (__c == '0' || __c == '1') __tmp.push_back(__c); - else if (_Traits::eq_int_type(__buf->sputbackc(__c2), - __eof)) + else if (_Traits::eq_int_type(__buf->sputbackc(__c2), __eof)) { - __is.setstate(ios_base::failbit); + __state |= ios_base::failbit; break; } } } if (__tmp.empty() && !_Nb) - __is.setstate(ios_base::failbit); + __state |= ios_base::failbit; else __x._M_copy_from_string(__tmp, static_cast<size_t>(0), _Nb); + + if (__state != ios_base::goodbit) + __is.setstate(__state); // may throw an exception } return __is; diff --git a/libstdc++-v3/testsuite/23_containers/bitset_members.cc b/libstdc++-v3/testsuite/23_containers/bitset_members.cc index 30e0ab6..054018d 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset_members.cc +++ b/libstdc++-v3/testsuite/23_containers/bitset_members.cc @@ -22,6 +22,7 @@ #include <bitset> #include <stdexcept> +#include <sstream> #include <testsuite_hooks.h> void @@ -52,9 +53,26 @@ void test02() bs.count(); } +void test03() +{ + std::bitset<5> b; + std::stringstream ss ("101"); + + ss.exceptions(std::ios_base::eofbit); + + try + { + ss >> b; + } + catch (std::exception&) {} + + VERIFY( b.to_ulong() == 5 ); +} + int main() { test01(); test02(); + test03(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/bitset_shift.cc b/libstdc++-v3/testsuite/23_containers/bitset_shift.cc index 35531bf..01fdd2f 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset_shift.cc +++ b/libstdc++-v3/testsuite/23_containers/bitset_shift.cc @@ -106,9 +106,25 @@ test01() { return test; } +bool +test02() +{ + bool test = true; + + std::bitset<66> b; + b <<= 400; + VERIFY( b.count() == 0 ); + +#ifdef DEBUG_ASSERT + assert(test); +#endif + return test; +} + int main() { test01(); + test02(); return 0; } |