diff --git a/libcxx/include/bitset b/libcxx/include/bitset index a20842985b3d5..c63e47463b0a0 100644 --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -329,12 +329,10 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) *__p = ~*__p; // do last partial word - if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b = *__p & __m; - *__p &= ~__m; - *__p |= ~__b & __m; - } + // Ensure trailing padding bits are zeroed as part of the ABI for consistent hashing behavior. std::hash + // assumes trailing bits are zeroed; otherwise, identical bitsets could hash differently. + if (__n > 0) + *__p ^= (__storage_type(1) << __n) - 1; } template @@ -514,9 +512,7 @@ __bitset<1, _Size>::operator^=(const __bitset& __v) _NOEXCEPT { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Size>::flip() _NOEXCEPT { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - _Size); - __first_ = ~__first_; - __first_ &= __m; + __first_ ^= ~__storage_type(0) >> (__bits_per_word - _Size); } template diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/flip_all.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/flip_all.pass.cpp index 79fa505e63cd3..55401367cd08f 100644 --- a/libcxx/test/std/utilities/template.bitset/bitset.members/flip_all.pass.cpp +++ b/libcxx/test/std/utilities/template.bitset/bitset.members/flip_all.pass.cpp @@ -18,19 +18,21 @@ template TEST_CONSTEXPR_CXX23 void test_flip_all() { - std::vector > const cases = get_test_cases(); - for (std::size_t c = 0; c != cases.size(); ++c) { - std::bitset v1 = cases[c]; - std::bitset v2 = v1; - v2.flip(); - for (std::size_t i = 0; i < v1.size(); ++i) - assert(v2[i] == ~v1[i]); - } + std::vector > const cases = get_test_cases(); + for (std::size_t c = 0; c != cases.size(); ++c) { + std::bitset v1 = cases[c]; + std::bitset v2 = v1; + v2.flip(); + for (std::size_t i = 0; i < v1.size(); ++i) + assert(v2[i] == ~v1[i]); + } } TEST_CONSTEXPR_CXX23 bool test() { test_flip_all<0>(); test_flip_all<1>(); + test_flip_all<2>(); + test_flip_all<5>(); test_flip_all<31>(); test_flip_all<32>(); test_flip_all<33>(); diff --git a/libcxx/test/std/utilities/template.bitset/bitset_test_cases.h b/libcxx/test/std/utilities/template.bitset/bitset_test_cases.h index b561b01ef19a9..1ca19ec469e2c 100644 --- a/libcxx/test/std/utilities/template.bitset/bitset_test_cases.h +++ b/libcxx/test/std/utilities/template.bitset/bitset_test_cases.h @@ -43,6 +43,28 @@ TEST_CONSTEXPR_CXX23 inline std::vector > get_test_cases<2>() { return cases; } +template <> +TEST_CONSTEXPR_CXX23 inline std::vector > get_test_cases<5>() { + std::vector > cases; + cases.push_back(std::bitset<5>("00000")); + cases.push_back(std::bitset<5>("00001")); + cases.push_back(std::bitset<5>("10000")); + cases.push_back(std::bitset<5>("00010")); + cases.push_back(std::bitset<5>("01000")); + cases.push_back(std::bitset<5>("00011")); + cases.push_back(std::bitset<5>("11000")); + cases.push_back(std::bitset<5>("00100")); + cases.push_back(std::bitset<5>("11011")); + cases.push_back(std::bitset<5>("00101")); + cases.push_back(std::bitset<5>("10100")); + cases.push_back(std::bitset<5>("00110")); + cases.push_back(std::bitset<5>("01100")); + cases.push_back(std::bitset<5>("00111")); + cases.push_back(std::bitset<5>("11100")); + cases.push_back(std::bitset<5>("11111")); + return cases; +} + template <> TEST_CONSTEXPR_CXX23 inline std::vector > get_test_cases<31>() { std::vector > cases;