diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-06-10 14:08:16 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2024-06-12 15:06:47 +0100 |
commit | bd3a312728fbf8c35a09239b9180269f938f872e (patch) | |
tree | d2775de3e5d07ffe67332d96f53d225997c4fa1a | |
parent | 3f2f9059c7f76ff888e9d0e8f10dec6f48e346c9 (diff) | |
download | gcc-bd3a312728fbf8c35a09239b9180269f938f872e.zip gcc-bd3a312728fbf8c35a09239b9180269f938f872e.tar.gz gcc-bd3a312728fbf8c35a09239b9180269f938f872e.tar.bz2 |
libstdc++: Fix std::tr2::dynamic_bitset shift operations [PR115399]
The shift operations for dynamic_bitset fail to zero out words where the
non-zero bits were shifted to a completely different word.
For a right shift we don't need to sanitize the unused bits in the high
word, because we know they were already clear and a right shift doesn't
change that.
libstdc++-v3/ChangeLog:
PR libstdc++/115399
* include/tr2/dynamic_bitset (operator>>=): Remove redundant
call to _M_do_sanitize.
* include/tr2/dynamic_bitset.tcc (_M_do_left_shift): Zero out
low bits in words that should no longer be populated.
(_M_do_right_shift): Likewise for high bits.
* testsuite/tr2/dynamic_bitset/pr115399.cc: New test.
-rw-r--r-- | libstdc++-v3/include/tr2/dynamic_bitset | 5 | ||||
-rw-r--r-- | libstdc++-v3/include/tr2/dynamic_bitset.tcc | 6 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/tr2/dynamic_bitset/pr115399.cc | 37 |
3 files changed, 40 insertions, 8 deletions
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset index 0e4e889..274c4f6 100644 --- a/libstdc++-v3/include/tr2/dynamic_bitset +++ b/libstdc++-v3/include/tr2/dynamic_bitset @@ -815,10 +815,7 @@ namespace tr2 operator>>=(size_type __pos) { if (__builtin_expect(__pos < this->_M_Nb, 1)) - { - this->_M_do_right_shift(__pos); - this->_M_do_sanitize(); - } + this->_M_do_right_shift(__pos); else this->_M_do_reset(); return *this; diff --git a/libstdc++-v3/include/tr2/dynamic_bitset.tcc b/libstdc++-v3/include/tr2/dynamic_bitset.tcc index 63ba6f2..5aac7d8 100644 --- a/libstdc++-v3/include/tr2/dynamic_bitset.tcc +++ b/libstdc++-v3/include/tr2/dynamic_bitset.tcc @@ -60,8 +60,7 @@ namespace tr2 this->_M_w[__wshift] = this->_M_w[0] << __offset; } - //// std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift, - //// static_cast<_WordT>(0)); + std::fill_n(this->_M_w.begin(), __wshift, _WordT(0)); } } @@ -88,8 +87,7 @@ namespace tr2 this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset; } - ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(), - //// static_cast<_WordT>(0)); + std::fill_n(this->_M_w.end() - __wshift, __wshift, _WordT(0)); } } diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr115399.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr115399.cc new file mode 100644 index 0000000..e626e4a --- /dev/null +++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr115399.cc @@ -0,0 +1,37 @@ +// { dg-do run { target c++11 } } + +// PR libstdc++/115399 +// std::tr2::dynamic_bitset shift behaves differently from std::bitset + +#include <tr2/dynamic_bitset> +#include <testsuite_hooks.h> + +void +test_left_shift() +{ + std::tr2::dynamic_bitset<> b(65); + b[0] = 1; + auto b2 = b << 64; + VERIFY(b2[64] == 1); + VERIFY(b2[0] == 0); + b <<= 64; + VERIFY( b2 == b ); +} + +void +test_right_shift() +{ + std::tr2::dynamic_bitset<> b(65); + b[64] = 1; + auto b2 = b >> 64; + VERIFY(b2[64] == 0); + VERIFY(b2[0] == 1); + b >>= 64; + VERIFY( b2 == b ); +} + +int main() +{ + test_left_shift(); + test_right_shift(); +} |