-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[libc++] Don't instantiate __split_buffer with an allocator reference #171651
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
[libc++] Don't instantiate __split_buffer with an allocator reference #171651
Conversation
Allocators should be extremely cheap, if not free, to copy. Furthermore, we have requirements on allocator types that copies must compare equal, and that move and copy must be the same. Hence, taking an allocator by reference should not provide benefits beyond making a copy of it. However, taking the allocator by reference leads to complexity in __split_buffer, which can be removed if we stop using that pattern.
|
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesAllocators should be extremely cheap, if not free, to copy. Furthermore, we have requirements on allocator types that copies must compare equal, and that move and copy must be the same. Hence, taking an allocator by reference should not provide benefits beyond making a copy of it. However, taking the allocator by reference leads to complexity in __split_buffer, which can be removed if we stop using that pattern. Patch is 21.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171651.diff 3 Files Affected:
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1e05e4df8ba0f..d6176f8ca2749 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -33,7 +33,6 @@
#include <__type_traits/is_swappable.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/is_trivially_relocatable.h>
-#include <__type_traits/remove_reference.h>
#include <__utility/forward.h>
#include <__utility/move.h>
@@ -54,8 +53,7 @@ class __split_buffer_pointer_layout {
protected:
using value_type = _Tp;
using allocator_type = _Allocator;
- using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = typename __alloc_traits::size_type;
@@ -159,9 +157,9 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
- __split_buffer_pointer_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_pointer_layout>,
+ __split_buffer_pointer_layout<__split_buffer<value_type, allocator_type, __split_buffer_pointer_layout>,
value_type,
- __alloc_rr&>& __other) _NOEXCEPT {
+ allocator_type>& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__back_cap_, __other.__back_cap_);
@@ -207,8 +205,7 @@ class __split_buffer_size_layout {
protected:
using value_type = _Tp;
using allocator_type = _Allocator;
- using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = typename __alloc_traits::size_type;
@@ -316,9 +313,9 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
- __split_buffer_pointer_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_pointer_layout>,
+ __split_buffer_pointer_layout<__split_buffer<value_type, allocator_type, __split_buffer_pointer_layout>,
value_type,
- __alloc_rr&>& __other) _NOEXCEPT {
+ allocator_type>& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
@@ -386,8 +383,7 @@ private:
// protected:
// using value_type = _Tp;
// using allocator_type = _Allocator;
-// using __alloc_rr = __libcpp_remove_reference_t<allocator_type>;
-// using __alloc_traits = allocator_traits<__alloc_rr>;
+// using __alloc_traits = allocator_traits<allocator_type>;
// using reference = value_type&;
// using const_reference = const value_type&;
// using size_type = typename __alloc_traits::size_type;
@@ -462,7 +458,6 @@ public:
using __base_type::__set_sentinel;
using __base_type::__set_valid_range;
- using typename __base_type::__alloc_rr;
using typename __base_type::__alloc_traits;
using typename __base_type::allocator_type;
using typename __base_type::const_iterator;
@@ -489,18 +484,18 @@ public:
_LIBCPP_HIDE_FROM_ABI __split_buffer() = default;
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) : __base_type(__a) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(allocator_type& __a) : __base_type(__a) {}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const allocator_type& __a)
: __base_type(__a) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
+ __split_buffer(size_type __cap, size_type __start, allocator_type& __a);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const allocator_type& __a);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c)
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
@@ -560,7 +555,7 @@ public:
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT;
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
if (__front_cap() == nullptr) {
@@ -589,7 +584,7 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_without_allocator(__split_buffer<value_type, __alloc_rr&, _Layout>& __other) _NOEXCEPT {
+ __swap_without_allocator(__split_buffer<value_type, allocator_type, _Layout>& __other) _NOEXCEPT {
__base_type::__swap_without_allocator(__other);
}
@@ -653,7 +648,7 @@ template <class _Tp, class _Allocator, template <class, class, class> class _Lay
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
- __alloc_rr& __a = __get_allocator();
+ allocator_type& __a = __get_allocator();
for (; __first != __last; ++__first) {
if (__back_spare() == 0) {
size_type __old_cap = capacity();
@@ -718,7 +713,7 @@ __split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_end(pointer __new_last,
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
+__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_type __start, allocator_type& __a)
: __base_type(__a) {
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
if (__cap > 0) {
@@ -748,7 +743,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::__split_
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20
-__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
+__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const allocator_type& __a)
: __base_type(__a) {
if (__a == __c.__get_allocator()) {
__set_data(__c.__front_cap());
@@ -781,7 +776,7 @@ __split_buffer<_Tp, _Allocator, _Layout>::operator=(__split_buffer&& __c)
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::swap(__split_buffer& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
__base_type::swap(__x);
}
@@ -791,7 +786,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shr
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, __alloc_rr&, _Layout> __t(size(), 0, __get_allocator());
+ __split_buffer<value_type, allocator_type, _Layout> __t(size(), 0, __get_allocator());
if (__t.capacity() < capacity()) {
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(end()));
__t.__set_sentinel(size());
@@ -818,7 +813,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
__set_valid_range(std::move_backward(begin(), __end, __new_end), __new_end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
- __split_buffer<value_type, __alloc_rr&, _Layout> __t(__c, (__c + 3) / 4, __get_allocator());
+ __split_buffer<value_type, allocator_type, _Layout> __t(__c, (__c + 3) / 4, __get_allocator());
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
__base_type::__swap_without_allocator(__t);
}
@@ -840,7 +835,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emp
__set_valid_range(begin() - __d, __end);
} else {
size_type __c = std::max<size_type>(2 * capacity(), 1);
- __split_buffer<value_type, __alloc_rr&, _Layout> __t(__c, __c / 4, __get_allocator());
+ __split_buffer<value_type, allocator_type, _Layout> __t(__c, __c / 4, __get_allocator());
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
__base_type::__swap_without_allocator(__t);
}
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 4961a5fcb2067..93358d863492e 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -687,9 +687,9 @@ class vector {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v);
+ __swap_out_circular_buffer(__split_buffer<value_type, allocator_type>& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p);
+ __swap_out_circular_buffer(__split_buffer<value_type, allocator_type>& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -810,7 +810,7 @@ class vector {
return __p;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer<_Tp, allocator_type&>& __sb) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer<_Tp, allocator_type>& __sb) {
auto __vector_begin = __begin_;
auto __vector_sentinel = __end_;
auto __vector_cap = __cap_;
@@ -855,7 +855,7 @@ vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type>& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
@@ -874,7 +874,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
// function has a strong exception guarantee if __begin_ == __p || __end_ == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type>& __v, pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
@@ -1074,7 +1074,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer<value_type, allocator_type&> __v(__n, size(), this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__n, size(), this->__alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1085,7 +1085,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, allocator_type&> __v(size(), size(), this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(size(), size(), this->__alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1102,7 +1102,7 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
__alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
@@ -1205,7 +1205,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1224,7 +1224,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1245,7 +1245,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1273,7 +1273,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1294,11 +1294,11 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
if (__first == __last)
(void)std::rotate(__p, __old_last, this->__end_);
else {
- __split_buffer<value_type, allocator_type&> __v(__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__alloc_);
auto __guard = std::__make_exception_guard(
_AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, this->__end_));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
- __split_buffer<value_type, allocator_type&> __merged(
+ __split_buffer<value_type, allocator_type> __merged(
__recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
__alloc_, std::__to_address(__old_last), std::__to_address(this->__end_), std::__to_address(__merged.end()));
@@ -1344,7 +1344,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1359,7 +1359,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
@@ -1375,7 +1375,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer<value_type, allocator_type> __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
diff --git a/libcxx/include/deque b/libcxx/include/deque
index ad2d759e1fcac..befe27bb4282d 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1785,9 +1785,9 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI typename deque<_Tp, _Allocator>::iterator
deque<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l) {
- __split_buffer<value_type, allocator_type&> __buf(__alloc());
+ __split_buffer<value_type, allocator_type> __buf(__alloc());
__buf.__construct_at_end_with_sentinel(std::move(__f), std::move(__l));
- typedef typename __split_buffer<value_type, allocator_type&>::iterator __bi;
+ typedef typename __split_buffer<value_type, allocator_type>::iterator __bi;
return insert(__p, move_iterator<__bi>(__buf.begin()), move_iterator<__bi>(__buf.end()));
}
@@ -1802,9 +1802,9 @@ template <class _Tp, class _Allocator>
template <class _Iterator>
_LIBCPP_HIDE_FROM_ABI typename deque<_Tp, _Allocator>::iterator
deque<_Tp, _Allocator>::__insert_with_size(const_iterator __p, _Iterator __f, size_type __n) {
- __split_buffer<value_type, allocator_type&> __buf(__n, 0, __alloc());
+ __split_buffer<value_type, allocator_type> __buf(__n, 0, __alloc());
__buf.__construct_at_end_with_size(__f, __n);
- typedef typename __split_buffer<value_type, allocator_type&>::iterator __fwd;
+ typedef typename __split_buffer<value_type, allocator_type>::iterator __fwd;
return insert(__p, move_iterator<__fwd>(__buf.begin()), move_iterator<__fwd>(__buf.end()));
}
@@ -1982,7 +1982,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() {
...
[truncated]
|
|
@junov-google Are you able to verify whether this indeed fixes your issue with Swift interop? |
Actually, I was able to reproduce your issue myself and I can confirm it solves it! Note that I had to remove |
Confirmed. I applied the change on top of my WIP tests for swift/C++ interop in the Chromium project, and I can confirm that this PR fixes the issue. This probably also unblocks apple-llvm's next update. |
|
Just for awareness, this is the test I am checking in downstream: commit 678dff31fc3aa4cca8af265a0205b6392027480d
Author: Louis Dionne <[email protected]>
Date: Wed Dec 10 14:26:41 2025 -0500
[libc++] Add reproducer for swiftlang/swift#85820
diff --git a/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/foo.h b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/foo.h
new file mode 100644
index 000000000000..58a15627ea18
--- /dev/null
+++ b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/foo.h
@@ -0,0 +1,11 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+inline std::vector<int> GetOneTwoThree() { return {1, 2, 3}; }
diff --git a/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/main.swift b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/main.swift
new file mode 100644
index 000000000000..b88674cf2c1b
--- /dev/null
+++ b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/main.swift
@@ -0,0 +1,14 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+import Foo
+
+public func testingOneTwoThree() {
+ let v = GetOneTwoThree()
+ print(v.size())
+}
diff --git a/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/module.modulemap b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/module.modulemap
new file mode 100644
index 000000000000..57c5884f0437
--- /dev/null
+++ b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/module.modulemap
@@ -0,0 +1,4 @@
+module Foo {
+ header "foo.h"
+ export *
+}
diff --git a/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/repro.sh.cpp b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/repro.sh.cpp
new file mode 100644
index 000000000000..109655663fd6
--- /dev/null
+++ b/libcxx/test/libcxx/vendor/apple/swift-interop/swiftlang-85820/repro.sh.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// This test requires access to the Swift compiler, which we assume is only available on Apple platforms for now.
+// REQUIRES: buildhost=darwin
+
+// Reproducer for https://github.com/swiftlang/swift/issues/85820
+//
+// RUN: swiftc -cxx-interoperability-mode=default -Xcc -nostdinc++ -Xcc -isystem -Xcc "%{include-dir}" \
+// RUN: -Xcc -fmodule-map-file=%S/module.modulemap -Xcc -std=c++20 %S/main.swiftI'm not upstreaming that because we don't currently have a policy for officially supporting any interop with other languages, so for now I am building up a downstream suite to track these issues. |
Allocators should be extremely cheap, if not free, to copy. Furthermore, we have requirements on allocator types that copies must compare equal, and that move and copy must be the same.
Hence, taking an allocator by reference should not provide benefits beyond making a copy of it. However, taking the allocator by reference leads to complexity in __split_buffer, which can be removed if we stop using that pattern.