diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 36eb7f350ac40..525fc35b26cc9 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -1049,18 +1049,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::resize(size_type __ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { - // do middle whole words - size_type __n = __size_; + // Flip each storage word entirely, including the last potentially partial word. + // The unused bits in the last word are safe to flip as they won't be accessed. __storage_pointer __p = __begin_; - for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) + for (size_type __n = __external_cap_to_internal(size()); __n != 0; ++__p, --__n) *__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; - } } template diff --git a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp new file mode 100644 index 0000000000000..f8f575cdc0e21 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// void flip(); + +#include +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +template +TEST_CONSTEXPR_CXX20 void test_vector_flip(std::size_t n, Allocator a) { + std::vector v(n, false, a); + for (std::size_t i = 0; i < n; ++i) + v[i] = i & 1; + std::vector original = v; + v.flip(); + for (size_t i = 0; i < n; ++i) + assert(v[i] == !original[i]); + v.flip(); + assert(v == original); +} + +TEST_CONSTEXPR_CXX20 bool tests() { + // Test small vectors with different allocators + test_vector_flip(3, std::allocator()); + test_vector_flip(3, min_allocator()); + test_vector_flip(3, test_allocator(5)); + + // Test large vectors with different allocators + test_vector_flip(1000, std::allocator()); + test_vector_flip(1000, min_allocator()); + test_vector_flip(1000, test_allocator(5)); + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER >= 20 + static_assert(tests()); +#endif + return 0; +}