diff --git a/compiler-rt/lib/asan/asan_poisoning.cpp b/compiler-rt/lib/asan/asan_poisoning.cpp --- a/compiler-rt/lib/asan/asan_poisoning.cpp +++ b/compiler-rt/lib/asan/asan_poisoning.cpp @@ -490,7 +490,7 @@ void __sanitizer_annotate_double_ended_contiguous_container_back( const void *storage_beg_p, const void *storage_end_p, const void *old_container_beg_p, const void *old_container_end_p, - const void *new_container_end_p, const void *new_container_beg_p) { + const void *new_container_beg_p, const void *new_container_end_p) { // Unchecked argument requirements: // During unpoisoning memory of empty container (before first element is // added): diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -1280,6 +1280,9 @@ class _LIBCPP_TEMPLATE_VIS deque : private __deque_base<_Tp, _Allocator> { +private: + using __default_allocator_type = allocator<_Tp>; + public: // types: @@ -1310,10 +1313,8 @@ // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY - deque() - _NOEXCEPT_(is_nothrow_default_constructible::value) - {} - _LIBCPP_INLINE_VISIBILITY explicit deque(const allocator_type& __a) : __base(__a) {} + deque() _NOEXCEPT_(is_nothrow_default_constructible::value) { __annotate_new(0); } + _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a) : __base(__a) { __annotate_new(0); } explicit deque(size_type __n); #if _LIBCPP_STD_VER > 11 explicit deque(size_type __n, const _Allocator& __a); @@ -1323,8 +1324,9 @@ template ::value> > deque(size_type __n, const value_type& __v, const allocator_type& __a) : __base(__a) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -1529,75 +1531,418 @@ } private: - _LIBCPP_INLINE_VISIBILITY - bool __maybe_remove_front_spare(bool __keep_one = true) { - if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { - __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), - __base::__block_size); - __base::__map_.pop_front(); - __base::__start_ -= __base::__block_size; - return true; - } - return false; - } + // Implementation based on the one from std::vector. + // + // The following functions are no-ops outside of AddressSanitizer mode. + // We call annotatations only for the default Allocator because other allocators + // may not meet the AddressSanitizer alignment constraints. + // See the documentation for __sanitizer_annotate_contiguous_container for more details. +#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 16000 + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_front( + const void* __beg, + const void* __end, + const void* __new_con_beg, + const void* __old_con_beg, + const void* __con_end) const { + // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block. + if (__beg && is_same::value) + __sanitizer_annotate_double_ended_contiguous_container( + __beg, __end, __old_con_beg, __con_end, __new_con_beg, __con_end); + } + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_back( + const void* __beg, + const void* __end, + const void* __old_con_end, + const void* __new_con_end, + const void* __con_beg) const { + // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block + if (__beg && is_same::value) + __sanitizer_annotate_double_ended_contiguous_container( + __beg, __end, __con_beg, __old_con_end, __con_beg, __new_con_end); + } +#else + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_front( + const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_back( + const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} +#endif // !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 16000 + + _LIBCPP_HIDE_FROM_ABI + // __b - index of first item in __map_ to annotate + // __e - index behind the last item in __map_ to annotate (so last item + 1) + void __annotate_poison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // __mp - ponter to the first chunk which annotations we want to modify. + // __last_mp - pointer to the last chunk which annotations we want to modify. + // If ony one chunk if affected, __mp == __last_mp + // We use (__e - 1) in calculations, because if we poison to the very end of chunk, + // we still want to point at that chunk and not the next one. Using __e, would + // point at the memory for the next element, which may be in a next chunk. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + + // We iterate over map pointers and fully poison all blocks between the first and the last. + // The first block is partialy poisoned here as well. + // The last one is poisoned after the while loop. + while (__mp != __last_mp) { + // Pointer to chunk's/block's beginning + const void* __p_t_b = std::__to_address(*__mp); + // Pointer to chunk's/block's end + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + // We are poisoning rest of the blocks memory, therefore end of block is last argument. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_t_e); + // Poisoned memory: [__p, __p_t_e] + + __mp += 1; + __p_b = std::__to_address(*__mp); + } + + // If __last_block_index is zero, then we should point to the end of a chunk (one of its contiguous blocks). + size_type __last_block_index = __e % __base::__block_size; + + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + + // Poisoning happens after the container modification, so the size + // was already changed and may be 0 but we still have to poison the cleared blocks. + if (__last_block_index == 0 || size() == 0) + // Read comments in __annotate_contiguous_container_front for empty block argument requrements. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_e); + else { + // Due to current limitations of ASan, it only matters if container is empty or not, + // therefore we do not have to calculate true end of the container in the block (better performance), + // but if poisoning prefixes are implemented in Asan, we will have to pass correct end of memory in use + // inside that chunk, instead of just end of the allocated memory. (Last argument.) + // + // Correct end of container is passed to __annotate_contiguous_container_front, but it + // may be changes to __p_t_e for better performance. + // __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p, __p_t_e); + if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { + // End of the container is in the block which we are poisoning. + const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_e); + } else + // End of the container is in a different chunk, rest of chunk is in use. + // Therefore last argument is end of chunk. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_t_e); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_unpoison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + while (__mp != __last_mp) { + // Pointer to block's beginning + const void* __p_t_b = std::__to_address(*__mp); + // Pointer to block's end + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_t_e); + + __mp += 1; + __p_b = std::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + + // unpoison happens before the size is changed + // so we have to unpoison the block before its modified + if (__last_block_index == 0 || size() == 0) + __annotate_contiguous_container_front(__p_t_b, __p_e, __p_b, __p_e, __p_e); + else { + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { + const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_e); + } else + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_t_e); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_poison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + const void* __p_c_b; + // Poisoning happens after container modification and size updated. + if (size() == 0) + __p_c_b = __p_b; + else { + if (__base::__start_ / __base::__block_size == __b / __base::__block_size) + // Container starts in the block we are about to poison. + __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); + else + // Container starts in a different block. + __p_c_b = std::__to_address(*__mp); + } + while (__mp != __last_mp) { + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_c_b); + + __mp += 1; + __p_c_b = __p_b = std::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + // Poisoning happens after elemests were removed. + if (size() == 0) + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_b); + else + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_b); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_unpoison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); + const void* __p_c_b; + // Unpoisoning happens befor container modification and size updated. + if (size() == 0) + __p_c_b = __p_b; + else { + if (__base::__start_ / __base::__block_size == __b / __base::__block_size) + // Container starts in the block we are about to poison. + __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); + else + // Container starts in a different block. + __p_c_b = std::__to_address(*__mp); + } + + while (__mp != __last_mp) { + const void* __p_t_b = _VSTD::__to_address(*__mp); + const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_c_b); + + __mp += 1; + __p_c_b = __p_b = _VSTD::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + const void* __p_e = + _VSTD::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = _VSTD::__to_address(*__mp); + const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_b); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_new(size_type __current_size) const _NOEXCEPT { + if (__current_size == 0) + __annotate_poison_from_to_back(0, __base::__map_.size() * __base::__block_size); + else { + // This branch is never reached in current implementation because + // __annotate_new is always called with 0, + // but let's leave it here in case anyone needs to use + // __annotate_new(n) in the future + __annotate_poison_from_to_front(0, __base::__start_); + __annotate_poison_from_to_back(__base::__start_ + __current_size, __base::__map_.size() * __base::__block_size); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_delete() const _NOEXCEPT { + if (!empty()) { + __annotate_unpoison_from_to_front(0, __base::__start_); + __annotate_unpoison_from_to_back( + __base::__start_ + __base::size(), __base::__map_.size() * __base::__block_size); + } else + __annotate_unpoison_from_to_back(0, __base::__map_.size() * __base::__block_size); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_front(size_type __n) const _NOEXCEPT { + __annotate_unpoison_from_to_front(__base::__start_ - __n, __base::__start_); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_back(size_type __n) const _NOEXCEPT { + __annotate_unpoison_from_to_back(__base::__start_ + __base::size(), __base::__start_ + __base::size() + __n); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_poison_from_to_front(__old_start, __old_start + (__old_size - size())); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_poison_from_to_back(__old_start + size(), __old_start + __old_size); + } + +// This macro should be defined only during testing ASAN. +// Include the "asan_testing.h" file which defines it +// to be able to use it in ASan tests. +#ifdef _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS - _LIBCPP_INLINE_VISIBILITY - bool __maybe_remove_back_spare(bool __keep_one = true) { - if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { - __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), - __base::__block_size); - __base::__map_.pop_back(); - return true; +public: + bool __verify_asan_annotations() const _NOEXCEPT { + // This function tests deque object annotations. + // This test is simplified, it tests only if: + // - memory owned by deque (deque blocks) not containig alements is poisoned. + // - memory owned by deque elements is accessible. + // + // Therefore you cannot test, with that function, deque containing objects + // which memory may be partialy (or fully) poisoned, like std::string (SSO case). + // You can test std::vector or long std::string. + + if (empty()) { + for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); + ++__it) + if (!__sanitizer_verify_double_ended_contiguous_container(*__it, *__it, *__it, *__it + __base::__block_size)) + return false; + + return true; + } + + size_type __e = __base::__start_ + __base::size(); + typename __base::__map_traits::const_pointer __first_mp = + __base::__map_.begin() + __base::__start_ / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + // Pointers to first and last elements + // They can be in *different deque blocks* + pointer __p_first = *__first_mp + (__base::__start_ % __base::__block_size); + pointer __p_last = + *__last_mp + ((__e % __base::__block_size == 0) ? __base::__block_size : __e % __base::__block_size); + + for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); + ++__it) { + // Go over all blocks, find the place we are in and verify its annotations + // Note that __p_last points *behind* the last item. + + // - blocks before the first block with container elements + // - first block with items + // - last block with items + // - blocks after last block with ciontainer elements + + // Is the block before or after deque blocks that contain elements? + if (__it < __first_mp || __it > __last_mp) { + if (!__sanitizer_verify_double_ended_contiguous_container(*__it, *__it, *__it, (*__it + __base::__block_size))) + return false; } - return false; - } - - template - void __append(_InpIter __f, _InpIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); - template - void __append(_ForIter __f, _ForIter __l, - typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); - void __append(size_type __n); - void __append(size_type __n, const value_type& __v); - void __erase_to_end(const_iterator __f); - void __add_front_capacity(); - void __add_front_capacity(size_type __n); - void __add_back_capacity(); - void __add_back_capacity(size_type __n); - iterator __move_and_check(iterator __f, iterator __l, iterator __r, - const_pointer& __vt); - iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, - const_pointer& __vt); - void __move_construct_and_check(iterator __f, iterator __l, - iterator __r, const_pointer& __vt); - void __move_construct_backward_and_check(iterator __f, iterator __l, - iterator __r, const_pointer& __vt); - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque& __c) - {__copy_assign_alloc(__c, integral_constant());} - - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque& __c, true_type) + else { + // Is the block the first block that contains elements? + pointer __con_beg = (__it == __first_mp) ? __p_first : *__it; + // Is it the last one? + pointer __con_end = (__it == __last_mp) ? __p_last : (*__it + __base::__block_size); { - if (__base::__alloc() != __c.__alloc()) - { - clear(); - shrink_to_fit(); - } - __base::__alloc() = __c.__alloc(); - __base::__map_.__alloc() = __c.__map_.__alloc(); + if (!__sanitizer_verify_double_ended_contiguous_container( + *__it, __con_beg, __con_end, (*__it + __base::__block_size))) + return false; } + } + } - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque&, false_type) - {} + return true; + } + +private: +#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS + + _LIBCPP_INLINE_VISIBILITY + bool __maybe_remove_front_spare(bool __keep_one = true) { + if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { + __annotate_unpoison_from_to_back(0, __base::__block_size); + __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), __base::__block_size); + __base::__map_.pop_front(); + __base::__start_ -= __base::__block_size; + return true; + } + return false; + } + + _LIBCPP_INLINE_VISIBILITY + bool __maybe_remove_back_spare(bool __keep_one = true) { + if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { + __annotate_unpoison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), __base::__block_size); + __base::__map_.pop_back(); + return true; + } + return false; + } + + template + void __append(_InpIter __f, + _InpIter __l, + typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); + template + void + __append(_ForIter __f, _ForIter __l, typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); + void __append(size_type __n); + void __append(size_type __n, const value_type& __v); + void __erase_to_end(const_iterator __f); + void __add_front_capacity(); + void __add_front_capacity(size_type __n); + void __add_back_capacity(); + void __add_back_capacity(size_type __n); + iterator __move_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + void __move_construct_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + void __move_construct_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque& __c) { + __copy_assign_alloc(__c, integral_constant()); + } + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque& __c, true_type) { + if (__base::__alloc() != __c.__alloc()) { + clear(); + shrink_to_fit(); + } + __base::__alloc() = __c.__alloc(); + __base::__map_.__alloc() = __c.__map_.__alloc(); + } + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque&, false_type) {} + + void __move_assign(deque& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); + void __move_assign(deque& __c, false_type); - void __move_assign(deque& __c, true_type) - _NOEXCEPT_(is_nothrow_move_assignable::value); - void __move_assign(deque& __c, false_type); +public: + ~deque() { __annotate_delete(); } }; #if _LIBCPP_STD_VER >= 17 @@ -1621,8 +1966,9 @@ template deque<_Tp, _Allocator>::deque(size_type __n) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #if _LIBCPP_STD_VER > 11 @@ -1630,16 +1976,18 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) : __base(__a) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #endif template deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -1647,7 +1995,8 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template @@ -1656,21 +2005,24 @@ typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) : __base(__a) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template deque<_Tp, _Allocator>::deque(const deque& __c) : __base(__alloc_traits::select_on_container_copy_construction(__c.__alloc())) { - __append(__c.begin(), __c.end()); + __annotate_new(0); + __append(__c.begin(), __c.end()); } template deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t& __a) : __base(__a) { - __append(__c.begin(), __c.end()); + __annotate_new(0); + __append(__c.begin(), __c.end()); } template @@ -1690,14 +2042,16 @@ template deque<_Tp, _Allocator>::deque(initializer_list __il) { - __append(__il.begin(), __il.end()); + __annotate_new(0); + __append(__il.begin(), __il.end()); } template deque<_Tp, _Allocator>::deque(initializer_list __il, const allocator_type& __a) : __base(__a) { - __append(__il.begin(), __il.end()); + __annotate_new(0); + __append(__il.begin(), __il.end()); } template @@ -1839,12 +2193,13 @@ allocator_type& __a = __base::__alloc(); if (empty()) { - while (__base::__map_.size() > 0) - { - __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); - __base::__map_.pop_back(); - } + __annotate_delete(); + while (__base::__map_.size() > 0) { + __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); + __base::__map_.pop_back(); + } __base::__start_ = 0; + __annotate_new(0); } else { @@ -1938,6 +2293,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), __v); ++__base::size(); } @@ -1950,6 +2306,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); --__base::__start_; ++__base::size(); @@ -1964,6 +2321,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::move(__v)); ++__base::size(); } @@ -1981,6 +2339,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::forward<_Args>(__args)...); ++__base::size(); @@ -1997,6 +2356,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); --__base::__start_; ++__base::size(); @@ -2016,6 +2376,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); --__base::__start_; ++__base::size(); @@ -2036,6 +2397,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); @@ -2059,6 +2421,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2092,6 +2455,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); @@ -2116,6 +2480,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2152,6 +2517,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); @@ -2178,6 +2544,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2213,6 +2580,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = __base::begin(); iterator __i = __old_begin; if (__n > __pos) @@ -2237,6 +2605,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = __base::end(); iterator __i = __old_end; size_type __de = __base::size() - __pos; @@ -2299,6 +2668,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = __base::begin(); iterator __i = __old_begin; _BiIter __m = __f; @@ -2329,6 +2699,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = __base::end(); iterator __i = __old_end; _BiIter __m = __l; @@ -2379,6 +2750,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) { @@ -2396,6 +2768,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -2413,6 +2786,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -2454,6 +2828,7 @@ __base::__start_ = __base::__map_.size() == 1 ? __base::__block_size / 2 : __base::__start_ + __base::__block_size; + __annotate_poison_from_to_back(0, __base::__block_size); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -2479,6 +2854,7 @@ __base::__start_ = __base::__map_.size() == 1 ? __base::__block_size / 2 : __base::__start_ + __base::__block_size; + __annotate_poison_from_to_back(0, __base::__block_size); } } @@ -2515,6 +2891,7 @@ if (__base::__map_.__front_spare() == 0) break; __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back(0, __base::__block_size); } for (; __nb > 0; --__nb, ++__back_capacity) __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); @@ -2525,6 +2902,7 @@ pointer __pt = __base::__map_.back(); __base::__map_.pop_back(); __base::__map_.push_front(__pt); + __annotate_poison_from_to_back(0, __base::__block_size); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -2539,16 +2917,24 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) - __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + for (; __nb > 0; --__nb) { + __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_contiguous_container_back( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back()), + std::__to_address(__buf.back())); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - for (typename __base::__map_pointer __i = __buf.begin(); - __i != __buf.end(); ++__i) - __alloc_traits::deallocate(__a, *__i, __base::__block_size); - throw; + __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); + throw; } #endif // _LIBCPP_NO_EXCEPTIONS for (; __back_capacity > 0; --__back_capacity) @@ -2596,6 +2982,8 @@ __base::__map_.pop_front(); __base::__map_.push_back(__pt); } + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -2619,6 +3007,8 @@ _VSTD::swap(__base::__map_.__begin_, __buf.__begin_); _VSTD::swap(__base::__map_.__end_, __buf.__end_); _VSTD::swap(__base::__map_.__end_cap(), __buf.__end_cap()); + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); } } @@ -2655,10 +3045,14 @@ if (__base::__map_.__back_spare() == 0) break; __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + } + for (; __nb > 0; + --__nb, ++__front_capacity, __base::__start_ += __base::__block_size - (__base::__map_.size() == 1)) { + __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back(0, __base::__block_size); } - for (; __nb > 0; --__nb, ++__front_capacity, __base::__start_ += - __base::__block_size - (__base::__map_.size() == 1)) - __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); // Done allocating, reorder capacity __base::__start_ -= __base::__block_size * __front_capacity; for (; __front_capacity > 0; --__front_capacity) @@ -2681,16 +3075,24 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) - __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + for (; __nb > 0; --__nb) { + __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_contiguous_container_back( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back()), + std::__to_address(__buf.back())); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - for (typename __base::__map_pointer __i = __buf.begin(); - __i != __buf.end(); ++__i) - __alloc_traits::deallocate(__a, *__i, __base::__block_size); - throw; + __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); + throw; } #endif // _LIBCPP_NO_EXCEPTIONS for (; __front_capacity > 0; --__front_capacity) @@ -2713,13 +3115,16 @@ void deque<_Tp, _Allocator>::pop_front() { - allocator_type& __a = __base::__alloc(); - __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + - __base::__start_ / __base::__block_size) + - __base::__start_ % __base::__block_size)); - --__base::size(); - ++__base::__start_; - __maybe_remove_front_spare(); + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + allocator_type& __a = __base::__alloc(); + __alloc_traits::destroy(__a, + _VSTD::__to_address(*(__base::__map_.begin() + __base::__start_ / __base::__block_size) + + __base::__start_ % __base::__block_size)); + --__base::size(); + ++__base::__start_; + __annotate_shrink_front(__old_sz, __old_start); + __maybe_remove_front_spare(); } template @@ -2727,12 +3132,15 @@ deque<_Tp, _Allocator>::pop_back() { _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; allocator_type& __a = __base::__alloc(); size_type __p = __base::size() + __base::__start_ - 1; __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + __p / __base::__block_size) + __p % __base::__block_size)); --__base::size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } @@ -2872,25 +3280,26 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) { - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - iterator __p = __b + __pos; - allocator_type& __a = __base::__alloc(); - if (static_cast(__pos) <= (__base::size() - 1) / 2) - { // erase from front - _VSTD::move_backward(__b, __p, _VSTD::next(__p)); - __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); - --__base::size(); - ++__base::__start_; - __maybe_remove_front_spare(); - } - else - { // erase from back - iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); - __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); - --__base::size(); - __maybe_remove_back_spare(); - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + iterator __p = __b + __pos; + allocator_type& __a = __base::__alloc(); + if (static_cast(__pos) <= (__base::size() - 1) / 2) { // erase from front + _VSTD::move_backward(__b, __p, _VSTD::next(__p)); + __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); + --__base::size(); + ++__base::__start_; + __annotate_shrink_front(__old_sz, __old_start); + __maybe_remove_front_spare(); + } else { // erase from back + iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); + __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); + --__base::size(); + __annotate_shrink_back(__old_sz, __old_start); + __maybe_remove_back_spare(); + } return __base::begin() + __pos; } @@ -2898,33 +3307,33 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) { - difference_type __n = __l - __f; - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - iterator __p = __b + __pos; - if (__n > 0) - { - allocator_type& __a = __base::__alloc(); - if (static_cast(__pos) <= (__base::size() - __n) / 2) - { // erase from front - iterator __i = _VSTD::move_backward(__b, __p, __p + __n); - for (; __b != __i; ++__b) - __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); - __base::size() -= __n; - __base::__start_ += __n; - while (__maybe_remove_front_spare()) { - } - } - else - { // erase from back - iterator __i = _VSTD::move(__p + __n, __base::end(), __p); - for (iterator __e = __base::end(); __i != __e; ++__i) - __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); - __base::size() -= __n; - while (__maybe_remove_back_spare()) { - } - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + difference_type __n = __l - __f; + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + iterator __p = __b + __pos; + if (__n > 0) { + allocator_type& __a = __base::__alloc(); + if (static_cast(__pos) <= (__base::size() - __n) / 2) { // erase from front + iterator __i = _VSTD::move_backward(__b, __p, __p + __n); + for (; __b != __i; ++__b) + __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); + __base::size() -= __n; + __base::__start_ += __n; + __annotate_shrink_front(__old_sz, __old_start); + while (__maybe_remove_front_spare()) { + } + } else { // erase from back + iterator __i = _VSTD::move(__p + __n, __base::end(), __p); + for (iterator __e = __base::end(); __i != __e; ++__i) + __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); + __base::size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); + while (__maybe_remove_back_spare()) { + } } + } return __base::begin() + __pos; } @@ -2932,19 +3341,21 @@ void deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) { - iterator __e = __base::end(); - difference_type __n = __e - __f; - if (__n > 0) - { - allocator_type& __a = __base::__alloc(); - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - for (iterator __p = __b + __pos; __p != __e; ++__p) - __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); - __base::size() -= __n; - while (__maybe_remove_back_spare()) { - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + iterator __e = __base::end(); + difference_type __n = __e - __f; + if (__n > 0) { + allocator_type& __a = __base::__alloc(); + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + for (iterator __p = __b + __pos; __p != __e; ++__p) + __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); + __base::size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); + while (__maybe_remove_back_spare()) { } + } } template @@ -2966,7 +3377,9 @@ void deque<_Tp, _Allocator>::clear() _NOEXCEPT { - __base::clear(); + __annotate_delete(); + __base::clear(); + __annotate_new(0); } template diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp @@ -0,0 +1,461 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +#if TEST_STD_VER >= 11 +template +void test_assign_d5(const size_t N) { + typedef std::deque D; + D empty_d5; + D short_d5a(1), short_d5b(N - 1); + D mid_d5(N + 1); + D long_d5(32 * N + 1); + + empty_d5.assign({T(), T()}); + short_d5a.assign({T(), T()}); + short_d5b.assign({T(), T()}); + mid_d5.assign({T(), T()}); + long_d5.assign({T(), T()}); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5)); + + empty_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d5a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d5b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + mid_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + long_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(empty_d5.size() > 16); + assert(short_d5a.size() > 16); + assert(short_d5b.size() > 16); + assert(mid_d5.size() > 16); + assert(long_d5.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5)); +} + +template +void test_assign_d6(const size_t N) { + typedef std::deque D; + D empty_d6; + D short_d6a(1), short_d6b(N - 1); + D mid_d6(N + 1); + D long_d6(32 * N + 1); + + empty_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d6a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d6b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + mid_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + long_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(empty_d6.size() > 16); + assert(short_d6a.size() > 16); + assert(short_d6b.size() > 16); + assert(mid_d6.size() > 16); + assert(long_d6.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6)); +} + +template +void test_assign_d7(const size_t N) { + typedef std::deque D; + const T val = T(); + D empty_d7; + D short_d7a(1), short_d7b(N - 1); + D mid_d7(N + 1); + D long_d7(32 * N + 1); + + empty_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + short_d7a.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + short_d7b.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + mid_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + long_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + + assert(empty_d7.size() > 16); + assert(short_d7a.size() > 16); + assert(short_d7b.size() > 16); + assert(mid_d7.size() > 16); + assert(long_d7.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d7)); + assert(is_double_ended_contiguous_container_asan_correct(long_d7)); +} +#endif // TEST_STD_VER >= 11 + +template +void test_assign() { + typedef std::deque D; + const size_t N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void assign( size_type count, const T& value ); + + D empty_d1; + D short_d1a(1), short_d1b(N - 1); + D mid_d1(N + 1); + D long_d1(32 * N + 1); + + empty_d1.assign(2, T()); + short_d1a.assign(2, T()); + short_d1b.assign(2, T()); + mid_d1.assign(2, T()); + long_d1.assign(2, T()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + + empty_d1.assign(2 * N, T()); + short_d1a.assign(2 * N, T()); + short_d1b.assign(2 * N, T()); + mid_d1.assign(2 * N, T()); + long_d1.assign(2 * N, T()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + + D empty_d2; + D short_d2a(1), short_d2b(N - 1); + D mid_d2(N + 1); + D long_d2(32 * N + 1); + + empty_d2.assign(42 * N, T()); + short_d2a.assign(42 * N, T()); + short_d2b.assign(42 * N, T()); + mid_d2.assign(42 * N, T()); + long_d2.assign(42 * N, T()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2)); + + // template< class InputIt > + // void assign( InputIt first, InputIt last ); + D source_d(50 * N); + + D empty_d3; + D short_d3a(1), short_d3b(N - 1); + D mid_d3(N + 1); + D long_d3(32 * N + 1); + + empty_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + short_d3a.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + short_d3b.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + mid_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + long_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3)); + assert(is_double_ended_contiguous_container_asan_correct(source_d)); + + empty_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + short_d3a.assign(source_d.begin() + N, source_d.begin() + 3 * N); + short_d3b.assign(source_d.begin() + N, source_d.begin() + 3 * N); + mid_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + long_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3)); + assert(is_double_ended_contiguous_container_asan_correct(source_d)); + + D empty_d4; + D short_d4a(1), short_d4b(N - 1); + D mid_d4(N + 1); + D long_d4(32 * N + 1); + + empty_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + short_d4a.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + short_d4b.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + mid_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + long_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); + assert(is_double_ended_contiguous_container_asan_correct(short_d4a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d4b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d4)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4)); + assert(is_double_ended_contiguous_container_asan_correct(source_d)); + +#if TEST_STD_VER >= 11 + // void assign( std::initializer_list ilist ); + test_assign_d5(N); + test_assign_d6(N); + test_assign_d7(N); +#endif +} + +template +void test_operator() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // deque& operator=( const deque& other ); + + D empty_d1, empty_d2; + D mid_d1(N), mid_d2(N); + D long_d1(32 * N), long_d2(32 * N); + + empty_d1 = empty_d2; + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + empty_d1 = mid_d1; + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + empty_d1 = empty_d2; + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + empty_d1 = long_d1; + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + empty_d1 = empty_d2; + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + + empty_d2 = long_d1; + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + + mid_d1 = long_d1; + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + mid_d1 = empty_d2; + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + mid_d1 = long_d1; + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + mid_d1 = mid_d2; + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + + long_d1 = long_d2; + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + long_d1 = empty_d1; + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + long_d1 = long_d2; + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + + empty_d1 = D(); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + mid_d1 = D(); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + long_d1 = D(); + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + + mid_d1 = mid_d2; + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + long_d1 = long_d2; + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + + // deque& operator=( deque&& other ) + +#if TEST_STD_VER >= 11 + mid_d1 = std::move(mid_d2); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2)); + long_d1 = std::move(long_d2); + assert(is_double_ended_contiguous_container_asan_correct(long_d1)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2)); + + D mid_d3a(N), mid_d3b(N); + D long_d3a(32 * N), long_d3b(32 * N); + + mid_d3a = std::move(long_d3a); + long_d3b = std::move(mid_d3b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); + + D empty_d4; + D long_d4a(32 * N), long_d4b(32 * N); + + long_d4a = std::move(empty_d4); + long_d4b = std::move(empty_d1); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4b)); + + // void assign( std::initializer_list ilist ) + + D empty_d5; + D short_d5a(1), short_d5b(N - 1); + D mid_d5(N + 1); + D long_d5(32 * N + 1); + + empty_d5 = {T(), T()}; + short_d5a = {T(), T()}; + short_d5b = {T(), T()}; + mid_d5 = {T(), T()}; + long_d5 = {T(), T()}; + + assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5)); + + empty_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d5a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d5b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + mid_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + long_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + + assert(empty_d5.size() > 16); + assert(short_d5a.size() > 16); + assert(short_d5b.size() > 16); + assert(mid_d5.size() > 16); + assert(long_d5.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5)); + + D empty_d6; + D short_d6a(1), short_d6b(N - 1); + D mid_d6(N + 1); + D long_d6(32 * N + 1); + + empty_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d6a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d6b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + mid_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + long_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + + assert(empty_d6.size() > 16); + assert(short_d6a.size() > 16); + assert(short_d6b.size() > 16); + assert(mid_d6.size() > 16); + assert(long_d6.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6)); + + empty_d6 = {}; + short_d6a = {}; + short_d6b = {}; + mid_d6 = {}; + long_d6 = {}; + + assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6)); + + D empty_d7; + D short_d7a(1), short_d7b(N - 1); + D mid_d7(N + 1); + D long_d7a(32 * N + 1), long_d7b(32 * N + 1); + + empty_d7 = {}; + short_d7a = {}; + short_d7b = {}; + mid_d7 = {}; + long_d7a = {}; + + long_d7b.pop_front(); + long_d7b = {}; + + assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d7)); + assert(is_double_ended_contiguous_container_asan_correct(long_d7a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d7b)); +#endif // TEST_STD_VER >= 11 +} + +template +void test() { + test_assign(); + test_operator(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void clear() + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.clear(); + short_d1a.clear(); + short_d1b.clear(); + mid_d1a.clear(); + mid_d1b.clear(); + mid_d1c.clear(); + long_d1a.clear(); + long_d1b.clear(); + long_d1c.clear(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp @@ -0,0 +1,313 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // Different constructors are called based on the used standard. + // Please, check https://en.cppreference.com/w/cpp/container/deque/deque + // for full list. + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d2(empty_d1); + D short_d2a(short_d1a), short_d2b(short_d1b); + D mid_d2a(mid_d1a), mid_d2b(mid_d1b), mid_d2c(mid_d1c); + D long_d2a(long_d1a), long_d2b(long_d1b), long_d2c(long_d1c); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d3(std::move(empty_d2)); + D short_d3a(std::move(short_d2a)), short_d3b(std::move(short_d2b)); + D mid_d3a(std::move(mid_d2a)), mid_d3b(std::move(mid_d2b)), mid_d3c(std::move(mid_d2c)); + D long_d3a(std::move(long_d2a)), long_d3b(std::move(long_d2b)), long_d3c(std::move(long_d2c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); + +#if TEST_STD_VER >= 11 + D empty_d4(empty_d1.cbegin(), empty_d1.cend()); + D short_d4a(short_d1a.cbegin(), short_d1a.cend()), short_d4b(short_d1b.cbegin(), short_d1b.cend()); + D mid_d4a(mid_d1a.cbegin(), mid_d1a.cend()), mid_d4b(mid_d1b.cbegin(), mid_d1b.cend()), + mid_d4c(mid_d1c.cbegin(), mid_d1c.cend()); + D long_d4a(long_d1a.cbegin(), long_d1a.cend()), long_d4b(long_d1a.cbegin(), long_d1a.cend()), + long_d4c(long_d1a.cbegin(), long_d1a.cend()); +#else + D empty_d4(empty_d1.begin(), empty_d1.end()); + D short_d4a(short_d1a.begin(), short_d1a.end()), short_d4b(short_d1b.begin(), short_d1b.end()); + D mid_d4a(mid_d1a.begin(), mid_d1a.end()), mid_d4b(mid_d1b.begin(), mid_d1b.end()), + mid_d4c(mid_d1c.begin(), mid_d1c.end()); + D long_d4a(long_d1a.begin(), long_d1a.end()), long_d4b(long_d1a.begin(), long_d1a.end()), + long_d4c(long_d1a.begin(), long_d1a.end()); +#endif + + assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); + assert(is_double_ended_contiguous_container_asan_correct(short_d4a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d4b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d4a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d4b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d4c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d4c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + +#if TEST_STD_VER >= 11 + D empty_d5(empty_d1.crbegin(), empty_d1.crend()); + D short_d5a(short_d1a.crbegin(), short_d1a.crend()), short_d5b(short_d1b.crbegin(), short_d1b.crend()); + D mid_d5a(mid_d1a.crbegin(), mid_d1a.crend()), mid_d5b(mid_d1b.crbegin(), mid_d1b.crend()), + mid_d5c(mid_d1c.crbegin(), mid_d1c.crend()); + D long_d5a(long_d1a.crbegin(), long_d1a.crend()), long_d5b(long_d1a.crbegin(), long_d1a.crend()), + long_d5c(long_d1a.crbegin(), long_d1a.crend()); +#else + D empty_d5(empty_d1.rbegin(), empty_d1.rend()); + D short_d5a(short_d1a.rbegin(), short_d1a.rend()), short_d5b(short_d1b.rbegin(), short_d1b.rend()); + D mid_d5a(mid_d1a.rbegin(), mid_d1a.rend()), mid_d5b(mid_d1b.rbegin(), mid_d1b.rend()), + mid_d5c(mid_d1c.rbegin(), mid_d1c.rend()); + D long_d5a(long_d1a.rbegin(), long_d1a.rend()), long_d5b(long_d1a.rbegin(), long_d1a.rend()), + long_d5c(long_d1a.rbegin(), long_d1a.rend()); +#endif + + assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d5c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d5c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d6(0, T()); + D short_d6a(1, T()), short_d6b(2, T()); + D mid_d6a(N - 1, T()), mid_d6b(N, T()), mid_d6c(N + 1, T()); + D long_d6a(17 * N - 1, T()), long_d6b(8 * N, T()), long_d6c(11 * N + 1, T()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d6c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d6c)); + +#if TEST_STD_VER >= 11 + D empty_d7({}); + D short_d7a({T()}), short_d7b({T(), T()}); + D mid_d7a({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + D mid_d7b({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); + assert(mid_d7a.size() == 16); + assert(is_double_ended_contiguous_container_asan_correct(mid_d7a)); + assert(mid_d7b.size() == 17); + assert(is_double_ended_contiguous_container_asan_correct(mid_d7b)); + + const T val = T(); + D empty_d8({}); + D short_d8a({val}), short_d8b({val, val}); + D mid_d8a({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + D mid_d8b({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d8)); + assert(is_double_ended_contiguous_container_asan_correct(short_d8a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d8b)); + assert(mid_d8a.size() == 16); + assert(is_double_ended_contiguous_container_asan_correct(mid_d8a)); + assert(mid_d8b.size() == 17); + assert(is_double_ended_contiguous_container_asan_correct(mid_d8b)); +#endif + + D empty_d9a((std::allocator())), empty_d9b(empty_d1.get_allocator()); + assert(is_double_ended_contiguous_container_asan_correct(empty_d9a)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d9b)); + +#if TEST_STD_VER >= 11 + D empty_d10(empty_d3, std::allocator()); + D short_d10a(short_d3a, std::allocator()), short_d10b(short_d3b, std::allocator()); + D mid_d10a(mid_d3a, std::allocator()), mid_d10b(mid_d3b, std::allocator()), + mid_d10c(mid_d3c, std::allocator()); + D long_d10a(long_d3a, std::allocator()), long_d10b(long_d3b, std::allocator()), + long_d10c(long_d3c, std::allocator()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d10)); + assert(is_double_ended_contiguous_container_asan_correct(short_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d3c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d3c)); + + D empty_d11(std::move(empty_d10), std::allocator()); + D short_d11a(std::move(short_d10a), std::allocator()), short_d11b(std::move(short_d10b), std::allocator()); + D mid_d11a(std::move(mid_d10a), std::allocator()), mid_d11b(std::move(mid_d10b), std::allocator()), + mid_d11c(std::move(mid_d10c), std::allocator()); + D long_d11a(std::move(long_d10a), std::allocator()), long_d11b(std::move(long_d10b), std::allocator()), + long_d11c(std::move(long_d10c), std::allocator()); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d11)); + assert(is_double_ended_contiguous_container_asan_correct(short_d11a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d11b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d11a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d11b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d11c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d11a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d11b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d11c)); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d10)); + assert(is_double_ended_contiguous_container_asan_correct(short_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d10c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d10c)); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// The test helped us find issues with llvm12 implementation, +// but it's a problematic one now. +// We may want to delete it. + +// UNSUPPORTED: c++03 + +#include +#include +#include "emplace_constructible.h" +#include "asan_testing.h" // includes deque - don't do it before +#include "test_iterators.h" + +template +void test_constructible() { + T arr1[] = {T()}; + using T2 = EmplaceConstructibleMoveableAndAssignable; + using It = cpp17_input_iterator; + typedef std::deque D; + + D d; + d.assign(It(arr1), It(std::end(arr1))); + assert(is_double_ended_contiguous_container_asan_correct(d)); +} + +template +void test() { + test_constructible(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // iterator erase( iterator first, iterator last ); + // iterator erase( const_iterator first, const_iterator last ); + + D d1a(N), d1b(N), d1c(N); +#if TEST_STD_VER >= 11 + d1a.erase(d1a.cbegin(), d1a.cend()); + d1b.erase(d1b.cbegin() + 1); + d1c.erase(d1c.cend() - 1); +#else + d1a.erase(d1a.begin(), d1a.end()); + d1b.erase(d1b.begin() + 1); + d1c.erase(d1c.end() - 1); +#endif + + assert(is_double_ended_contiguous_container_asan_correct(d1a)); + assert(is_double_ended_contiguous_container_asan_correct(d1b)); + assert(is_double_ended_contiguous_container_asan_correct(d1c)); + + D d2a(N + 1), d2b(N + 1), d2c(N + 1), d2d(N + 1); + + d2a.erase(d2a.begin(), d2a.end() - 2); + d2b.erase(d2b.begin() + 1, d2b.end()); + // iterator erase( iterator pos ); + // iterator erase( const_iterator pos ); + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + D d3a(32 * N + 1), d3b(32 * N + 1), d3c(32 * N + 1), d3d(32 * N + 1); + + d3a.erase(d3a.begin() + N + 1, d3a.end() - N - 2); + d3b.erase(d3b.begin() + N - 1, d3b.end()); + + assert(is_double_ended_contiguous_container_asan_correct(d3a)); + assert(is_double_ended_contiguous_container_asan_correct(d3b)); + while (d3c.size() > 3) { + d3c.erase(d3c.begin() + 2); + assert(is_double_ended_contiguous_container_asan_correct(d3c)); + } + while (d3d.size() > 4) { + d3d.erase(d3d.end() - 3); + assert(is_double_ended_contiguous_container_asan_correct(d3d)); + } + + D d4a(32 * N + 3), d4b(32 * N + 3); + while (d4a.size() > 5) { + d4a.erase(d4a.begin() + 2, d4a.begin() + 4); + assert(is_double_ended_contiguous_container_asan_correct(d4a)); + } + + while (d4b.size() > 5) { + d4b.erase(d4b.end() - 4, d4b.end() - 2); + assert(is_double_ended_contiguous_container_asan_correct(d4b)); + } +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp @@ -0,0 +1,278 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_insert() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + T t = T(); + D d1a(2), d1b(2), d1c(2); + +#if TEST_STD_VER >= 11 + d1a.insert(d1a.cbegin(), t); + d1b.insert(d1b.cend(), t); + d1c.insert(d1c.cbegin() + 1, t); +#else + d1a.insert(d1a.begin(), t); + d1b.insert(d1b.end(), t); + d1c.insert(d1c.begin() + 1, t); +#endif + + assert(is_double_ended_contiguous_container_asan_correct(d1a)); + assert(is_double_ended_contiguous_container_asan_correct(d1b)); + assert(is_double_ended_contiguous_container_asan_correct(d1c)); + + D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); + + d2a.insert(d2a.begin(), t); + d2b.insert(d2b.end(), t); + d2c.insert(d2c.begin() + 1, t); + d2d.insert(d2d.end() - 1, t); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 2 * N + 1, t); + d2b.insert(d2b.end(), 2 * N + 1, t); + d2c.insert(d2c.begin() + 1, 2 * N + 1, t); + d2d.insert(d2d.end() - 1, 2 * N + 1, t); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2c.insert(d2c.begin() + N + 1, 2 * N + 1, t); + d2d.insert(d2d.end() - N - 1, 2 * N + 1, t); + + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + D source(3 * N); + + d2a.insert(d2a.begin(), source.begin() + 1, source.end() - 1); + d2b.insert(d2b.end(), source.begin() + 1, source.end() - 1); + d2c.insert(d2c.begin() + 1, source.begin() + 1, source.end() - 1); + d2d.insert(d2d.end() - 1, source.begin() + 1, source.end() - 1); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2c.insert(d2c.begin() + N + 1, source.begin() + 1, source.end() - 1); + d2d.insert(d2d.end() - N - 1, source.begin() + 1, source.end() - 1); + + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), T()); + d2b.insert(d2b.end(), T()); + d2c.insert(d2c.begin() + 1, T()); + d2d.insert(d2d.end() - 1, T()); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + T a = T(), b = T(), c = T(), d = T(); + d2a.insert(d2a.begin(), a); + d2b.insert(d2b.end(), b); + d2c.insert(d2c.begin() + 1, c); + d2d.insert(d2d.end() - 1, d); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 3, a); + d2b.insert(d2b.end(), 3, b); + d2c.insert(d2c.begin() + 1, 3, c); + d2d.insert(d2d.end() - 1, 3, d); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 3 * N, a); + d2b.insert(d2b.end(), 3 * N, b); + d2c.insert(d2c.begin() + 1, 3 * N, c); + d2d.insert(d2d.end() - 1, 3 * N, d); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), std::move(a)); + d2b.insert(d2b.end(), std::move(b)); + d2c.insert(d2c.begin() + 1, std::move(c)); + d2d.insert(d2d.end() - 1, std::move(d)); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + +#if TEST_STD_VER >= 11 + D d3a(2), d3b(2), d3c(2); + + d3a.insert(d3a.cbegin(), {t}); + d3b.insert(d3b.cend(), {t}); + d3c.insert(d3c.cbegin() + 1, {t}); + + assert(is_double_ended_contiguous_container_asan_correct(d3a)); + assert(is_double_ended_contiguous_container_asan_correct(d3b)); + assert(is_double_ended_contiguous_container_asan_correct(d3c)); + + d3a.insert(d3a.cbegin(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3b.insert(d3b.cend(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3c.insert(d3c.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + + assert(d3a.size() > 16); + assert(d3b.size() > 16); + assert(d3c.size() > 16); + + assert(is_double_ended_contiguous_container_asan_correct(d3a)); + assert(is_double_ended_contiguous_container_asan_correct(d3b)); + assert(is_double_ended_contiguous_container_asan_correct(d3c)); + + d3a.insert(d3a.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3b.insert(d3b.cend() - 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3c.resize(N - 1); + d3c.insert(d3c.cbegin() + N - 2, {t, t, t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + + assert(is_double_ended_contiguous_container_asan_correct(d3a)); + assert(is_double_ended_contiguous_container_asan_correct(d3b)); + assert(is_double_ended_contiguous_container_asan_correct(d3c)); +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + T t = T(); + D d1a(2), d1b(2), d1c(2); + + d1a.emplace(d1a.cbegin(), t); + d1b.emplace(d1b.cend(), t); + d1c.emplace(d1c.cbegin() + 1, t); + + assert(is_double_ended_contiguous_container_asan_correct(d1a)); + assert(is_double_ended_contiguous_container_asan_correct(d1b)); + assert(is_double_ended_contiguous_container_asan_correct(d1c)); + + D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); + + d2a.emplace(d2a.cbegin(), t); + d2b.emplace(d2b.cend(), t); + d2c.emplace(d2c.cbegin() + 1, t); + d2d.emplace(d2d.cend() - 1, t); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + d2a.emplace(d2a.cbegin(), T()); + d2b.emplace(d2b.cend(), T()); + d2c.emplace(d2c.cbegin() + 1, T()); + d2d.emplace(d2d.cend() - 1, T()); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); + + T a = T(), b = T(), c = T(), d = T(); + d2a.emplace(d2a.cbegin(), std::move(a)); + d2b.emplace(d2b.cend(), std::move(b)); + d2c.emplace(d2c.cbegin() + 1, std::move(c)); + d2d.emplace(d2d.cend() - 1, std::move(d)); + + assert(is_double_ended_contiguous_container_asan_correct(d2a)); + assert(is_double_ended_contiguous_container_asan_correct(d2b)); + assert(is_double_ended_contiguous_container_asan_correct(d2c)); + assert(is_double_ended_contiguous_container_asan_correct(d2d)); +} +#endif + +template +void test() { + test_insert(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_aligned() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_back() + + D single_d(1); + single_d.pop_back(); + assert(is_double_ended_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_back(); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } +} + +template +void test_not_aligned() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_back() + + D single_d(1); + single_d.pop_back(); + assert(is_double_ended_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + d1.pop_front(); + + while (!d1.empty()) { + d1.pop_back(); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } +} + +template +void test() { + test_aligned(); + test_not_aligned(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_front() + + D single_d(1); + single_d.pop_front(); + assert(is_double_ended_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_front(); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + D d2(34 * N + 1); + while (!d2.empty()) { + d2.pop_front(); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + } +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_push() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D d1; + + // void push_back( const T& value ); + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d1.push_back(b); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d1.push_back(b); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + +#if TEST_STD_VER >= 11 + // void push_back( T&& value ); + + D d2; + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d2.push_back(std::move(b)); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + d2.push_back(T()); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + } +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // template< class... Args > + // reference emplace_back( Args&&... args ); + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d1.emplace_back(b); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d1.emplace_back(b); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d2.emplace_back(std::move(b)); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + d2.emplace_back(T()); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + } +} +#endif + +template +void test() { + test_push(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_push() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void push_front( const T& value ); + + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d1.push_front(f); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T f = T(); + d1.push_front(f); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + +#if TEST_STD_VER >= 11 + // void push_front( T&& value ); + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d2.push_front(std::move(f)); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + d2.push_front(T()); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + } +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // template< class... Args > + // reference emplace_front( Args&&... args ); + + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d1.emplace_front(f); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T f = T(); + d1.emplace_front(f); + assert(is_double_ended_contiguous_container_asan_correct(d1)); + } + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d2.emplace_front(std::move(f)); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + d2.emplace_front(T()); + assert(is_double_ended_contiguous_container_asan_correct(d2)); + } +} +#endif + +template +void test() { + test_push(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp @@ -0,0 +1,501 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_count() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1); + short_d1a.resize(1); + short_d1b.resize(1); + mid_d1a.resize(1); + mid_d1b.resize(1); + mid_d1c.resize(1); + long_d1a.resize(1); + long_d1b.resize(1); + long_d1c.resize(1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(2); + short_d1a.resize(2); + short_d1b.resize(2); + mid_d1a.resize(2); + mid_d1b.resize(2); + mid_d1c.resize(2); + long_d1a.resize(2); + long_d1b.resize(2); + long_d1c.resize(2); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N - 1); + short_d1a.resize(N - 1); + short_d1b.resize(N - 1); + mid_d1a.resize(N - 1); + mid_d1b.resize(N - 1); + mid_d1c.resize(N - 1); + long_d1a.resize(N - 1); + long_d1b.resize(N - 1); + long_d1c.resize(N - 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N + 1); + short_d1a.resize(N + 1); + short_d1b.resize(N + 1); + mid_d1a.resize(N + 1); + mid_d1b.resize(N + 1); + mid_d1c.resize(N + 1); + long_d1a.resize(N + 1); + long_d1b.resize(N + 1); + long_d1c.resize(N + 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(20 * N); + short_d1a.resize(20 * N); + short_d1b.resize(20 * N); + mid_d1a.resize(20 * N); + mid_d1b.resize(20 * N); + mid_d1c.resize(20 * N); + long_d1a.resize(20 * N); + long_d1b.resize(20 * N); + long_d1c.resize(20 * N); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N); + short_d2a.resize(20 * N); + short_d2b.resize(20 * N); + mid_d2a.resize(20 * N); + mid_d2b.resize(20 * N); + mid_d2c.resize(20 * N); + long_d2a.resize(20 * N); + long_d2b.resize(20 * N); + long_d2c.resize(20 * N); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); +} + +template +void test_value() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + const T val = T(); + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0, val); + short_d1a.resize(1, val); + short_d1b.resize(2, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(17 * N - 1, val); + long_d1b.resize(8 * N, val); + long_d1c.resize(11 * N + 1, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1, val); + short_d1a.resize(1, val); + short_d1b.resize(1, val); + mid_d1a.resize(1, val); + mid_d1b.resize(1, val); + mid_d1c.resize(1, val); + long_d1a.resize(1, val); + long_d1b.resize(1, val); + long_d1c.resize(1, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(2, val); + short_d1a.resize(2, val); + short_d1b.resize(2, val); + mid_d1a.resize(2, val); + mid_d1b.resize(2, val); + mid_d1c.resize(2, val); + long_d1a.resize(2, val); + long_d1b.resize(2, val); + long_d1c.resize(2, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N - 1, val); + short_d1a.resize(N - 1, val); + short_d1b.resize(N - 1, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N - 1, val); + mid_d1c.resize(N - 1, val); + long_d1a.resize(N - 1, val); + long_d1b.resize(N - 1, val); + long_d1c.resize(N - 1, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N, val); + short_d1a.resize(N, val); + short_d1b.resize(N, val); + mid_d1a.resize(N, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N, val); + long_d1a.resize(N, val); + long_d1b.resize(N, val); + long_d1c.resize(N, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N + 1, val); + short_d1a.resize(N + 1, val); + short_d1b.resize(N + 1, val); + mid_d1a.resize(N + 1, val); + mid_d1b.resize(N + 1, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(N + 1, val); + long_d1b.resize(N + 1, val); + long_d1c.resize(N + 1, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N, val); + short_d1a.resize(N, val); + short_d1b.resize(N, val); + mid_d1a.resize(N, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N, val); + long_d1a.resize(N, val); + long_d1b.resize(N, val); + long_d1c.resize(N, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(20 * N, val); + short_d1a.resize(20 * N, val); + short_d1b.resize(20 * N, val); + mid_d1a.resize(20 * N, val); + mid_d1b.resize(20 * N, val); + mid_d1c.resize(20 * N, val); + long_d1a.resize(20 * N, val); + long_d1b.resize(20 * N, val); + long_d1c.resize(20 * N, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0, val); + short_d1a.resize(1, val); + short_d1b.resize(2, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(17 * N - 1, val); + long_d1b.resize(8 * N, val); + long_d1c.resize(11 * N + 1, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N, val); + short_d2a.resize(20 * N, val); + short_d2b.resize(20 * N, val); + mid_d2a.resize(20 * N, val); + mid_d2b.resize(20 * N, val); + mid_d2c.resize(20 * N, val); + long_d2a.resize(20 * N, val); + long_d2b.resize(20 * N, val); + long_d2c.resize(20 * N, val); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); +} + +template +void test() { + test_count(); + test_value(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp @@ -0,0 +1,500 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03 + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1); + short_d1a.resize(1); + short_d1b.resize(1); + mid_d1a.resize(1); + mid_d1b.resize(1); + mid_d1c.resize(1); + long_d1a.resize(1); + long_d1b.resize(1); + long_d1c.resize(1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(2); + short_d1a.resize(2); + short_d1b.resize(2); + mid_d1a.resize(2); + mid_d1b.resize(2); + mid_d1c.resize(2); + long_d1a.resize(2); + long_d1b.resize(2); + long_d1c.resize(2); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N - 1); + short_d1a.resize(N - 1); + short_d1b.resize(N - 1); + mid_d1a.resize(N - 1); + mid_d1b.resize(N - 1); + mid_d1c.resize(N - 1); + long_d1a.resize(N - 1); + long_d1b.resize(N - 1); + long_d1c.resize(N - 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N + 1); + short_d1a.resize(N + 1); + short_d1b.resize(N + 1); + mid_d1a.resize(N + 1); + mid_d1b.resize(N + 1); + mid_d1c.resize(N + 1); + long_d1a.resize(N + 1); + long_d1b.resize(N + 1); + long_d1c.resize(N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(20 * N); + short_d1a.resize(20 * N); + short_d1b.resize(20 * N); + mid_d1a.resize(20 * N); + mid_d1b.resize(20 * N); + mid_d1c.resize(20 * N); + long_d1a.resize(20 * N); + long_d1b.resize(20 * N); + long_d1c.resize(20 * N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + empty_d1.clear(); + short_d1a.clear(); + short_d1b.clear(); + mid_d1a.clear(); + mid_d1b.clear(); + mid_d1c.clear(); + long_d1a.clear(); + long_d1b.clear(); + long_d1c.clear(); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N); + short_d2a.resize(20 * N); + short_d2b.resize(20 * N); + mid_d2a.resize(20 * N); + mid_d2b.resize(20 * N); + mid_d2c.resize(20 * N); + long_d2a.resize(20 * N); + long_d2b.resize(20 * N); + long_d2c.resize(20 * N); + + empty_d2.shrink_to_fit(); + short_d2a.shrink_to_fit(); + short_d2b.shrink_to_fit(); + mid_d2a.shrink_to_fit(); + mid_d2b.shrink_to_fit(); + mid_d2c.shrink_to_fit(); + long_d2a.shrink_to_fit(); + long_d2b.shrink_to_fit(); + long_d2c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); + + empty_d2.resize(0); + short_d2a.resize(0); + short_d2b.resize(0); + mid_d2a.resize(0); + mid_d2b.resize(0); + mid_d2c.resize(0); + long_d2a.resize(0); + long_d2b.resize(0); + long_d2c.resize(0); + + empty_d2.shrink_to_fit(); + short_d2a.shrink_to_fit(); + short_d2b.shrink_to_fit(); + mid_d2a.shrink_to_fit(); + mid_d2b.shrink_to_fit(); + mid_d2c.shrink_to_fit(); + long_d2a.shrink_to_fit(); + long_d2b.shrink_to_fit(); + long_d2c.shrink_to_fit(); + + assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); + assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp @@ -0,0 +1,280 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_external() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1a, empty_d1b; + D short_d1a(1), short_d1b; + D mid_d1a(N), mid_d1b(N + 1); + D long_d1a(8 * N), long_d1b(11 * N + 1); + + std::swap(empty_d1a, empty_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); + std::swap(empty_d1a, empty_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); + + std::swap(empty_d1a, short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + std::swap(empty_d1a, short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + + std::swap(empty_d1a, mid_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + std::swap(empty_d1a, mid_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + + std::swap(empty_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + std::swap(empty_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + std::swap(empty_d1a, long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + std::swap(empty_d1a, long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + + std::swap(empty_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + std::swap(empty_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + std::swap(short_d1a, short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + std::swap(short_d1a, short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + + std::swap(short_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + std::swap(short_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + std::swap(short_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + std::swap(short_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + std::swap(mid_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + std::swap(mid_d1a, mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + std::swap(mid_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + std::swap(mid_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + std::swap(long_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + std::swap(long_d1a, long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + std::swap(empty_d1a, empty_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + + std::swap(short_d1a, short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + std::swap(short_d1b, short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + + std::swap(long_d1a, long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); +} + +template +void test_member() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1a, empty_d1b; + D short_d1a(1), short_d1b; + D mid_d1a(N), mid_d1b(N + 1); + D long_d1a(8 * N), long_d1b(11 * N + 1); + + empty_d1a.swap(empty_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); + empty_d1a.swap(empty_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); + + empty_d1a.swap(short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + empty_d1a.swap(short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + + empty_d1a.swap(mid_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + empty_d1a.swap(mid_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + + empty_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + empty_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + empty_d1a.swap(long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + empty_d1a.swap(long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + + empty_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + empty_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + short_d1a.swap(short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + short_d1a.swap(short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + + short_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + short_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + short_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + short_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + mid_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + mid_d1a.swap(mid_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); + + mid_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + mid_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + long_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + long_d1a.swap(long_d1b); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); + assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); + + empty_d1a.swap(empty_d1a); + assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); + + short_d1a.swap(short_d1a); + assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); + short_d1b.swap(short_d1b); + assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); + + long_d1a.swap(long_d1a); + assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); +} + +template +void test() { + test_external(); + test_member(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/support/asan_testing.h b/libcxx/test/support/asan_testing.h --- a/libcxx/test/support/asan_testing.h +++ b/libcxx/test/support/asan_testing.h @@ -9,6 +9,12 @@ #ifndef ASAN_TESTING_H #define ASAN_TESTING_H +#ifdef _LIBCPP_DEQUE +// We need to define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS first +// prior to including deque, so we error out if its already included +# error deque included before asan_testing.h +#endif + #include "test_macros.h" #if TEST_HAS_FEATURE(address_sanitizer) @@ -25,14 +31,35 @@ c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0; return true; } - #else template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) { return true; } -#endif +#endif // TEST_HAS_FEATURE(address_sanitizer) + +#if TEST_HAS_FEATURE(address_sanitizer) && _LIBCPP_CLANG_VER >= 16000 +extern "C" int __sanitizer_verify_double_ended_contiguous_container( + const void* beg, const void* con_beg, const void* con_end, const void* end); +extern "C" bool __sanitizer_is_annotable(const void* address, const unsigned long size); +# define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS +# include +template +TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque& c) { + if (std::__libcpp_is_constant_evaluated()) + return true; + if (std::is_same >::value) + return c.__verify_asan_annotations(); + return true; +} +#else +# include +template +TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque&) { + return true; +} +#endif #endif // ASAN_TESTING_H diff --git a/show-patch.r2-20-09-22 b/show-patch.r2-20-09-22 new file mode 100644 --- /dev/null +++ b/show-patch.r2-20-09-22 @@ -0,0 +1,4434 @@ +commit 6f83fdfdb62517fd22881f64fef7dee7fdf0ae5b +Author: Advenam Tacet +Date: Wed Sep 7 09:05:54 2022 +0200 + + [2a/3][ASan][libcxx] std::deque annotations + + This commit is a part of patches extending AddressSanitizer + C++ container overflow detection capabilities by adding annotations, + similar to those existing in std::vector, to std::string and + std::deque collections. These changes allow ASan to detect cases + when the instrumented program accesses memory which is internally + allocated by the collection but is still not in-use + (accesses before or after the stored elements for std::deque, + or between the size and capacity bounds for std::string). + + Trail of Bits developed this as part of a research project where + we tried to find bugs using the oss-fuzz + (using llvm-14 with our modifications) harnesses. + Now, we want to upstream the llvm-15 port of this work. + + That commit adds ASan annotations to std::deque. + Every std::deque chunk (contiguous memory block used by the container) + is annotated separately and API functions from [1a/3] + are used for that purpose. + + Regarding performance, the introduced changes only affect cases when + a std::deque object is created or has an element added or removed. + It is similar to std::vector in that aspect. + + The commit also adds unit tests for those annotations and + a compiler-rt function, + __sanitizer_verify_de_contiguous_container, + which is used within those tests. + This function can also be used in the future to verify + the sanitization/annotation verification of other + double ended contiguous containers. + + Also please note that + the is_de_contiguous_container_asan_correct function + can only verify std::deque objects whose memory is never poisoned + by elements inside. + Therefore it cannot be and is not used within the tests with + a sanitized std::basic_string implementation + (which is added in the next commit in this patch series). + + Structure of our patches: + [1a/3][ASan][compiler-rt] API for double ended containers + [1b/3][ASan][compiler-rt] API for annotating objects memory + [2a/3][ASan][libcxx] std::deque annotations + [2b/3][ASan][libcxx] std::basic_string annotations + [3/3][ASan] integration test for std::deque and std::basic_string annotations + + 1a -> 2a - + \ + --> 3 + / + 1b -> 2b - + + If you have any questions, please email: + - advenam.tacet@trailofbits.com + - disconnect3d@trailofbits.com + +diff --git a/libcxx/include/deque b/libcxx/include/deque +index 2bb2643c2214..fd096e75ace1 100644 +--- a/libcxx/include/deque ++++ b/libcxx/include/deque +@@ -1280,6 +1280,9 @@ template */> + class _LIBCPP_TEMPLATE_VIS deque + : private __deque_base<_Tp, _Allocator> + { ++private: ++ using __default_allocator_type = allocator<_Tp>; ++ + public: + // types: + +@@ -1310,10 +1313,8 @@ public: + + // construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY +- deque() +- _NOEXCEPT_(is_nothrow_default_constructible::value) +- {} +- _LIBCPP_INLINE_VISIBILITY explicit deque(const allocator_type& __a) : __base(__a) {} ++ deque() _NOEXCEPT_(is_nothrow_default_constructible::value) { __annotate_new(0); } ++ _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a) : __base(__a) { __annotate_new(0); } + explicit deque(size_type __n); + #if _LIBCPP_STD_VER > 11 + explicit deque(size_type __n, const _Allocator& __a); +@@ -1323,8 +1324,9 @@ public: + template ::value> > + deque(size_type __n, const value_type& __v, const allocator_type& __a) : __base(__a) + { +- if (__n > 0) +- __append(__n, __v); ++ __annotate_new(0); ++ if (__n > 0) ++ __append(__n, __v); + } + + template +@@ -1529,75 +1531,418 @@ public: + } + + private: +- _LIBCPP_INLINE_VISIBILITY +- bool __maybe_remove_front_spare(bool __keep_one = true) { +- if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { +- __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), +- __base::__block_size); +- __base::__map_.pop_front(); +- __base::__start_ -= __base::__block_size; +- return true; +- } +- return false; +- } ++ // Implementation based on the one from std::vector. ++ // ++ // The following functions are no-ops outside of AddressSanitizer mode. ++ // We call annotatations only for the default Allocator because other allocators ++ // may not meet the AddressSanitizer alignment constraints. ++ // See the documentation for __sanitizer_annotate_contiguous_container for more details. ++#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 16000 ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_contiguous_container_front( ++ const void* __beg, ++ const void* __end, ++ const void* __new_con_beg, ++ const void* __old_con_beg, ++ const void* __con_end) const { ++ // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block. ++ if (__beg && is_same::value) ++ __sanitizer_annotate_double_ended_contiguous_container( ++ __beg, __end, __old_con_beg, __con_end, __new_con_beg, __con_end); ++ } ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_contiguous_container_back( ++ const void* __beg, ++ const void* __end, ++ const void* __old_con_end, ++ const void* __new_con_end, ++ const void* __con_beg) const { ++ // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block ++ if (__beg && is_same::value) ++ __sanitizer_annotate_double_ended_contiguous_container( ++ __beg, __end, __con_beg, __old_con_end, __con_beg, __new_con_end); ++ } ++#else ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_contiguous_container_front( ++ const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_contiguous_container_back( ++ const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} ++#endif // !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 16000 ++ ++ _LIBCPP_HIDE_FROM_ABI ++ // __b - index of first item in __map_ to annotate ++ // __e - index behind the last item in __map_ to annotate (so last item + 1) ++ void __annotate_poison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { ++ if (__b == __e) ++ return; ++ ++ // __mp - ponter to the first chunk which annotations we want to modify. ++ // __last_mp - pointer to the last chunk which annotations we want to modify. ++ // If ony one chunk if affected, __mp == __last_mp ++ // We use (__e - 1) in calculations, because if we poison to the very end of chunk, ++ // we still want to point at that chunk and not the next one. Using __e, would ++ // point at the memory for the next element, which may be in a next chunk. ++ typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; ++ typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; ++ ++ const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); ++ ++ // We iterate over map pointers and fully poison all blocks between the first and the last. ++ // The first block is partialy poisoned here as well. ++ // The last one is poisoned after the while loop. ++ while (__mp != __last_mp) { ++ // Pointer to chunk's/block's beginning ++ const void* __p_t_b = std::__to_address(*__mp); ++ // Pointer to chunk's/block's end ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ // We are poisoning rest of the blocks memory, therefore end of block is last argument. ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_t_e); ++ // Poisoned memory: [__p, __p_t_e] ++ ++ __mp += 1; ++ __p_b = std::__to_address(*__mp); ++ } ++ ++ // If __last_block_index is zero, then we should point to the end of a chunk (one of its contiguous blocks). ++ size_type __last_block_index = __e % __base::__block_size; ++ ++ const void* __p_e = ++ std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); ++ const void* __p_t_b = std::__to_address(*__mp); ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ ++ // Poisoning happens after the container modification, so the size ++ // was already changed and may be 0 but we still have to poison the cleared blocks. ++ if (__last_block_index == 0 || size() == 0) ++ // Read comments in __annotate_contiguous_container_front for empty block argument requrements. ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_e); ++ else { ++ // Due to current limitations of ASan, it only matters if container is empty or not, ++ // therefore we do not have to calculate true end of the container in the block (better performance), ++ // but if poisoning prefixes are implemented in Asan, we will have to pass correct end of memory in use ++ // inside that chunk, instead of just end of the allocated memory. (Last argument.) ++ // ++ // Correct end of container is passed to __annotate_contiguous_container_front, but it ++ // may be changes to __p_t_e for better performance. ++ // __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p, __p_t_e); ++ if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { ++ // End of the container is in the block which we are poisoning. ++ const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_e); ++ } else ++ // End of the container is in a different chunk, rest of chunk is in use. ++ // Therefore last argument is end of chunk. ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_t_e); ++ } ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_unpoison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { ++ if (__b == __e) ++ return; ++ // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. ++ typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; ++ typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; ++ ++ const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); ++ while (__mp != __last_mp) { ++ // Pointer to block's beginning ++ const void* __p_t_b = std::__to_address(*__mp); ++ // Pointer to block's end ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_t_e); ++ ++ __mp += 1; ++ __p_b = std::__to_address(*__mp); ++ } ++ ++ size_type __last_block_index = __e % __base::__block_size; ++ ++ const void* __p_e = ++ std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); ++ const void* __p_t_b = std::__to_address(*__mp); ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ ++ // unpoison happens before the size is changed ++ // so we have to unpoison the block before its modified ++ if (__last_block_index == 0 || size() == 0) ++ __annotate_contiguous_container_front(__p_t_b, __p_e, __p_b, __p_e, __p_e); ++ else { ++ // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. ++ if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { ++ const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_e); ++ } else ++ __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_t_e); ++ } ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_poison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { ++ if (__b == __e) ++ return; ++ ++ // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. ++ typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; ++ typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; ++ ++ const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); ++ const void* __p_c_b; ++ // Poisoning happens after container modification and size updated. ++ if (size() == 0) ++ __p_c_b = __p_b; ++ else { ++ if (__base::__start_ / __base::__block_size == __b / __base::__block_size) ++ // Container starts in the block we are about to poison. ++ __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); ++ else ++ // Container starts in a different block. ++ __p_c_b = std::__to_address(*__mp); ++ } ++ while (__mp != __last_mp) { ++ const void* __p_t_b = std::__to_address(*__mp); ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_c_b); ++ ++ __mp += 1; ++ __p_c_b = __p_b = std::__to_address(*__mp); ++ } ++ ++ size_type __last_block_index = __e % __base::__block_size; ++ const void* __p_e = ++ std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); ++ const void* __p_t_b = std::__to_address(*__mp); ++ const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); ++ // Poisoning happens after elemests were removed. ++ if (size() == 0) ++ __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_b); ++ else ++ __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_b); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_unpoison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { ++ if (__b == __e) ++ return; ++ ++ // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. ++ typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; ++ typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; ++ ++ const void* __p_b = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); ++ const void* __p_c_b; ++ // Unpoisoning happens befor container modification and size updated. ++ if (size() == 0) ++ __p_c_b = __p_b; ++ else { ++ if (__base::__start_ / __base::__block_size == __b / __base::__block_size) ++ // Container starts in the block we are about to poison. ++ __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); ++ else ++ // Container starts in a different block. ++ __p_c_b = std::__to_address(*__mp); ++ } ++ ++ while (__mp != __last_mp) { ++ const void* __p_t_b = _VSTD::__to_address(*__mp); ++ const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_c_b); ++ ++ __mp += 1; ++ __p_c_b = __p_b = _VSTD::__to_address(*__mp); ++ } ++ ++ size_type __last_block_index = __e % __base::__block_size; ++ const void* __p_e = ++ _VSTD::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); ++ const void* __p_t_b = _VSTD::__to_address(*__mp); ++ const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_b); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_new(size_type __current_size) const _NOEXCEPT { ++ if (__current_size == 0) ++ __annotate_poison_from_to_back(0, __base::__map_.size() * __base::__block_size); ++ else { ++ // This branch is never reached in current implementation because ++ // __annotate_new is always called with 0, ++ // but let's leave it here in case anyone needs to use ++ // __annotate_new(n) in the future ++ __annotate_poison_from_to_front(0, __base::__start_); ++ __annotate_poison_from_to_back(__base::__start_ + __current_size, __base::__map_.size() * __base::__block_size); ++ } ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_delete() const _NOEXCEPT { ++ if (!empty()) { ++ __annotate_unpoison_from_to_front(0, __base::__start_); ++ __annotate_unpoison_from_to_back( ++ __base::__start_ + __base::size(), __base::__map_.size() * __base::__block_size); ++ } else ++ __annotate_unpoison_from_to_back(0, __base::__map_.size() * __base::__block_size); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_increase_front(size_type __n) const _NOEXCEPT { ++ __annotate_unpoison_from_to_front(__base::__start_ - __n, __base::__start_); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_increase_back(size_type __n) const _NOEXCEPT { ++ __annotate_unpoison_from_to_back(__base::__start_ + __base::size(), __base::__start_ + __base::size() + __n); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT { ++ __annotate_poison_from_to_front(__old_start, __old_start + (__old_size - size())); ++ } ++ ++ _LIBCPP_HIDE_FROM_ABI ++ void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT { ++ __annotate_poison_from_to_back(__old_start + size(), __old_start + __old_size); ++ } ++ ++// This macro should be defined only during testing ASAN. ++// Include the "asan_testing.h" file which defines it ++// to be able to use it in ASan tests. ++#ifdef _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS + +- _LIBCPP_INLINE_VISIBILITY +- bool __maybe_remove_back_spare(bool __keep_one = true) { +- if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { +- __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), +- __base::__block_size); +- __base::__map_.pop_back(); +- return true; ++public: ++ bool __verify_asan_annotations() const _NOEXCEPT { ++ // This function tests deque object annotations. ++ // This test is simplified, it tests only if: ++ // - memory owned by deque (deque blocks) not containig alements is poisoned. ++ // - memory owned by deque elements is accessible. ++ // ++ // Therefore you cannot test, with that function, deque containing objects ++ // which memory may be partialy (or fully) poisoned, like std::string (SSO case). ++ // You can test std::vector or long std::string. ++ ++ if (empty()) { ++ for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); ++ ++__it) ++ if (!__sanitizer_verify_double_ended_contiguous_container(*__it, *__it, *__it, *__it + __base::__block_size)) ++ return false; ++ ++ return true; ++ } ++ ++ size_type __e = __base::__start_ + __base::size(); ++ typename __base::__map_traits::const_pointer __first_mp = ++ __base::__map_.begin() + __base::__start_ / __base::__block_size; ++ typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; ++ ++ // Pointers to first and last elements ++ // They can be in *different deque blocks* ++ pointer __p_first = *__first_mp + (__base::__start_ % __base::__block_size); ++ pointer __p_last = ++ *__last_mp + ((__e % __base::__block_size == 0) ? __base::__block_size : __e % __base::__block_size); ++ ++ for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); ++ ++__it) { ++ // Go over all blocks, find the place we are in and verify its annotations ++ // Note that __p_last points *behind* the last item. ++ ++ // - blocks before the first block with container elements ++ // - first block with items ++ // - last block with items ++ // - blocks after last block with ciontainer elements ++ ++ // Is the block before or after deque blocks that contain elements? ++ if (__it < __first_mp || __it > __last_mp) { ++ if (!__sanitizer_verify_double_ended_contiguous_container(*__it, *__it, *__it, (*__it + __base::__block_size))) ++ return false; + } +- return false; +- } +- +- template +- void __append(_InpIter __f, _InpIter __l, +- typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); +- template +- void __append(_ForIter __f, _ForIter __l, +- typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); +- void __append(size_type __n); +- void __append(size_type __n, const value_type& __v); +- void __erase_to_end(const_iterator __f); +- void __add_front_capacity(); +- void __add_front_capacity(size_type __n); +- void __add_back_capacity(); +- void __add_back_capacity(size_type __n); +- iterator __move_and_check(iterator __f, iterator __l, iterator __r, +- const_pointer& __vt); +- iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, +- const_pointer& __vt); +- void __move_construct_and_check(iterator __f, iterator __l, +- iterator __r, const_pointer& __vt); +- void __move_construct_backward_and_check(iterator __f, iterator __l, +- iterator __r, const_pointer& __vt); + +- _LIBCPP_INLINE_VISIBILITY +- void __copy_assign_alloc(const deque& __c) +- {__copy_assign_alloc(__c, integral_constant());} +- +- _LIBCPP_INLINE_VISIBILITY +- void __copy_assign_alloc(const deque& __c, true_type) ++ else { ++ // Is the block the first block that contains elements? ++ pointer __con_beg = (__it == __first_mp) ? __p_first : *__it; ++ // Is it the last one? ++ pointer __con_end = (__it == __last_mp) ? __p_last : (*__it + __base::__block_size); + { +- if (__base::__alloc() != __c.__alloc()) +- { +- clear(); +- shrink_to_fit(); +- } +- __base::__alloc() = __c.__alloc(); +- __base::__map_.__alloc() = __c.__map_.__alloc(); ++ if (!__sanitizer_verify_double_ended_contiguous_container( ++ *__it, __con_beg, __con_end, (*__it + __base::__block_size))) ++ return false; + } ++ } ++ } + +- _LIBCPP_INLINE_VISIBILITY +- void __copy_assign_alloc(const deque&, false_type) +- {} ++ return true; ++ } ++ ++private: ++#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS ++ ++ _LIBCPP_INLINE_VISIBILITY ++ bool __maybe_remove_front_spare(bool __keep_one = true) { ++ if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { ++ __annotate_unpoison_from_to_back(0, __base::__block_size); ++ __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), __base::__block_size); ++ __base::__map_.pop_front(); ++ __base::__start_ -= __base::__block_size; ++ return true; ++ } ++ return false; ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ bool __maybe_remove_back_spare(bool __keep_one = true) { ++ if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { ++ __annotate_unpoison_from_to_back( ++ (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); ++ __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), __base::__block_size); ++ __base::__map_.pop_back(); ++ return true; ++ } ++ return false; ++ } ++ ++ template ++ void __append(_InpIter __f, ++ _InpIter __l, ++ typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); ++ template ++ void ++ __append(_ForIter __f, _ForIter __l, typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); ++ void __append(size_type __n); ++ void __append(size_type __n, const value_type& __v); ++ void __erase_to_end(const_iterator __f); ++ void __add_front_capacity(); ++ void __add_front_capacity(size_type __n); ++ void __add_back_capacity(); ++ void __add_back_capacity(size_type __n); ++ iterator __move_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); ++ iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); ++ void __move_construct_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); ++ void __move_construct_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); ++ ++ _LIBCPP_INLINE_VISIBILITY ++ void __copy_assign_alloc(const deque& __c) { ++ __copy_assign_alloc(__c, integral_constant()); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ void __copy_assign_alloc(const deque& __c, true_type) { ++ if (__base::__alloc() != __c.__alloc()) { ++ clear(); ++ shrink_to_fit(); ++ } ++ __base::__alloc() = __c.__alloc(); ++ __base::__map_.__alloc() = __c.__map_.__alloc(); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ void __copy_assign_alloc(const deque&, false_type) {} ++ ++ void __move_assign(deque& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); ++ void __move_assign(deque& __c, false_type); + +- void __move_assign(deque& __c, true_type) +- _NOEXCEPT_(is_nothrow_move_assignable::value); +- void __move_assign(deque& __c, false_type); ++public: ++ ~deque() { __annotate_delete(); } + }; + + #if _LIBCPP_STD_VER >= 17 +@@ -1621,8 +1966,9 @@ deque(_InputIterator, _InputIterator, _Alloc) + template + deque<_Tp, _Allocator>::deque(size_type __n) + { +- if (__n > 0) +- __append(__n); ++ __annotate_new(0); ++ if (__n > 0) ++ __append(__n); + } + + #if _LIBCPP_STD_VER > 11 +@@ -1630,16 +1976,18 @@ template + deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) + : __base(__a) + { +- if (__n > 0) +- __append(__n); ++ __annotate_new(0); ++ if (__n > 0) ++ __append(__n); + } + #endif + + template + deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) + { +- if (__n > 0) +- __append(__n, __v); ++ __annotate_new(0); ++ if (__n > 0) ++ __append(__n, __v); + } + + template +@@ -1647,7 +1995,8 @@ template + deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + { +- __append(__f, __l); ++ __annotate_new(0); ++ __append(__f, __l); + } + + template +@@ -1656,21 +2005,24 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, const allocator_ty + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + : __base(__a) + { +- __append(__f, __l); ++ __annotate_new(0); ++ __append(__f, __l); + } + + template + deque<_Tp, _Allocator>::deque(const deque& __c) + : __base(__alloc_traits::select_on_container_copy_construction(__c.__alloc())) + { +- __append(__c.begin(), __c.end()); ++ __annotate_new(0); ++ __append(__c.begin(), __c.end()); + } + + template + deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t& __a) + : __base(__a) + { +- __append(__c.begin(), __c.end()); ++ __annotate_new(0); ++ __append(__c.begin(), __c.end()); + } + + template +@@ -1690,14 +2042,16 @@ deque<_Tp, _Allocator>::operator=(const deque& __c) + template + deque<_Tp, _Allocator>::deque(initializer_list __il) + { +- __append(__il.begin(), __il.end()); ++ __annotate_new(0); ++ __append(__il.begin(), __il.end()); + } + + template + deque<_Tp, _Allocator>::deque(initializer_list __il, const allocator_type& __a) + : __base(__a) + { +- __append(__il.begin(), __il.end()); ++ __annotate_new(0); ++ __append(__il.begin(), __il.end()); + } + + template +@@ -1839,12 +2193,13 @@ deque<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT + allocator_type& __a = __base::__alloc(); + if (empty()) + { +- while (__base::__map_.size() > 0) +- { +- __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); +- __base::__map_.pop_back(); +- } ++ __annotate_delete(); ++ while (__base::__map_.size() > 0) { ++ __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); ++ __base::__map_.pop_back(); ++ } + __base::__start_ = 0; ++ __annotate_new(0); + } + else + { +@@ -1938,6 +2293,7 @@ deque<_Tp, _Allocator>::push_back(const value_type& __v) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_spare() >= 1 ++ __annotate_increase_back(1); + __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), __v); + ++__base::size(); + } +@@ -1950,6 +2306,7 @@ deque<_Tp, _Allocator>::push_front(const value_type& __v) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); + --__base::__start_; + ++__base::size(); +@@ -1964,6 +2321,7 @@ deque<_Tp, _Allocator>::push_back(value_type&& __v) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_spare() >= 1 ++ __annotate_increase_back(1); + __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::move(__v)); + ++__base::size(); + } +@@ -1981,6 +2339,7 @@ deque<_Tp, _Allocator>::emplace_back(_Args&&... __args) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_spare() >= 1 ++ __annotate_increase_back(1); + __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), + _VSTD::forward<_Args>(__args)...); + ++__base::size(); +@@ -1997,6 +2356,7 @@ deque<_Tp, _Allocator>::push_front(value_type&& __v) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); + --__base::__start_; + ++__base::size(); +@@ -2016,6 +2376,7 @@ deque<_Tp, _Allocator>::emplace_front(_Args&&... __args) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); + --__base::__start_; + ++__base::size(); +@@ -2036,6 +2397,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, value_type&& __v) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + if (__pos == 0) + { + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); +@@ -2059,6 +2421,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, value_type&& __v) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_capacity >= 1 ++ __annotate_increase_back(1); + size_type __de = __base::size() - __pos; + if (__de == 0) + { +@@ -2092,6 +2455,7 @@ deque<_Tp, _Allocator>::emplace(const_iterator __p, _Args&&... __args) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + if (__pos == 0) + { + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); +@@ -2116,6 +2480,7 @@ deque<_Tp, _Allocator>::emplace(const_iterator __p, _Args&&... __args) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_capacity >= 1 ++ __annotate_increase_back(1); + size_type __de = __base::size() - __pos; + if (__de == 0) + { +@@ -2152,6 +2517,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, const value_type& __v) + if (__front_spare() == 0) + __add_front_capacity(); + // __front_spare() >= 1 ++ __annotate_increase_front(1); + if (__pos == 0) + { + __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); +@@ -2178,6 +2544,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, const value_type& __v) + if (__back_spare() == 0) + __add_back_capacity(); + // __back_capacity >= 1 ++ __annotate_increase_back(1); + size_type __de = __base::size() - __pos; + if (__de == 0) + { +@@ -2213,6 +2580,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, size_type __n, const value_ty + if (__n > __front_spare()) + __add_front_capacity(__n - __front_spare()); + // __n <= __front_spare() ++ __annotate_increase_front(__n); + iterator __old_begin = __base::begin(); + iterator __i = __old_begin; + if (__n > __pos) +@@ -2237,6 +2605,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, size_type __n, const value_ty + if (__n > __back_capacity) + __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity ++ __annotate_increase_back(__n); + iterator __old_end = __base::end(); + iterator __i = __old_end; + size_type __de = __base::size() - __pos; +@@ -2299,6 +2668,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, _BiIter __f, _BiIter __l, + if (__n > __front_spare()) + __add_front_capacity(__n - __front_spare()); + // __n <= __front_spare() ++ __annotate_increase_front(__n); + iterator __old_begin = __base::begin(); + iterator __i = __old_begin; + _BiIter __m = __f; +@@ -2329,6 +2699,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, _BiIter __f, _BiIter __l, + if (__n > __back_capacity) + __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity ++ __annotate_increase_back(__n); + iterator __old_end = __base::end(); + iterator __i = __old_end; + _BiIter __m = __l; +@@ -2379,6 +2750,7 @@ deque<_Tp, _Allocator>::__append(_ForIter __f, _ForIter __l, + if (__n > __back_capacity) + __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity ++ __annotate_increase_back(__n); + for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { + _ConstructTransaction __tx(this, __br); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) { +@@ -2396,6 +2768,7 @@ deque<_Tp, _Allocator>::__append(size_type __n) + if (__n > __back_capacity) + __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity ++ __annotate_increase_back(__n); + for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { + _ConstructTransaction __tx(this, __br); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { +@@ -2413,6 +2786,7 @@ deque<_Tp, _Allocator>::__append(size_type __n, const value_type& __v) + if (__n > __back_capacity) + __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity ++ __annotate_increase_back(__n); + for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) { + _ConstructTransaction __tx(this, __br); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { +@@ -2454,6 +2828,7 @@ deque<_Tp, _Allocator>::__add_front_capacity() + __base::__start_ = __base::__map_.size() == 1 ? + __base::__block_size / 2 : + __base::__start_ + __base::__block_size; ++ __annotate_poison_from_to_back(0, __base::__block_size); + } + // Else need to allocate 1 buffer, *and* we need to reallocate __map_. + else +@@ -2479,6 +2854,7 @@ deque<_Tp, _Allocator>::__add_front_capacity() + __base::__start_ = __base::__map_.size() == 1 ? + __base::__block_size / 2 : + __base::__start_ + __base::__block_size; ++ __annotate_poison_from_to_back(0, __base::__block_size); + } + } + +@@ -2515,6 +2891,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) + if (__base::__map_.__front_spare() == 0) + break; + __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); ++ __annotate_poison_from_to_back(0, __base::__block_size); + } + for (; __nb > 0; --__nb, ++__back_capacity) + __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); +@@ -2525,6 +2902,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) + pointer __pt = __base::__map_.back(); + __base::__map_.pop_back(); + __base::__map_.push_front(__pt); ++ __annotate_poison_from_to_back(0, __base::__block_size); + } + } + // Else need to allocate __nb buffers, *and* we need to reallocate __map_. +@@ -2539,16 +2917,24 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) + try + { + #endif // _LIBCPP_NO_EXCEPTIONS +- for (; __nb > 0; --__nb) +- __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); ++ for (; __nb > 0; --__nb) { ++ __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); ++ // ASan: this is empty container, we have to poison whole ++ __annotate_contiguous_container_back( ++ std::__to_address(__buf.back()), ++ std::__to_address(__buf.back() + __base::__block_size), ++ std::__to_address(__buf.back() + __base::__block_size), ++ std::__to_address(__buf.back()), ++ std::__to_address(__buf.back())); ++ } + #ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { +- for (typename __base::__map_pointer __i = __buf.begin(); +- __i != __buf.end(); ++__i) +- __alloc_traits::deallocate(__a, *__i, __base::__block_size); +- throw; ++ __annotate_delete(); ++ for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) ++ __alloc_traits::deallocate(__a, *__i, __base::__block_size); ++ throw; + } + #endif // _LIBCPP_NO_EXCEPTIONS + for (; __back_capacity > 0; --__back_capacity) +@@ -2596,6 +2982,8 @@ deque<_Tp, _Allocator>::__add_back_capacity() + __base::__map_.pop_front(); + __base::__map_.push_back(__pt); + } ++ __annotate_poison_from_to_back( ++ (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + } + // Else need to allocate 1 buffer, *and* we need to reallocate __map_. + else +@@ -2619,6 +3007,8 @@ deque<_Tp, _Allocator>::__add_back_capacity() + _VSTD::swap(__base::__map_.__begin_, __buf.__begin_); + _VSTD::swap(__base::__map_.__end_, __buf.__end_); + _VSTD::swap(__base::__map_.__end_cap(), __buf.__end_cap()); ++ __annotate_poison_from_to_back( ++ (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + } + } + +@@ -2655,10 +3045,14 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) + if (__base::__map_.__back_spare() == 0) + break; + __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); ++ __annotate_poison_from_to_back( ++ (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); ++ } ++ for (; __nb > 0; ++ --__nb, ++__front_capacity, __base::__start_ += __base::__block_size - (__base::__map_.size() == 1)) { ++ __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); ++ __annotate_poison_from_to_back(0, __base::__block_size); + } +- for (; __nb > 0; --__nb, ++__front_capacity, __base::__start_ += +- __base::__block_size - (__base::__map_.size() == 1)) +- __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); + // Done allocating, reorder capacity + __base::__start_ -= __base::__block_size * __front_capacity; + for (; __front_capacity > 0; --__front_capacity) +@@ -2681,16 +3075,24 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) + try + { + #endif // _LIBCPP_NO_EXCEPTIONS +- for (; __nb > 0; --__nb) +- __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); ++ for (; __nb > 0; --__nb) { ++ __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); ++ // ASan: this is empty container, we have to poison whole ++ __annotate_contiguous_container_back( ++ std::__to_address(__buf.back()), ++ std::__to_address(__buf.back() + __base::__block_size), ++ std::__to_address(__buf.back() + __base::__block_size), ++ std::__to_address(__buf.back()), ++ std::__to_address(__buf.back())); ++ } + #ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { +- for (typename __base::__map_pointer __i = __buf.begin(); +- __i != __buf.end(); ++__i) +- __alloc_traits::deallocate(__a, *__i, __base::__block_size); +- throw; ++ __annotate_delete(); ++ for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) ++ __alloc_traits::deallocate(__a, *__i, __base::__block_size); ++ throw; + } + #endif // _LIBCPP_NO_EXCEPTIONS + for (; __front_capacity > 0; --__front_capacity) +@@ -2713,13 +3115,16 @@ template + void + deque<_Tp, _Allocator>::pop_front() + { +- allocator_type& __a = __base::__alloc(); +- __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + +- __base::__start_ / __base::__block_size) + +- __base::__start_ % __base::__block_size)); +- --__base::size(); +- ++__base::__start_; +- __maybe_remove_front_spare(); ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; ++ allocator_type& __a = __base::__alloc(); ++ __alloc_traits::destroy(__a, ++ _VSTD::__to_address(*(__base::__map_.begin() + __base::__start_ / __base::__block_size) + ++ __base::__start_ % __base::__block_size)); ++ --__base::size(); ++ ++__base::__start_; ++ __annotate_shrink_front(__old_sz, __old_start); ++ __maybe_remove_front_spare(); + } + + template +@@ -2727,12 +3132,15 @@ void + deque<_Tp, _Allocator>::pop_back() + { + _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; + allocator_type& __a = __base::__alloc(); + size_type __p = __base::size() + __base::__start_ - 1; + __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + + __p / __base::__block_size) + + __p % __base::__block_size)); + --__base::size(); ++ __annotate_shrink_back(__old_sz, __old_start); + __maybe_remove_back_spare(); + } + +@@ -2872,25 +3280,26 @@ template + typename deque<_Tp, _Allocator>::iterator + deque<_Tp, _Allocator>::erase(const_iterator __f) + { +- iterator __b = __base::begin(); +- difference_type __pos = __f - __b; +- iterator __p = __b + __pos; +- allocator_type& __a = __base::__alloc(); +- if (static_cast(__pos) <= (__base::size() - 1) / 2) +- { // erase from front +- _VSTD::move_backward(__b, __p, _VSTD::next(__p)); +- __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); +- --__base::size(); +- ++__base::__start_; +- __maybe_remove_front_spare(); +- } +- else +- { // erase from back +- iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); +- __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); +- --__base::size(); +- __maybe_remove_back_spare(); +- } ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; ++ iterator __b = __base::begin(); ++ difference_type __pos = __f - __b; ++ iterator __p = __b + __pos; ++ allocator_type& __a = __base::__alloc(); ++ if (static_cast(__pos) <= (__base::size() - 1) / 2) { // erase from front ++ _VSTD::move_backward(__b, __p, _VSTD::next(__p)); ++ __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); ++ --__base::size(); ++ ++__base::__start_; ++ __annotate_shrink_front(__old_sz, __old_start); ++ __maybe_remove_front_spare(); ++ } else { // erase from back ++ iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); ++ __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); ++ --__base::size(); ++ __annotate_shrink_back(__old_sz, __old_start); ++ __maybe_remove_back_spare(); ++ } + return __base::begin() + __pos; + } + +@@ -2898,33 +3307,33 @@ template + typename deque<_Tp, _Allocator>::iterator + deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) + { +- difference_type __n = __l - __f; +- iterator __b = __base::begin(); +- difference_type __pos = __f - __b; +- iterator __p = __b + __pos; +- if (__n > 0) +- { +- allocator_type& __a = __base::__alloc(); +- if (static_cast(__pos) <= (__base::size() - __n) / 2) +- { // erase from front +- iterator __i = _VSTD::move_backward(__b, __p, __p + __n); +- for (; __b != __i; ++__b) +- __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); +- __base::size() -= __n; +- __base::__start_ += __n; +- while (__maybe_remove_front_spare()) { +- } +- } +- else +- { // erase from back +- iterator __i = _VSTD::move(__p + __n, __base::end(), __p); +- for (iterator __e = __base::end(); __i != __e; ++__i) +- __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); +- __base::size() -= __n; +- while (__maybe_remove_back_spare()) { +- } +- } ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; ++ difference_type __n = __l - __f; ++ iterator __b = __base::begin(); ++ difference_type __pos = __f - __b; ++ iterator __p = __b + __pos; ++ if (__n > 0) { ++ allocator_type& __a = __base::__alloc(); ++ if (static_cast(__pos) <= (__base::size() - __n) / 2) { // erase from front ++ iterator __i = _VSTD::move_backward(__b, __p, __p + __n); ++ for (; __b != __i; ++__b) ++ __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); ++ __base::size() -= __n; ++ __base::__start_ += __n; ++ __annotate_shrink_front(__old_sz, __old_start); ++ while (__maybe_remove_front_spare()) { ++ } ++ } else { // erase from back ++ iterator __i = _VSTD::move(__p + __n, __base::end(), __p); ++ for (iterator __e = __base::end(); __i != __e; ++__i) ++ __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); ++ __base::size() -= __n; ++ __annotate_shrink_back(__old_sz, __old_start); ++ while (__maybe_remove_back_spare()) { ++ } + } ++ } + return __base::begin() + __pos; + } + +@@ -2932,19 +3341,21 @@ template + void + deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) + { +- iterator __e = __base::end(); +- difference_type __n = __e - __f; +- if (__n > 0) +- { +- allocator_type& __a = __base::__alloc(); +- iterator __b = __base::begin(); +- difference_type __pos = __f - __b; +- for (iterator __p = __b + __pos; __p != __e; ++__p) +- __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); +- __base::size() -= __n; +- while (__maybe_remove_back_spare()) { +- } ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; ++ iterator __e = __base::end(); ++ difference_type __n = __e - __f; ++ if (__n > 0) { ++ allocator_type& __a = __base::__alloc(); ++ iterator __b = __base::begin(); ++ difference_type __pos = __f - __b; ++ for (iterator __p = __b + __pos; __p != __e; ++__p) ++ __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); ++ __base::size() -= __n; ++ __annotate_shrink_back(__old_sz, __old_start); ++ while (__maybe_remove_back_spare()) { + } ++ } + } + + template +@@ -2966,7 +3377,9 @@ inline + void + deque<_Tp, _Allocator>::clear() _NOEXCEPT + { +- __base::clear(); ++ __annotate_delete(); ++ __base::clear(); ++ __annotate_new(0); + } + + template +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp +new file mode 100644 +index 000000000000..8376f4f8db6e +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp +@@ -0,0 +1,461 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++#if TEST_STD_VER >= 11 ++template ++void test_assign_d5(const size_t N) { ++ typedef std::deque D; ++ D empty_d5; ++ D short_d5a(1), short_d5b(N - 1); ++ D mid_d5(N + 1); ++ D long_d5(32 * N + 1); ++ ++ empty_d5.assign({T(), T()}); ++ short_d5a.assign({T(), T()}); ++ short_d5b.assign({T(), T()}); ++ mid_d5.assign({T(), T()}); ++ long_d5.assign({T(), T()}); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5)); ++ ++ empty_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ short_d5a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ short_d5b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ mid_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ long_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ ++ assert(empty_d5.size() > 16); ++ assert(short_d5a.size() > 16); ++ assert(short_d5b.size() > 16); ++ assert(mid_d5.size() > 16); ++ assert(long_d5.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5)); ++} ++ ++template ++void test_assign_d6(const size_t N) { ++ typedef std::deque D; ++ D empty_d6; ++ D short_d6a(1), short_d6b(N - 1); ++ D mid_d6(N + 1); ++ D long_d6(32 * N + 1); ++ ++ empty_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ short_d6a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ short_d6b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ mid_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ long_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ ++ assert(empty_d6.size() > 16); ++ assert(short_d6a.size() > 16); ++ assert(short_d6b.size() > 16); ++ assert(mid_d6.size() > 16); ++ assert(long_d6.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6)); ++} ++ ++template ++void test_assign_d7(const size_t N) { ++ typedef std::deque D; ++ const T val = T(); ++ D empty_d7; ++ D short_d7a(1), short_d7b(N - 1); ++ D mid_d7(N + 1); ++ D long_d7(32 * N + 1); ++ ++ empty_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ short_d7a.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ short_d7b.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ mid_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ long_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ ++ assert(empty_d7.size() > 16); ++ assert(short_d7a.size() > 16); ++ assert(short_d7b.size() > 16); ++ assert(mid_d7.size() > 16); ++ assert(long_d7.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d7)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d7)); ++} ++#endif // TEST_STD_VER >= 11 ++ ++template ++void test_assign() { ++ typedef std::deque D; ++ const size_t N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void assign( size_type count, const T& value ); ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(N - 1); ++ D mid_d1(N + 1); ++ D long_d1(32 * N + 1); ++ ++ empty_d1.assign(2, T()); ++ short_d1a.assign(2, T()); ++ short_d1b.assign(2, T()); ++ mid_d1.assign(2, T()); ++ long_d1.assign(2, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ ++ empty_d1.assign(2 * N, T()); ++ short_d1a.assign(2 * N, T()); ++ short_d1b.assign(2 * N, T()); ++ mid_d1.assign(2 * N, T()); ++ long_d1.assign(2 * N, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ ++ D empty_d2; ++ D short_d2a(1), short_d2b(N - 1); ++ D mid_d2(N + 1); ++ D long_d2(32 * N + 1); ++ ++ empty_d2.assign(42 * N, T()); ++ short_d2a.assign(42 * N, T()); ++ short_d2b.assign(42 * N, T()); ++ mid_d2.assign(42 * N, T()); ++ long_d2.assign(42 * N, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2)); ++ ++ // template< class InputIt > ++ // void assign( InputIt first, InputIt last ); ++ D source_d(50 * N); ++ ++ D empty_d3; ++ D short_d3a(1), short_d3b(N - 1); ++ D mid_d3(N + 1); ++ D long_d3(32 * N + 1); ++ ++ empty_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); ++ short_d3a.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); ++ short_d3b.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); ++ mid_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); ++ long_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(source_d)); ++ ++ empty_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); ++ short_d3a.assign(source_d.begin() + N, source_d.begin() + 3 * N); ++ short_d3b.assign(source_d.begin() + N, source_d.begin() + 3 * N); ++ mid_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); ++ long_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(source_d)); ++ ++ D empty_d4; ++ D short_d4a(1), short_d4b(N - 1); ++ D mid_d4(N + 1); ++ D long_d4(32 * N + 1); ++ ++ empty_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); ++ short_d4a.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); ++ short_d4b.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); ++ mid_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); ++ long_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d4a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d4b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d4)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4)); ++ assert(is_double_ended_contiguous_container_asan_correct(source_d)); ++ ++#if TEST_STD_VER >= 11 ++ // void assign( std::initializer_list ilist ); ++ test_assign_d5(N); ++ test_assign_d6(N); ++ test_assign_d7(N); ++#endif ++} ++ ++template ++void test_operator() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // deque& operator=( const deque& other ); ++ ++ D empty_d1, empty_d2; ++ D mid_d1(N), mid_d2(N); ++ D long_d1(32 * N), long_d2(32 * N); ++ ++ empty_d1 = empty_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ empty_d1 = mid_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ empty_d1 = empty_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ empty_d1 = long_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ empty_d1 = empty_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ ++ empty_d2 = long_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ ++ mid_d1 = long_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = empty_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = long_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = mid_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ ++ long_d1 = long_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ long_d1 = empty_d1; ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ long_d1 = long_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ ++ empty_d1 = D(); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ mid_d1 = D(); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ long_d1 = D(); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ ++ mid_d1 = mid_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ long_d1 = long_d2; ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ ++ // deque& operator=( deque&& other ) ++ ++#if TEST_STD_VER >= 11 ++ mid_d1 = std::move(mid_d2); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2)); ++ long_d1 = std::move(long_d2); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2)); ++ ++ D mid_d3a(N), mid_d3b(N); ++ D long_d3a(32 * N), long_d3b(32 * N); ++ ++ mid_d3a = std::move(long_d3a); ++ long_d3b = std::move(mid_d3b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); ++ ++ D empty_d4; ++ D long_d4a(32 * N), long_d4b(32 * N); ++ ++ long_d4a = std::move(empty_d4); ++ long_d4b = std::move(empty_d1); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4b)); ++ ++ // void assign( std::initializer_list ilist ) ++ ++ D empty_d5; ++ D short_d5a(1), short_d5b(N - 1); ++ D mid_d5(N + 1); ++ D long_d5(32 * N + 1); ++ ++ empty_d5 = {T(), T()}; ++ short_d5a = {T(), T()}; ++ short_d5b = {T(), T()}; ++ mid_d5 = {T(), T()}; ++ long_d5 = {T(), T()}; ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5)); ++ ++ empty_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ short_d5a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ short_d5b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ mid_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ long_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ ++ assert(empty_d5.size() > 16); ++ assert(short_d5a.size() > 16); ++ assert(short_d5b.size() > 16); ++ assert(mid_d5.size() > 16); ++ assert(long_d5.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5)); ++ ++ D empty_d6; ++ D short_d6a(1), short_d6b(N - 1); ++ D mid_d6(N + 1); ++ D long_d6(32 * N + 1); ++ ++ empty_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ short_d6a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ short_d6b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ mid_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ long_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; ++ ++ assert(empty_d6.size() > 16); ++ assert(short_d6a.size() > 16); ++ assert(short_d6b.size() > 16); ++ assert(mid_d6.size() > 16); ++ assert(long_d6.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6)); ++ ++ empty_d6 = {}; ++ short_d6a = {}; ++ short_d6b = {}; ++ mid_d6 = {}; ++ long_d6 = {}; ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6)); ++ ++ D empty_d7; ++ D short_d7a(1), short_d7b(N - 1); ++ D mid_d7(N + 1); ++ D long_d7a(32 * N + 1), long_d7b(32 * N + 1); ++ ++ empty_d7 = {}; ++ short_d7a = {}; ++ short_d7b = {}; ++ mid_d7 = {}; ++ long_d7a = {}; ++ ++ long_d7b.pop_front(); ++ long_d7b = {}; ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d7)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d7a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d7b)); ++#endif // TEST_STD_VER >= 11 ++} ++ ++template ++void test() { ++ test_assign(); ++ test_operator(); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp +new file mode 100644 +index 000000000000..d1a118f0616b +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp +@@ -0,0 +1,96 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void clear() ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(2); ++ D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); ++ D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); ++ ++ empty_d1.clear(); ++ short_d1a.clear(); ++ short_d1b.clear(); ++ mid_d1a.clear(); ++ mid_d1b.clear(); ++ mid_d1c.clear(); ++ long_d1a.clear(); ++ long_d1b.clear(); ++ long_d1c.clear(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ typedef std::deque D; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp +new file mode 100644 +index 000000000000..7f26f6e8680e +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp +@@ -0,0 +1,313 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // Different constructors are called based on the used standard. ++ // Please, check https://en.cppreference.com/w/cpp/container/deque/deque ++ // for full list. ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(2); ++ D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); ++ D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d2(empty_d1); ++ D short_d2a(short_d1a), short_d2b(short_d1b); ++ D mid_d2a(mid_d1a), mid_d2b(mid_d1b), mid_d2c(mid_d1c); ++ D long_d2a(long_d1a), long_d2b(long_d1b), long_d2c(long_d1c); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d3(std::move(empty_d2)); ++ D short_d3a(std::move(short_d2a)), short_d3b(std::move(short_d2b)); ++ D mid_d3a(std::move(mid_d2a)), mid_d3b(std::move(mid_d2b)), mid_d3c(std::move(mid_d2c)); ++ D long_d3a(std::move(long_d2a)), long_d3b(std::move(long_d2b)), long_d3c(std::move(long_d2c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++ ++#if TEST_STD_VER >= 11 ++ D empty_d4(empty_d1.cbegin(), empty_d1.cend()); ++ D short_d4a(short_d1a.cbegin(), short_d1a.cend()), short_d4b(short_d1b.cbegin(), short_d1b.cend()); ++ D mid_d4a(mid_d1a.cbegin(), mid_d1a.cend()), mid_d4b(mid_d1b.cbegin(), mid_d1b.cend()), ++ mid_d4c(mid_d1c.cbegin(), mid_d1c.cend()); ++ D long_d4a(long_d1a.cbegin(), long_d1a.cend()), long_d4b(long_d1a.cbegin(), long_d1a.cend()), ++ long_d4c(long_d1a.cbegin(), long_d1a.cend()); ++#else ++ D empty_d4(empty_d1.begin(), empty_d1.end()); ++ D short_d4a(short_d1a.begin(), short_d1a.end()), short_d4b(short_d1b.begin(), short_d1b.end()); ++ D mid_d4a(mid_d1a.begin(), mid_d1a.end()), mid_d4b(mid_d1b.begin(), mid_d1b.end()), ++ mid_d4c(mid_d1c.begin(), mid_d1c.end()); ++ D long_d4a(long_d1a.begin(), long_d1a.end()), long_d4b(long_d1a.begin(), long_d1a.end()), ++ long_d4c(long_d1a.begin(), long_d1a.end()); ++#endif ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d4)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d4a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d4b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d4a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d4b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d4c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d4c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++#if TEST_STD_VER >= 11 ++ D empty_d5(empty_d1.crbegin(), empty_d1.crend()); ++ D short_d5a(short_d1a.crbegin(), short_d1a.crend()), short_d5b(short_d1b.crbegin(), short_d1b.crend()); ++ D mid_d5a(mid_d1a.crbegin(), mid_d1a.crend()), mid_d5b(mid_d1b.crbegin(), mid_d1b.crend()), ++ mid_d5c(mid_d1c.crbegin(), mid_d1c.crend()); ++ D long_d5a(long_d1a.crbegin(), long_d1a.crend()), long_d5b(long_d1a.crbegin(), long_d1a.crend()), ++ long_d5c(long_d1a.crbegin(), long_d1a.crend()); ++#else ++ D empty_d5(empty_d1.rbegin(), empty_d1.rend()); ++ D short_d5a(short_d1a.rbegin(), short_d1a.rend()), short_d5b(short_d1b.rbegin(), short_d1b.rend()); ++ D mid_d5a(mid_d1a.rbegin(), mid_d1a.rend()), mid_d5b(mid_d1b.rbegin(), mid_d1b.rend()), ++ mid_d5c(mid_d1c.rbegin(), mid_d1c.rend()); ++ D long_d5a(long_d1a.rbegin(), long_d1a.rend()), long_d5b(long_d1a.rbegin(), long_d1a.rend()), ++ long_d5c(long_d1a.rbegin(), long_d1a.rend()); ++#endif ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d5)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d5c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d5c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d6(0, T()); ++ D short_d6a(1, T()), short_d6b(2, T()); ++ D mid_d6a(N - 1, T()), mid_d6b(N, T()), mid_d6c(N + 1, T()); ++ D long_d6a(17 * N - 1, T()), long_d6b(8 * N, T()), long_d6c(11 * N + 1, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d6)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d6c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d6c)); ++ ++#if TEST_STD_VER >= 11 ++ D empty_d7({}); ++ D short_d7a({T()}), short_d7b({T(), T()}); ++ D mid_d7a({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ D mid_d7b({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d7)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d7b)); ++ assert(mid_d7a.size() == 16); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d7a)); ++ assert(mid_d7b.size() == 17); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d7b)); ++ ++ const T val = T(); ++ D empty_d8({}); ++ D short_d8a({val}), short_d8b({val, val}); ++ D mid_d8a({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ D mid_d8b({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d8)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d8a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d8b)); ++ assert(mid_d8a.size() == 16); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d8a)); ++ assert(mid_d8b.size() == 17); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d8b)); ++#endif ++ ++ D empty_d9a((std::allocator())), empty_d9b(empty_d1.get_allocator()); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d9a)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d9b)); ++ ++#if TEST_STD_VER >= 11 ++ D empty_d10(empty_d3, std::allocator()); ++ D short_d10a(short_d3a, std::allocator()), short_d10b(short_d3b, std::allocator()); ++ D mid_d10a(mid_d3a, std::allocator()), mid_d10b(mid_d3b, std::allocator()), ++ mid_d10c(mid_d3c, std::allocator()); ++ D long_d10a(long_d3a, std::allocator()), long_d10b(long_d3b, std::allocator()), ++ long_d10c(long_d3c, std::allocator()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d10)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d3)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d3c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d3c)); ++ ++ D empty_d11(std::move(empty_d10), std::allocator()); ++ D short_d11a(std::move(short_d10a), std::allocator()), short_d11b(std::move(short_d10b), std::allocator()); ++ D mid_d11a(std::move(mid_d10a), std::allocator()), mid_d11b(std::move(mid_d10b), std::allocator()), ++ mid_d11c(std::move(mid_d10c), std::allocator()); ++ D long_d11a(std::move(long_d10a), std::allocator()), long_d11b(std::move(long_d10b), std::allocator()), ++ long_d11c(std::move(long_d10c), std::allocator()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d11)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d11a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d11b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d11a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d11b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d11c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d11a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d11b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d11c)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d10)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d10c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d10c)); ++#endif ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp +new file mode 100644 +index 000000000000..6c0e2d720842 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp +@@ -0,0 +1,86 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// ++//===----------------------------------------------------------------------===// ++ ++// ++ ++// The test helped us find issues with llvm12 implementation, ++// but it's a problematic one now. ++// We may want to delete it. ++ ++// UNSUPPORTED: c++03 ++ ++#include ++#include ++#include "emplace_constructible.h" ++#include "asan_testing.h" // includes deque - don't do it before ++#include "test_iterators.h" ++ ++template ++void test_constructible() { ++ T arr1[] = {T()}; ++ using T2 = EmplaceConstructibleMoveableAndAssignable; ++ using It = cpp17_input_iterator; ++ typedef std::deque D; ++ ++ D d; ++ d.assign(It(arr1), It(std::end(arr1))); ++ assert(is_double_ended_contiguous_container_asan_correct(d)); ++} ++ ++template ++void test() { ++ test_constructible(); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp +new file mode 100644 +index 000000000000..69681ce4704d +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp +@@ -0,0 +1,137 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // iterator erase( iterator first, iterator last ); ++ // iterator erase( const_iterator first, const_iterator last ); ++ ++ D d1a(N), d1b(N), d1c(N); ++#if TEST_STD_VER >= 11 ++ d1a.erase(d1a.cbegin(), d1a.cend()); ++ d1b.erase(d1b.cbegin() + 1); ++ d1c.erase(d1c.cend() - 1); ++#else ++ d1a.erase(d1a.begin(), d1a.end()); ++ d1b.erase(d1b.begin() + 1); ++ d1c.erase(d1c.end() - 1); ++#endif ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1c)); ++ ++ D d2a(N + 1), d2b(N + 1), d2c(N + 1), d2d(N + 1); ++ ++ d2a.erase(d2a.begin(), d2a.end() - 2); ++ d2b.erase(d2b.begin() + 1, d2b.end()); ++ // iterator erase( iterator pos ); ++ // iterator erase( const_iterator pos ); ++ d2c.erase(d2c.begin() + 2); ++ d2d.erase(d2d.end() - 3); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2c.erase(d2c.begin() + 2); ++ d2d.erase(d2d.end() - 3); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2c.erase(d2c.begin() + 2); ++ d2d.erase(d2d.end() - 3); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ D d3a(32 * N + 1), d3b(32 * N + 1), d3c(32 * N + 1), d3d(32 * N + 1); ++ ++ d3a.erase(d3a.begin() + N + 1, d3a.end() - N - 2); ++ d3b.erase(d3b.begin() + N - 1, d3b.end()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3b)); ++ while (d3c.size() > 3) { ++ d3c.erase(d3c.begin() + 2); ++ assert(is_double_ended_contiguous_container_asan_correct(d3c)); ++ } ++ while (d3d.size() > 4) { ++ d3d.erase(d3d.end() - 3); ++ assert(is_double_ended_contiguous_container_asan_correct(d3d)); ++ } ++ ++ D d4a(32 * N + 3), d4b(32 * N + 3); ++ while (d4a.size() > 5) { ++ d4a.erase(d4a.begin() + 2, d4a.begin() + 4); ++ assert(is_double_ended_contiguous_container_asan_correct(d4a)); ++ } ++ ++ while (d4b.size() > 5) { ++ d4b.erase(d4b.end() - 4, d4b.end() - 2); ++ assert(is_double_ended_contiguous_container_asan_correct(d4b)); ++ } ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp +new file mode 100644 +index 000000000000..3950247565da +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp +@@ -0,0 +1,278 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_insert() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ T t = T(); ++ D d1a(2), d1b(2), d1c(2); ++ ++#if TEST_STD_VER >= 11 ++ d1a.insert(d1a.cbegin(), t); ++ d1b.insert(d1b.cend(), t); ++ d1c.insert(d1c.cbegin() + 1, t); ++#else ++ d1a.insert(d1a.begin(), t); ++ d1b.insert(d1b.end(), t); ++ d1c.insert(d1c.begin() + 1, t); ++#endif ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1c)); ++ ++ D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); ++ ++ d2a.insert(d2a.begin(), t); ++ d2b.insert(d2b.end(), t); ++ d2c.insert(d2c.begin() + 1, t); ++ d2d.insert(d2d.end() - 1, t); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.insert(d2a.begin(), 2 * N + 1, t); ++ d2b.insert(d2b.end(), 2 * N + 1, t); ++ d2c.insert(d2c.begin() + 1, 2 * N + 1, t); ++ d2d.insert(d2d.end() - 1, 2 * N + 1, t); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2c.insert(d2c.begin() + N + 1, 2 * N + 1, t); ++ d2d.insert(d2d.end() - N - 1, 2 * N + 1, t); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ D source(3 * N); ++ ++ d2a.insert(d2a.begin(), source.begin() + 1, source.end() - 1); ++ d2b.insert(d2b.end(), source.begin() + 1, source.end() - 1); ++ d2c.insert(d2c.begin() + 1, source.begin() + 1, source.end() - 1); ++ d2d.insert(d2d.end() - 1, source.begin() + 1, source.end() - 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2c.insert(d2c.begin() + N + 1, source.begin() + 1, source.end() - 1); ++ d2d.insert(d2d.end() - N - 1, source.begin() + 1, source.end() - 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.insert(d2a.begin(), T()); ++ d2b.insert(d2b.end(), T()); ++ d2c.insert(d2c.begin() + 1, T()); ++ d2d.insert(d2d.end() - 1, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ T a = T(), b = T(), c = T(), d = T(); ++ d2a.insert(d2a.begin(), a); ++ d2b.insert(d2b.end(), b); ++ d2c.insert(d2c.begin() + 1, c); ++ d2d.insert(d2d.end() - 1, d); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.insert(d2a.begin(), 3, a); ++ d2b.insert(d2b.end(), 3, b); ++ d2c.insert(d2c.begin() + 1, 3, c); ++ d2d.insert(d2d.end() - 1, 3, d); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.insert(d2a.begin(), 3 * N, a); ++ d2b.insert(d2b.end(), 3 * N, b); ++ d2c.insert(d2c.begin() + 1, 3 * N, c); ++ d2d.insert(d2d.end() - 1, 3 * N, d); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.insert(d2a.begin(), std::move(a)); ++ d2b.insert(d2b.end(), std::move(b)); ++ d2c.insert(d2c.begin() + 1, std::move(c)); ++ d2d.insert(d2d.end() - 1, std::move(d)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++#if TEST_STD_VER >= 11 ++ D d3a(2), d3b(2), d3c(2); ++ ++ d3a.insert(d3a.cbegin(), {t}); ++ d3b.insert(d3b.cend(), {t}); ++ d3c.insert(d3c.cbegin() + 1, {t}); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3c)); ++ ++ d3a.insert(d3a.cbegin(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ d3b.insert(d3b.cend(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ d3c.insert(d3c.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ ++ assert(d3a.size() > 16); ++ assert(d3b.size() > 16); ++ assert(d3c.size() > 16); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3c)); ++ ++ d3a.insert(d3a.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ d3b.insert(d3b.cend() - 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ d3c.resize(N - 1); ++ d3c.insert(d3c.cbegin() + N - 2, {t, t, t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d3a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d3c)); ++#endif ++} ++ ++#if TEST_STD_VER >= 11 ++template ++void test_emplace() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ T t = T(); ++ D d1a(2), d1b(2), d1c(2); ++ ++ d1a.emplace(d1a.cbegin(), t); ++ d1b.emplace(d1b.cend(), t); ++ d1c.emplace(d1c.cbegin() + 1, t); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d1c)); ++ ++ D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); ++ ++ d2a.emplace(d2a.cbegin(), t); ++ d2b.emplace(d2b.cend(), t); ++ d2c.emplace(d2c.cbegin() + 1, t); ++ d2d.emplace(d2d.cend() - 1, t); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ d2a.emplace(d2a.cbegin(), T()); ++ d2b.emplace(d2b.cend(), T()); ++ d2c.emplace(d2c.cbegin() + 1, T()); ++ d2d.emplace(d2d.cend() - 1, T()); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++ ++ T a = T(), b = T(), c = T(), d = T(); ++ d2a.emplace(d2a.cbegin(), std::move(a)); ++ d2b.emplace(d2b.cend(), std::move(b)); ++ d2c.emplace(d2c.cbegin() + 1, std::move(c)); ++ d2d.emplace(d2d.cend() - 1, std::move(d)); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2d)); ++} ++#endif ++ ++template ++void test() { ++ test_insert(); ++#if TEST_STD_VER >= 11 ++ test_emplace(); ++#endif ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp +new file mode 100644 +index 000000000000..2589f939162a +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp +@@ -0,0 +1,107 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_aligned() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void pop_back() ++ ++ D single_d(1); ++ single_d.pop_back(); ++ assert(is_double_ended_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ while (!d1.empty()) { ++ d1.pop_back(); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++} ++ ++template ++void test_not_aligned() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void pop_back() ++ ++ D single_d(1); ++ single_d.pop_back(); ++ assert(is_double_ended_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ d1.pop_front(); ++ ++ while (!d1.empty()) { ++ d1.pop_back(); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++} ++ ++template ++void test() { ++ test_aligned(); ++ test_not_aligned(); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ typedef std::deque D; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp +new file mode 100644 +index 000000000000..5bdeba6c0ad0 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp +@@ -0,0 +1,87 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void pop_front() ++ ++ D single_d(1); ++ single_d.pop_front(); ++ assert(is_double_ended_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ while (!d1.empty()) { ++ d1.pop_front(); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ D d2(34 * N + 1); ++ while (!d2.empty()) { ++ d2.pop_front(); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ } ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ typedef std::deque D; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp +new file mode 100644 +index 000000000000..c1aae3a933d0 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp +@@ -0,0 +1,144 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_push() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ D d1; ++ ++ // void push_back( const T& value ); ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T b = T(); ++ d1.push_back(b); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ d1.clear(); ++ ++ for (size_t i = 0; i < 34 * N; ++i) { ++ T b = T(); ++ d1.push_back(b); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++#if TEST_STD_VER >= 11 ++ // void push_back( T&& value ); ++ ++ D d2; ++ ++ for (size_t i = 0; i < 34 * N; ++i) { ++ T b = T(); ++ d2.push_back(std::move(b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ d2.push_back(T()); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ } ++#endif ++} ++ ++#if TEST_STD_VER >= 11 ++template ++void test_emplace() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // template< class... Args > ++ // reference emplace_back( Args&&... args ); ++ D d1; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T b = T(); ++ d1.emplace_back(b); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ d1.clear(); ++ ++ for (size_t i = 0; i < 34 * N; ++i) { ++ T b = T(); ++ d1.emplace_back(b); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ D d2; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T b = T(); ++ d2.emplace_back(std::move(b)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ d2.emplace_back(T()); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ } ++} ++#endif ++ ++template ++void test() { ++ test_push(); ++#if TEST_STD_VER >= 11 ++ test_emplace(); ++#endif ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp +new file mode 100644 +index 000000000000..95916d84ef1b +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp +@@ -0,0 +1,145 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_push() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // void push_front( const T& value ); ++ ++ D d1; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T f = T(); ++ d1.push_front(f); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ d1.clear(); ++ ++ for (size_t i = 0; i < 34 * N; ++i) { ++ T f = T(); ++ d1.push_front(f); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++#if TEST_STD_VER >= 11 ++ // void push_front( T&& value ); ++ ++ D d2; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T f = T(); ++ d2.push_front(std::move(f)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ d2.push_front(T()); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ } ++#endif ++} ++ ++#if TEST_STD_VER >= 11 ++template ++void test_emplace() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ // template< class... Args > ++ // reference emplace_front( Args&&... args ); ++ ++ D d1; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T f = T(); ++ d1.emplace_front(f); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ d1.clear(); ++ ++ for (size_t i = 0; i < 34 * N; ++i) { ++ T f = T(); ++ d1.emplace_front(f); ++ assert(is_double_ended_contiguous_container_asan_correct(d1)); ++ } ++ ++ D d2; ++ ++ for (size_t i = 0; i < 32 * N; ++i) { ++ T f = T(); ++ d2.emplace_front(std::move(f)); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ d2.emplace_front(T()); ++ assert(is_double_ended_contiguous_container_asan_correct(d2)); ++ } ++} ++#endif ++ ++template ++void test() { ++ test_push(); ++#if TEST_STD_VER >= 11 ++ test_emplace(); ++#endif ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp +new file mode 100644 +index 000000000000..f4f356534357 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp +@@ -0,0 +1,501 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_count() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(2); ++ D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); ++ D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(1); ++ short_d1a.resize(1); ++ short_d1b.resize(1); ++ mid_d1a.resize(1); ++ mid_d1b.resize(1); ++ mid_d1c.resize(1); ++ long_d1a.resize(1); ++ long_d1b.resize(1); ++ long_d1c.resize(1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(2); ++ short_d1a.resize(2); ++ short_d1b.resize(2); ++ mid_d1a.resize(2); ++ mid_d1b.resize(2); ++ mid_d1c.resize(2); ++ long_d1a.resize(2); ++ long_d1b.resize(2); ++ long_d1c.resize(2); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N - 1); ++ short_d1a.resize(N - 1); ++ short_d1b.resize(N - 1); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N - 1); ++ mid_d1c.resize(N - 1); ++ long_d1a.resize(N - 1); ++ long_d1b.resize(N - 1); ++ long_d1c.resize(N - 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N); ++ short_d1a.resize(N); ++ short_d1b.resize(N); ++ mid_d1a.resize(N); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N); ++ long_d1a.resize(N); ++ long_d1b.resize(N); ++ long_d1c.resize(N); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N + 1); ++ short_d1a.resize(N + 1); ++ short_d1b.resize(N + 1); ++ mid_d1a.resize(N + 1); ++ mid_d1b.resize(N + 1); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(N + 1); ++ long_d1b.resize(N + 1); ++ long_d1c.resize(N + 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N); ++ short_d1a.resize(N); ++ short_d1b.resize(N); ++ mid_d1a.resize(N); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N); ++ long_d1a.resize(N); ++ long_d1b.resize(N); ++ long_d1c.resize(N); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(20 * N); ++ short_d1a.resize(20 * N); ++ short_d1b.resize(20 * N); ++ mid_d1a.resize(20 * N); ++ mid_d1b.resize(20 * N); ++ mid_d1c.resize(20 * N); ++ long_d1a.resize(20 * N); ++ long_d1b.resize(20 * N); ++ long_d1c.resize(20 * N); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d2; ++ D short_d2a(1), short_d2b(2); ++ D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); ++ D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); ++ ++ empty_d2.resize(20 * N); ++ short_d2a.resize(20 * N); ++ short_d2b.resize(20 * N); ++ mid_d2a.resize(20 * N); ++ mid_d2b.resize(20 * N); ++ mid_d2c.resize(20 * N); ++ long_d2a.resize(20 * N); ++ long_d2b.resize(20 * N); ++ long_d2c.resize(20 * N); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++} ++ ++template ++void test_value() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ const T val = T(); ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(2); ++ D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); ++ D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); ++ ++ empty_d1.resize(0, val); ++ short_d1a.resize(1, val); ++ short_d1b.resize(2, val); ++ mid_d1a.resize(N - 1, val); ++ mid_d1b.resize(N, val); ++ mid_d1c.resize(N + 1, val); ++ long_d1a.resize(17 * N - 1, val); ++ long_d1b.resize(8 * N, val); ++ long_d1c.resize(11 * N + 1, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(1, val); ++ short_d1a.resize(1, val); ++ short_d1b.resize(1, val); ++ mid_d1a.resize(1, val); ++ mid_d1b.resize(1, val); ++ mid_d1c.resize(1, val); ++ long_d1a.resize(1, val); ++ long_d1b.resize(1, val); ++ long_d1c.resize(1, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(2, val); ++ short_d1a.resize(2, val); ++ short_d1b.resize(2, val); ++ mid_d1a.resize(2, val); ++ mid_d1b.resize(2, val); ++ mid_d1c.resize(2, val); ++ long_d1a.resize(2, val); ++ long_d1b.resize(2, val); ++ long_d1c.resize(2, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N - 1, val); ++ short_d1a.resize(N - 1, val); ++ short_d1b.resize(N - 1, val); ++ mid_d1a.resize(N - 1, val); ++ mid_d1b.resize(N - 1, val); ++ mid_d1c.resize(N - 1, val); ++ long_d1a.resize(N - 1, val); ++ long_d1b.resize(N - 1, val); ++ long_d1c.resize(N - 1, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N, val); ++ short_d1a.resize(N, val); ++ short_d1b.resize(N, val); ++ mid_d1a.resize(N, val); ++ mid_d1b.resize(N, val); ++ mid_d1c.resize(N, val); ++ long_d1a.resize(N, val); ++ long_d1b.resize(N, val); ++ long_d1c.resize(N, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N + 1, val); ++ short_d1a.resize(N + 1, val); ++ short_d1b.resize(N + 1, val); ++ mid_d1a.resize(N + 1, val); ++ mid_d1b.resize(N + 1, val); ++ mid_d1c.resize(N + 1, val); ++ long_d1a.resize(N + 1, val); ++ long_d1b.resize(N + 1, val); ++ long_d1c.resize(N + 1, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(N, val); ++ short_d1a.resize(N, val); ++ short_d1b.resize(N, val); ++ mid_d1a.resize(N, val); ++ mid_d1b.resize(N, val); ++ mid_d1c.resize(N, val); ++ long_d1a.resize(N, val); ++ long_d1b.resize(N, val); ++ long_d1c.resize(N, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(20 * N, val); ++ short_d1a.resize(20 * N, val); ++ short_d1b.resize(20 * N, val); ++ mid_d1a.resize(20 * N, val); ++ mid_d1b.resize(20 * N, val); ++ mid_d1c.resize(20 * N, val); ++ long_d1a.resize(20 * N, val); ++ long_d1b.resize(20 * N, val); ++ long_d1c.resize(20 * N, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0, val); ++ short_d1a.resize(1, val); ++ short_d1b.resize(2, val); ++ mid_d1a.resize(N - 1, val); ++ mid_d1b.resize(N, val); ++ mid_d1c.resize(N + 1, val); ++ long_d1a.resize(17 * N - 1, val); ++ long_d1b.resize(8 * N, val); ++ long_d1c.resize(11 * N + 1, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d2; ++ D short_d2a(1), short_d2b(2); ++ D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); ++ D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); ++ ++ empty_d2.resize(20 * N, val); ++ short_d2a.resize(20 * N, val); ++ short_d2b.resize(20 * N, val); ++ mid_d2a.resize(20 * N, val); ++ mid_d2b.resize(20 * N, val); ++ mid_d2c.resize(20 * N, val); ++ long_d2a.resize(20 * N, val); ++ long_d2b.resize(20 * N, val); ++ long_d2c.resize(20 * N, val); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++} ++ ++template ++void test() { ++ test_count(); ++ test_value(); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp +new file mode 100644 +index 000000000000..3de33133ec92 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp +@@ -0,0 +1,500 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// ++//===----------------------------------------------------------------------===// ++ ++// ++ ++// UNSUPPORTED: c++03 ++ ++#include ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ D empty_d1; ++ D short_d1a(1), short_d1b(2); ++ D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); ++ D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(1); ++ short_d1a.resize(1); ++ short_d1b.resize(1); ++ mid_d1a.resize(1); ++ mid_d1b.resize(1); ++ mid_d1c.resize(1); ++ long_d1a.resize(1); ++ long_d1b.resize(1); ++ long_d1c.resize(1); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(2); ++ short_d1a.resize(2); ++ short_d1b.resize(2); ++ mid_d1a.resize(2); ++ mid_d1b.resize(2); ++ mid_d1c.resize(2); ++ long_d1a.resize(2); ++ long_d1b.resize(2); ++ long_d1c.resize(2); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(N - 1); ++ short_d1a.resize(N - 1); ++ short_d1b.resize(N - 1); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N - 1); ++ mid_d1c.resize(N - 1); ++ long_d1a.resize(N - 1); ++ long_d1b.resize(N - 1); ++ long_d1c.resize(N - 1); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(N); ++ short_d1a.resize(N); ++ short_d1b.resize(N); ++ mid_d1a.resize(N); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N); ++ long_d1a.resize(N); ++ long_d1b.resize(N); ++ long_d1c.resize(N); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(N + 1); ++ short_d1a.resize(N + 1); ++ short_d1b.resize(N + 1); ++ mid_d1a.resize(N + 1); ++ mid_d1b.resize(N + 1); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(N + 1); ++ long_d1b.resize(N + 1); ++ long_d1c.resize(N + 1); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(N); ++ short_d1a.resize(N); ++ short_d1b.resize(N); ++ mid_d1a.resize(N); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N); ++ long_d1a.resize(N); ++ long_d1b.resize(N); ++ long_d1c.resize(N); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.resize(20 * N); ++ short_d1a.resize(20 * N); ++ short_d1b.resize(20 * N); ++ mid_d1a.resize(20 * N); ++ mid_d1b.resize(20 * N); ++ mid_d1c.resize(20 * N); ++ long_d1a.resize(20 * N); ++ long_d1b.resize(20 * N); ++ long_d1c.resize(20 * N); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.resize(0); ++ short_d1a.resize(1); ++ short_d1b.resize(2); ++ mid_d1a.resize(N - 1); ++ mid_d1b.resize(N); ++ mid_d1c.resize(N + 1); ++ long_d1a.resize(17 * N - 1); ++ long_d1b.resize(8 * N); ++ long_d1c.resize(11 * N + 1); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ empty_d1.clear(); ++ short_d1a.clear(); ++ short_d1b.clear(); ++ mid_d1a.clear(); ++ mid_d1b.clear(); ++ mid_d1c.clear(); ++ long_d1a.clear(); ++ long_d1b.clear(); ++ long_d1c.clear(); ++ ++ empty_d1.shrink_to_fit(); ++ short_d1a.shrink_to_fit(); ++ short_d1b.shrink_to_fit(); ++ mid_d1a.shrink_to_fit(); ++ mid_d1b.shrink_to_fit(); ++ mid_d1c.shrink_to_fit(); ++ long_d1a.shrink_to_fit(); ++ long_d1b.shrink_to_fit(); ++ long_d1c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1c)); ++ ++ D empty_d2; ++ D short_d2a(1), short_d2b(2); ++ D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); ++ D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); ++ ++ empty_d2.resize(20 * N); ++ short_d2a.resize(20 * N); ++ short_d2b.resize(20 * N); ++ mid_d2a.resize(20 * N); ++ mid_d2b.resize(20 * N); ++ mid_d2c.resize(20 * N); ++ long_d2a.resize(20 * N); ++ long_d2b.resize(20 * N); ++ long_d2c.resize(20 * N); ++ ++ empty_d2.shrink_to_fit(); ++ short_d2a.shrink_to_fit(); ++ short_d2b.shrink_to_fit(); ++ mid_d2a.shrink_to_fit(); ++ mid_d2b.shrink_to_fit(); ++ mid_d2c.shrink_to_fit(); ++ long_d2a.shrink_to_fit(); ++ long_d2b.shrink_to_fit(); ++ long_d2c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++ ++ empty_d2.resize(0); ++ short_d2a.resize(0); ++ short_d2b.resize(0); ++ mid_d2a.resize(0); ++ mid_d2b.resize(0); ++ mid_d2c.resize(0); ++ long_d2a.resize(0); ++ long_d2b.resize(0); ++ long_d2c.resize(0); ++ ++ empty_d2.shrink_to_fit(); ++ short_d2a.shrink_to_fit(); ++ short_d2b.shrink_to_fit(); ++ mid_d2a.shrink_to_fit(); ++ mid_d2b.shrink_to_fit(); ++ mid_d2c.shrink_to_fit(); ++ long_d2a.shrink_to_fit(); ++ long_d2b.shrink_to_fit(); ++ long_d2c.shrink_to_fit(); ++ ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d2)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2b)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d2c)); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp +new file mode 100644 +index 000000000000..83657b546ba2 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp +@@ -0,0 +1,280 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++#include ++#include "test_macros.h" ++#include "asan_testing.h" // includes deque - don't do it before ++ ++template ++void test_external() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ D empty_d1a, empty_d1b; ++ D short_d1a(1), short_d1b; ++ D mid_d1a(N), mid_d1b(N + 1); ++ D long_d1a(8 * N), long_d1b(11 * N + 1); ++ ++ std::swap(empty_d1a, empty_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); ++ std::swap(empty_d1a, empty_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); ++ ++ std::swap(empty_d1a, short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ std::swap(empty_d1a, short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ ++ std::swap(empty_d1a, mid_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ std::swap(empty_d1a, mid_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ ++ std::swap(empty_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(empty_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(empty_d1a, long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ std::swap(empty_d1a, long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ ++ std::swap(empty_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ std::swap(empty_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(short_d1a, short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ std::swap(short_d1a, short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ ++ std::swap(short_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(short_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(short_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ std::swap(short_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(mid_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(mid_d1a, mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(mid_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ std::swap(mid_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(long_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ std::swap(long_d1a, long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(empty_d1a, empty_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ ++ std::swap(short_d1a, short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ std::swap(short_d1b, short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ ++ std::swap(long_d1a, long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++} ++ ++template ++void test_member() { ++ typedef std::deque D; ++ size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; ++ ++ D empty_d1a, empty_d1b; ++ D short_d1a(1), short_d1b; ++ D mid_d1a(N), mid_d1b(N + 1); ++ D long_d1a(8 * N), long_d1b(11 * N + 1); ++ ++ empty_d1a.swap(empty_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); ++ empty_d1a.swap(empty_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1b)); ++ ++ empty_d1a.swap(short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ empty_d1a.swap(short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ ++ empty_d1a.swap(mid_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ empty_d1a.swap(mid_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ ++ empty_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ empty_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ empty_d1a.swap(long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ empty_d1a.swap(long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ ++ empty_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ empty_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ short_d1a.swap(short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ short_d1a.swap(short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ ++ short_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ short_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ short_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ short_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ mid_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ mid_d1a.swap(mid_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1b)); ++ ++ mid_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ mid_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ long_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ long_d1a.swap(long_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1b)); ++ ++ empty_d1a.swap(empty_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(empty_d1a)); ++ ++ short_d1a.swap(short_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1a)); ++ short_d1b.swap(short_d1b); ++ assert(is_double_ended_contiguous_container_asan_correct(short_d1b)); ++ ++ long_d1a.swap(long_d1a); ++ assert(is_double_ended_contiguous_container_asan_correct(long_d1a)); ++} ++ ++template ++void test() { ++ test_external(); ++ test_member(); ++} ++ ++int main(int, char**) { ++ { ++ typedef char T; ++ test(); ++ } ++ { ++ typedef short T; ++ test(); ++ } ++ { ++ typedef int T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array T; ++ test(); ++ } ++ { ++ typedef std::array, 8000> T; ++ test(); ++ } ++ /* ++ // Testing interface does not support situations, ++ // when object memory may be poisoned (SSO case). ++ { ++ typedef std::string T; ++ test(); ++ } ++*/ ++ return 0; ++} +diff --git a/libcxx/test/support/asan_testing.h b/libcxx/test/support/asan_testing.h +index aae93019fe1c..e5a5d25cfe0d 100644 +--- a/libcxx/test/support/asan_testing.h ++++ b/libcxx/test/support/asan_testing.h +@@ -9,6 +9,12 @@ + #ifndef ASAN_TESTING_H + #define ASAN_TESTING_H + ++#ifdef _LIBCPP_DEQUE ++// We need to define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS first ++// prior to including deque, so we error out if its already included ++# error deque included before asan_testing.h ++#endif ++ + #include "test_macros.h" + + #if TEST_HAS_FEATURE(address_sanitizer) +@@ -25,14 +31,35 @@ TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector + TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) + { + return true; + } +-#endif ++#endif // TEST_HAS_FEATURE(address_sanitizer) ++ ++#if TEST_HAS_FEATURE(address_sanitizer) && _LIBCPP_CLANG_VER >= 16000 ++extern "C" int __sanitizer_verify_double_ended_contiguous_container( ++ const void* beg, const void* con_beg, const void* con_end, const void* end); ++extern "C" bool __sanitizer_is_annotable(const void* address, const unsigned long size); ++# define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS ++# include + ++template ++TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque& c) { ++ if (std::__libcpp_is_constant_evaluated()) ++ return true; ++ if (std::is_same >::value && c.data() != NULL) ++ return c.__verify_asan_annotations(); ++ return true; ++} ++#else ++# include ++template ++TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque&) { ++ return true; ++} ++#endif + + #endif // ASAN_TESTING_H