]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
std_bitset.h (_Base_bitset::_M_do_left_shift, [...]): Expect a non-zero shift.
authorPhil Edwards <pme@gcc.gnu.org>
Fri, 27 Dec 2002 00:03:17 +0000 (00:03 +0000)
committerPhil Edwards <pme@gcc.gnu.org>
Fri, 27 Dec 2002 00:03:17 +0000 (00:03 +0000)
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

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/std_bitset.h
libstdc++-v3/testsuite/23_containers/bitset_members.cc
libstdc++-v3/testsuite/23_containers/bitset_shift.cc

index d6cd0041f886c7c880bde7d3747bdbb67b0e0938..f613267f9326776ed775ebc7c1c6863dc2b529d7 100644 (file)
@@ -1,3 +1,15 @@
+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.
index f2fde3111d16d9ac834eeba9c51b7dad8ab80bf1..83693f5e0b2953417e7a4b38f7c61e9b5b1a95ac 100644 (file)
@@ -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;
index 30e0ab6e063e5e7e38f45ac410425ad2e0875bbc..054018df66280d988a984952b84963a4792af7bc 100644 (file)
@@ -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;
 }
index 35531bf5b4cc48bc967d2386e14f5d72c49b918c..01fdd2fbc4ba6055a72292a7d80eca26915afbda 100644 (file)
@@ -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;
 }