-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Fix improper static_cast in std::deque and __split_buffer #119106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
b5ebd35
to
2fbcddc
Compare
2fbcddc
to
aa3cfef
Compare
@llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesThis PR addresses the improper use of In libc++'s implementations of Full diff: https://github.com/llvm/llvm-project/pull/119106.diff 2 Files Affected:
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index a637c83d17d107..5ee70220b55ab1 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -435,7 +435,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
__begin_ = std::move_backward(__begin_, __end_, __end_ + __d);
__end_ += __d;
} else {
- size_type __c = std::max<size_type>(2 * static_cast<size_t>(__cap_ - __first_), 1);
+ size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc_);
__t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
std::swap(__first_, __t.__first_);
@@ -458,7 +458,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back
__end_ = std::move(__begin_, __end_, __begin_ - __d);
__begin_ -= __d;
} else {
- size_type __c = std::max<size_type>(2 * static_cast<size_t>(__cap_ - __first_), 1);
+ size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1);
__split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc_);
__t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
std::swap(__first_, __t.__first_);
diff --git a/libcxx/include/deque b/libcxx/include/deque
index ad667503489741..f44eeb3b2de81a 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -2431,7 +2431,7 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_it
difference_type __pos = __f - __b;
iterator __p = __b + __pos;
allocator_type& __a = __alloc();
- if (static_cast<size_t>(__pos) <= (size() - 1) / 2) { // erase from front
+ if (static_cast<size_type>(__pos) <= (size() - 1) / 2) { // erase from front
std::move_backward(__b, __p, std::next(__p));
__alloc_traits::destroy(__a, std::addressof(*__b));
--__size();
@@ -2459,7 +2459,7 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_it
iterator __p = __b + __pos;
if (__n > 0) {
allocator_type& __a = __alloc();
- if (static_cast<size_t>(__pos) <= (size() - __n) / 2) { // erase from front
+ if (static_cast<size_type>(__pos) <= (size() - __n) / 2) { // erase from front
iterator __i = std::move_backward(__b, __p, __p + __n);
for (; __b != __i; ++__b)
__alloc_traits::destroy(__a, std::addressof(*__b));
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense to me, but would it make sense to try to exercise this with a test?
Thank you for the feedback. I am not sure how to add a suitable test for this purpose. I have tried to find examples that can trigger issues due to the improper However, the improper size_type __c = std::max<size_type>(2 * static_cast<size_t>(__cap_ - __first_), 1); I have also experimented with some custom allocators with different |
This PR addresses the improper use of
static_cast
tosize_t
wheresize_type
is intended. Although thesize_type
member type of STL containers is usually a synonym ofstd::size_t
, there is no guarantee that they are always equivalent. The C++ standard does not mandate this equivalence.In libc++'s implementations of
std::deque
,std::vector
, and__split_buffer
, thesize_type
member type is defined asstd::allocator_traits<allocator_type>::size_type
, which is eitherallocator_type::size_type
if available orstd::make_unsigned<difference_type>::type
. While it is true forstd::allocator
that thesize_type
member type isstd::size_t
, for user-defined allocator types, they may mismatch. This justifies the need to replacestatic_cast<size_t>
withstatic_cast<size_type>
in this PR.