Skip to content

Commit c624455

Browse files
Switch to use internally rebinding
1 parent 6080007 commit c624455

File tree

1 file changed

+44
-19
lines changed

1 file changed

+44
-19
lines changed

libcxx/include/deque

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,14 @@ template <class T, class Allocator, class Predicate>
227227
# include <__type_traits/disjunction.h>
228228
# include <__type_traits/enable_if.h>
229229
# include <__type_traits/is_allocator.h>
230+
# include <__type_traits/is_const.h>
230231
# include <__type_traits/is_convertible.h>
231232
# include <__type_traits/is_nothrow_assignable.h>
232233
# include <__type_traits/is_nothrow_constructible.h>
233234
# include <__type_traits/is_same.h>
234235
# include <__type_traits/is_swappable.h>
235236
# include <__type_traits/is_trivially_relocatable.h>
237+
# include <__type_traits/remove_reference.h>
236238
# include <__type_traits/type_identity.h>
237239
# include <__utility/forward.h>
238240
# include <__utility/move.h>
@@ -269,6 +271,15 @@ struct __deque_block_size {
269271
static const _DiffType value = sizeof(_ValueType) < 256 ? 4096 / sizeof(_ValueType) : 16;
270272
};
271273

274+
// When using fancy pointers, _MapPointer can be FancyPtr<const FancyPtr<const _ValueType>>, which causes strict
275+
// aliasing violation in direct dereferencing because the internal map stores FancyPtr<_ValueType> objects.
276+
// We need to transform the type to something like FancyPtr<const FancyPtr<_ValueType>>.
277+
template <class _ValueType, class _MapPointer>
278+
using __get_deque_map_iterator _LIBCPP_NODEBUG =
279+
conditional_t<is_const<__libcpp_remove_reference_t<decltype(**_MapPointer())> >::value,
280+
__rebind_pointer_t<_MapPointer, const __rebind_pointer_t<_MapPointer, _ValueType> >,
281+
_MapPointer>;
282+
272283
template <class _ValueType,
273284
class _Pointer,
274285
class _Reference,
@@ -284,7 +295,7 @@ template <class _ValueType,
284295
# endif
285296
>
286297
class __deque_iterator {
287-
typedef _MapPointer __map_iterator;
298+
using __map_iterator _LIBCPP_NODEBUG = __get_deque_map_iterator<_ValueType, _MapPointer>;
288299

289300
public:
290301
typedef _Pointer pointer;
@@ -461,7 +472,7 @@ private:
461472

462473
public:
463474
using __is_segmented_iterator _LIBCPP_NODEBUG = true_type;
464-
using __segment_iterator _LIBCPP_NODEBUG = _MapPointer;
475+
using __segment_iterator _LIBCPP_NODEBUG = __get_deque_map_iterator<_ValueType, _MapPointer>;
465476
using __local_iterator _LIBCPP_NODEBUG = _Pointer;
466477

467478
static _LIBCPP_HIDE_FROM_ABI __segment_iterator __segment(_Iterator __iter) { return __iter.__m_iter_; }
@@ -504,18 +515,27 @@ public:
504515
using pointer = typename __alloc_traits::pointer;
505516
using const_pointer = typename __alloc_traits::const_pointer;
506517

507-
using __pointer_allocator _LIBCPP_NODEBUG = __rebind_alloc<__alloc_traits, pointer>;
508-
using __map _LIBCPP_NODEBUG = __split_buffer<pointer, __pointer_allocator>;
509-
using __map_alloc_traits _LIBCPP_NODEBUG = allocator_traits<__pointer_allocator>;
510-
using __map_pointer _LIBCPP_NODEBUG = typename __map_alloc_traits::pointer;
511-
using __map_const_pointer _LIBCPP_NODEBUG = typename allocator_traits<__pointer_allocator>::const_pointer;
512-
using __map_const_iterator _LIBCPP_NODEBUG = typename __map::const_iterator;
518+
using __pointer_allocator _LIBCPP_NODEBUG = __rebind_alloc<__alloc_traits, pointer>;
519+
using __const_pointer_allocator _LIBCPP_NODEBUG = __rebind_alloc<__alloc_traits, const_pointer>;
520+
using __map _LIBCPP_NODEBUG = __split_buffer<pointer, __pointer_allocator>;
521+
using __map_alloc_traits _LIBCPP_NODEBUG = allocator_traits<__pointer_allocator>;
522+
using __map_pointer _LIBCPP_NODEBUG = typename __map_alloc_traits::pointer;
523+
using __map_const_iterator _LIBCPP_NODEBUG = typename __map::const_iterator;
524+
525+
// Direct dereferencing __map_const_pointer possibly causes strict aliasing violation.
526+
// We need to transform it to something like __map_alloc_traits::const_pointer for the const_iterator.
527+
using __map_const_pointer _LIBCPP_NODEBUG = typename allocator_traits<__const_pointer_allocator>::const_pointer;
528+
using __map_proper_const_pointer _LIBCPP_NODEBUG = typename __map_alloc_traits::const_pointer;
529+
530+
using __iter_proper_const_pointer _LIBCPP_NODEBUG = __get_deque_map_iterator<_Tp, __map_const_pointer>;
531+
static_assert(is_same<decltype(*__iter_proper_const_pointer()), const pointer&>::value,
532+
"The fancy pointer types provided by the allocators cannot be restored by pointer_traits::rebind.");
513533

514534
using reference = value_type&;
515535
using const_reference = const value_type&;
516536

517-
using iterator = __deque_iterator<value_type, pointer, reference, __map_pointer, difference_type>;
518-
using const_iterator =
537+
using iterator = __deque_iterator<value_type, pointer, reference, __map_pointer, difference_type>;
538+
using const_iterator = // Use of __map_const_pointer is merely kept for API stability.
519539
__deque_iterator<value_type, const_pointer, const_reference, __map_const_pointer, difference_type>;
520540
using reverse_iterator = std::reverse_iterator<iterator>;
521541
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -596,6 +616,10 @@ private:
596616
deque* const __base_;
597617
};
598618

