@@ -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+
272283template <class _ValueType ,
273284 class _Pointer ,
274285 class _Reference ,
@@ -284,7 +295,7 @@ template <class _ValueType,
284295# endif
285296 >
286297class __deque_iterator {
287- typedef _MapPointer __map_iterator;
298+ using __map_iterator _LIBCPP_NODEBUG = __get_deque_map_iterator<_ValueType, _MapPointer> ;
288299
289300public:
290301 typedef _Pointer pointer;
@@ -461,7 +472,7 @@ private:
461472
462473public:
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