From e9ffbc858ad51efcf58199a939ed7314f0d4e822 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Wed, 11 Dec 2024 18:21:46 -0500 Subject: [PATCH 1/4] Simplify vector::__construct_at_end --- libcxx/include/__vector/vector_bool.h | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 4f1c442ce0be8..3f4d443d386fe 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -558,30 +558,20 @@ vector::__recommend(size_type __new_size) const { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(size_type __n, bool __x) { - size_type __old_size = this->__size_; + iterator __old_end = end(); this->__size_ += __n; - if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) { - if (this->__size_ <= __bits_per_word) - this->__begin_[0] = __storage_type(0); - else - this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); - } - std::fill_n(__make_iter(__old_size), __n, __x); + this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); + std::fill_n(__old_end, __n, __x); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { - size_type __old_size = this->__size_; + iterator __old_end = end(); this->__size_ += __n; - if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) { - if (this->__size_ <= __bits_per_word) - this->__begin_[0] = __storage_type(0); - else - this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); - } - std::__copy(std::move(__first), std::move(__last), __make_iter(__old_size)); + this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); + std::__copy(std::move(__first), std::move(__last), __old_end); } template @@ -855,7 +845,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::reserve(size_type _ this->__throw_length_error(); vector __v(this->get_allocator()); __v.__vallocate(__n); - __v.__construct_at_end(this->begin(), this->end(), this->size()); + // Ensure that the call to __construct_at_end(first, last, n) meets the precondition of n > 0 + if (this->size() > 0) + __v.__construct_at_end(this->begin(), this->end(), this->size()); swap(__v); } } From 1b6529468e794793e46d6e75adca88108ec02ec5 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Mon, 13 Jan 2025 20:33:52 -0500 Subject: [PATCH 2/4] Add _LIBCPP_ASSERT_INTERNAL --- libcxx/include/__vector/vector_bool.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 3f4d443d386fe..494f91e781166 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -558,6 +558,7 @@ vector::__recommend(size_type __new_size) const { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(size_type __n, bool __x) { + _LIBCPP_ASSERT_INTERNAL(__n > 0, "This function expects __n > 0"); iterator __old_end = end(); this->__size_ += __n; this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); @@ -568,6 +569,7 @@ template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { + _LIBCPP_ASSERT_INTERNAL(__n > 0, "This function expects __n > 0"); iterator __old_end = end(); this->__size_ += __n; this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); From acc1a87c51223bd099eb006a6b7d3b141615d3d4 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Mon, 20 Jan 2025 14:45:49 -0500 Subject: [PATCH 3/4] Add explicit precondition check --- libcxx/include/__vector/vector_bool.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 494f91e781166..698f6c2658d10 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -552,28 +552,29 @@ vector::__recommend(size_type __new_size) const { } // Default constructs __n objects starting at __end_ -// Precondition: __n > 0 // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(size_type __n, bool __x) { - _LIBCPP_ASSERT_INTERNAL(__n > 0, "This function expects __n > 0"); - iterator __old_end = end(); + _LIBCPP_ASSERT_INTERNAL( + capacity() >= size() + __n, "vector::__construct_at_end called with insufficient capacity"); + std::fill_n(end(), __n, __x); this->__size_ += __n; - this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); - std::fill_n(__old_end, __n, __x); + if (end().__ctz_ != 0) // has uninitialized trailing bits in the last word + std::fill_n(end(), __bits_per_word - end().__ctz_, 0); } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { - _LIBCPP_ASSERT_INTERNAL(__n > 0, "This function expects __n > 0"); - iterator __old_end = end(); + _LIBCPP_ASSERT_INTERNAL( + capacity() >= size() + __n, "vector::__construct_at_end called with insufficient capacity"); + std::__copy(std::move(__first), std::move(__last), end()); this->__size_ += __n; - this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); - std::__copy(std::move(__first), std::move(__last), __old_end); + if (end().__ctz_ != 0) // has uninitialized trailing bits in the last word + std::fill_n(end(), __bits_per_word - end().__ctz_, 0); } template From c8a50276d23f86f91895bfaa2830b644b5c26cb7 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Mon, 20 Jan 2025 15:16:22 -0500 Subject: [PATCH 4/4] Remove unnecessary if condition and comment --- libcxx/include/__vector/vector_bool.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 698f6c2658d10..8d9257eddfcd2 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -561,7 +561,7 @@ vector::__construct_at_end(size_type __n, bool __x) { capacity() >= size() + __n, "vector::__construct_at_end called with insufficient capacity"); std::fill_n(end(), __n, __x); this->__size_ += __n; - if (end().__ctz_ != 0) // has uninitialized trailing bits in the last word + if (end().__ctz_ != 0) // Ensure uninitialized leading bits in the last word are set to zero std::fill_n(end(), __bits_per_word - end().__ctz_, 0); } @@ -573,7 +573,7 @@ vector::__construct_at_end(_InputIterator __first, _Sentinel _ capacity() >= size() + __n, "vector::__construct_at_end called with insufficient capacity"); std::__copy(std::move(__first), std::move(__last), end()); this->__size_ += __n; - if (end().__ctz_ != 0) // has uninitialized trailing bits in the last word + if (end().__ctz_ != 0) // Ensure uninitialized leading bits in the last word are set to zero std::fill_n(end(), __bits_per_word - end().__ctz_, 0); } @@ -848,9 +848,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::reserve(size_type _ this->__throw_length_error(); vector __v(this->get_allocator()); __v.__vallocate(__n); - // Ensure that the call to __construct_at_end(first, last, n) meets the precondition of n > 0 - if (this->size() > 0) - __v.__construct_at_end(this->begin(), this->end(), this->size()); + __v.__construct_at_end(this->begin(), this->end(), this->size()); swap(__v); } }