619+
static __iter_proper_const_pointer __map_const_ptr_to_iter_const_ptr(__map_proper_const_pointer __mp) _NOEXCEPT {
620+
return __mp ? pointer_traits<__iter_proper_const_pointer>::pointer_to(*__mp) : nullptr;
621+
}
622+
599623
static const difference_type __block_size;
600624

601625
__map __map_;
@@ -720,8 +744,9 @@ public:
720744
}
721745

722746
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
723-
__map_const_pointer __mp = __map_.begin() + __start_ / __block_size;
724-
return const_iterator(__mp, __map_.empty() ? 0 : *__mp + __start_ % __block_size);
747+
__map_proper_const_pointer __mp = __map_.begin() + __start_ / __block_size;
748+
return const_iterator(
749+
__map_const_ptr_to_iter_const_ptr(__mp), __map_.empty() ? 0 : *__mp + __start_ % __block_size);
725750
}
726751

727752
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
@@ -731,9 +756,9 @@ public:
731756
}
732757

733758
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
734-
size_type __p = size() + __start_;
735-
__map_const_pointer __mp = __map_.begin() + __p / __block_size;
736-
return const_iterator(__mp, __map_.empty() ? 0 : *__mp + __p % __block_size);
759+
size_type __p = size() + __start_;
760+
__map_proper_const_pointer __mp = __map_.begin() + __p / __block_size;
761+
return const_iterator(__map_const_ptr_to_iter_const_ptr(__mp), __map_.empty() ? 0 : *__mp + __p % __block_size);
737762
}
738763

739764
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
@@ -2330,7 +2355,7 @@ deque<_Tp, _Allocator>::__move_and_check(iterator __f, iterator __l, iterator __
23302355
__fe = __fb + __bs;
23312356
}
23322357
if (__fb <= __vt && __vt < __fe)
2333-
__vt = (const_iterator(static_cast<__map_const_pointer>(__f.__m_iter_), __vt) -= __f - __r).__ptr_;
2358+
__vt = (const_iterator(__map_const_ptr_to_iter_const_ptr(__f.__m_iter_), __vt) -= __f - __r).__ptr_;
23342359
__r = std::move(__fb, __fe, __r);
23352360
__n -= __bs;
23362361
__f += __bs;
@@ -2357,7 +2382,7 @@ deque<_Tp, _Allocator>::__move_backward_and_check(iterator __f, iterator __l, it
23572382
__lb = __le - __bs;
23582383
}
23592384
if (__lb <= __vt && __vt < __le)
2360-
__vt = (const_iterator(static_cast<__map_const_pointer>(__l.__m_iter_), __vt) += __r - __l - 1).__ptr_;
2385+
__vt = (const_iterator(__map_const_ptr_to_iter_const_ptr(__l.__m_iter_), __vt) += __r - __l - 1).__ptr_;
23612386
__r = std::move_backward(__lb, __le, __r);
23622387
__n -= __bs;
23632388
__l -= __bs - 1;
@@ -2383,7 +2408,7 @@ void deque<_Tp, _Allocator>::__move_construct_and_check(iterator __f, iterator _
23832408
__fe = __fb + __bs;
23842409
}
23852410
if (__fb <= __vt && __vt < __fe)
2386-
__vt = (const_iterator(static_cast<__map_const_pointer>(__f.__m_iter_), __vt) += __r - __f).__ptr_;
2411+
__vt = (const_iterator(__map_const_ptr_to_iter_const_ptr(__f.__m_iter_), __vt) += __r - __f).__ptr_;
23872412
for (; __fb != __fe; ++__fb, ++__r, ++__size())
23882413
__alloc_traits::construct(__a, std::addressof(*__r), std::move(*__fb));
23892414
__n -= __bs;
@@ -2415,7 +2440,7 @@ void deque<_Tp, _Allocator>::__move_construct_backward_and_check(
24152440
__lb = __le - __bs;
24162441
}
24172442
if (__lb <= __vt && __vt < __le)
2418-
__vt = (const_iterator(static_cast<__map_const_pointer>(__l.__m_iter_), __vt) -= __l - __r + 1).__ptr_;
2443+
__vt = (const_iterator(__map_const_ptr_to_iter_const_ptr(__l.__m_iter_), __vt) -= __l - __r + 1).__ptr_;
24192444
while (__le != __lb) {
24202445
__alloc_traits::construct(__a, std::addressof(*--__r), std::move(*--__le));
24212446
--__start_;

0 commit comments

Comments
 (0)