diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -1280,6 +1280,8 @@ class _LIBCPP_TEMPLATE_VIS deque : private __deque_base<_Tp, _Allocator> { +private: + typedef allocator<_Tp> __default_allocator_type; public: // types: @@ -1312,8 +1314,9 @@ _LIBCPP_INLINE_VISIBILITY deque() _NOEXCEPT_(is_nothrow_default_constructible::value) - {} - _LIBCPP_INLINE_VISIBILITY explicit deque(const allocator_type& __a) : __base(__a) {} + { __annotate_new(0); } + _LIBCPP_INLINE_VISIBILITY 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,6 +1326,7 @@ template ::value> > deque(size_type __n, const value_type& __v, const allocator_type& __a) : __base(__a) { + __annotate_new(0); if (__n > 0) __append(__n, __v); } @@ -1529,9 +1533,325 @@ } private: + // 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. +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_INLINE_VISIBILITY + + 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 + // Note that we don't maintain front annotations of a std::deque here + // as this is done in a more specific functions below and this one is only + // used by them. + if (__beg && is_same::value) + __sanitizer_annotate_de_contiguous_container_front(__beg, __end, __new_con_beg, __old_con_beg, __con_end); + + } + 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 + // Note that we don't maintain front annotations of a std::deque here + // as this is done in a more specific functions below and this one is only + // used by them. + if (__beg && is_same::value) + __sanitizer_annotate_de_contiguous_container_back(__beg, __end, __old_con_end, __new_con_end, __con_beg); + + } +#else + _LIBCPP_INLINE_VISIBILITY + void __annotate_contiguous_container_front(const void*, const void*, const void*, + const void*, const void*) const _NOEXCEPT {} + _LIBCPP_INLINE_VISIBILITY + void __annotate_contiguous_container_back(const void*, const void*, const void*, + const void*, const void *) const _NOEXCEPT {} +#endif + + _LIBCPP_INLINE_VISIBILITY + // __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 = _VSTD::__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 block's end + const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); + // Pointer to block's beginning + const void *__p_b = _VSTD::__to_address(*__mp); + __annotate_contiguous_container_front(__p_b, __p_e, __p_e, __p, __p_e); // poison [__p, __p_e] + + __mp += 1; + __p = _VSTD::__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 = _VSTD::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void *__p_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__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) + __annotate_contiguous_container_front(__p_b, __p_t_e, __p_e, __p, __p_e); + else { + // Due to current limitations of ASan, it only matters if container is empty or not, + // therefore we do not calculate true end of the container in the block (performance reasons), + // but if poisoning prefixes will be implemented in Asan, we should pass correct end of memory in use + // inside that chunk, instead of just end of the allocated memory. (Last argument.) + __annotate_contiguous_container_front(__p_b, __p_t_e, __p_e, __p, __p_t_e); + } + } + + _LIBCPP_INLINE_VISIBILITY + 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); + while (__mp != __last_mp) + { + // Pointer to block's end + const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); + // Pointer to block's beginning + const void *__p_b = _VSTD::__to_address(*__mp); + __annotate_contiguous_container_front(__p_b, __p_e, __p, __p_e, __p_e); + + __mp += 1; + __p = _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_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__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_b, __p_e, __p, __p_e, __p_e); + else + { + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + __annotate_contiguous_container_front(__p_b, __p_t_e, __p, __p_e, __p_t_e); + } + } + + _LIBCPP_INLINE_VISIBILITY + 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); + const void *__p_t_b = size() == 0 ? __p : _VSTD::__to_address(*__mp); + + while (__mp != __last_mp) + { + const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); + const void *__p_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_b, __p_t_e, __p_e, __p, __p_t_b); + + __mp += 1; + __p_t_b = __p = _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_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_b, __p_t_e, __p_e, __p, __p_t_b); + } + + _LIBCPP_INLINE_VISIBILITY + 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); + const void *__p_t_b = _VSTD::__to_address(*__mp); + + while (__mp != __last_mp) + { + const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); + const void *__p_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_b, __p_t_e, __p, __p_e, __p_t_b); + + __mp += 1; + __p_t_b = __p = _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_b = _VSTD::__to_address(*__mp); + const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_b, __p_t_e, __p, __p_e, __p_t_b); + } + + _LIBCPP_INLINE_VISIBILITY + 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_INLINE_VISIBILITY + 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_INLINE_VISIBILITY + void __annotate_increase_front(size_type __n) const _NOEXCEPT + { + __annotate_unpoison_from_to_front(__base::__start_ - __n, __base::__start_); + } + + _LIBCPP_INLINE_VISIBILITY + void __annotate_increase_back(size_type __n) const _NOEXCEPT + { + __annotate_unpoison_from_to_back(__base::__start_ + __base::size(), __base::__start_ + __base::size() + __n); + } + + _LIBCPP_INLINE_VISIBILITY + 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_INLINE_VISIBILITY + 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 + 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_de_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_de_contiguous_container(*__it, *__it, *__it, (*__it + __base::__block_size))) return false;} + + 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 (!__sanitizer_verify_de_contiguous_container(*__it, __con_beg, __con_end, (*__it + __base::__block_size))) return false;} + } + } + + return true; + } + private: +#endif + _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(); @@ -1544,6 +1864,7 @@ _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(); @@ -1598,6 +1919,8 @@ 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,6 +1944,7 @@ template deque<_Tp, _Allocator>::deque(size_type __n) { + __annotate_new(0); if (__n > 0) __append(__n); } @@ -1630,6 +1954,7 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) : __base(__a) { + __annotate_new(0); if (__n > 0) __append(__n); } @@ -1638,6 +1963,7 @@ template deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) { + __annotate_new(0); if (__n > 0) __append(__n, __v); } @@ -1647,6 +1973,7 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) { + __annotate_new(0); __append(__f, __l); } @@ -1656,6 +1983,7 @@ typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) : __base(__a) { + __annotate_new(0); __append(__f, __l); } @@ -1663,6 +1991,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c) : __base(__alloc_traits::select_on_container_copy_construction(__c.__alloc())) { + __annotate_new(0); __append(__c.begin(), __c.end()); } @@ -1670,6 +1999,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t& __a) : __base(__a) { + __annotate_new(0); __append(__c.begin(), __c.end()); } @@ -1690,6 +2020,7 @@ template deque<_Tp, _Allocator>::deque(initializer_list __il) { + __annotate_new(0); __append(__il.begin(), __il.end()); } @@ -1697,6 +2028,7 @@ deque<_Tp, _Allocator>::deque(initializer_list __il, const allocator_type& __a) : __base(__a) { + __annotate_new(0); __append(__il.begin(), __il.end()); } @@ -1839,12 +2171,14 @@ allocator_type& __a = __base::__alloc(); if (empty()) { + __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 +2272,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 +2285,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 +2300,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 +2318,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 +2335,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 +2355,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 +2376,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 +2400,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 +2434,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 +2459,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 +2496,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 +2523,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 +2559,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 +2584,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 +2647,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 +2678,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 +2729,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 +2747,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 +2765,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 +2807,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 +2833,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 +2870,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 +2881,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_. @@ -2540,11 +2897,21 @@ { #endif // _LIBCPP_NO_EXCEPTIONS 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(_VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __base::__block_size), + _VSTD::__to_address(__buf.back() + __base::__block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back()) + ); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __base::__block_size); @@ -2596,6 +2963,7 @@ __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 +2987,7 @@ _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 +3024,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); + } // Done allocating, reorder capacity __base::__start_ -= __base::__block_size * __front_capacity; for (; __front_capacity > 0; --__front_capacity) @@ -2682,11 +3055,21 @@ { #endif // _LIBCPP_NO_EXCEPTIONS 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(_VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __base::__block_size), + _VSTD::__to_address(__buf.back() + __base::__block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back()) + ); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __base::__block_size); @@ -2713,12 +3096,15 @@ void deque<_Tp, _Allocator>::pop_front() { + 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(); } @@ -2727,12 +3113,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,6 +3261,8 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) { + 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; @@ -2882,6 +3273,7 @@ __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); --__base::size(); ++__base::__start_; + __annotate_shrink_front(__old_sz, __old_start); __maybe_remove_front_spare(); } else @@ -2889,6 +3281,7 @@ 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,6 +3291,8 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) { + 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; @@ -2912,6 +3307,7 @@ __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()) { } } @@ -2921,6 +3317,7 @@ 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()) { } } @@ -2932,6 +3329,8 @@ void deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) { + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; iterator __e = __base::end(); difference_type __n = __e - __f; if (__n > 0) @@ -2942,6 +3341,7 @@ 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()) { } } @@ -2966,7 +3366,9 @@ void deque<_Tp, _Allocator>::clear() _NOEXCEPT { + __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,428 @@ +//===----------------------------------------------------------------------===// +// +// 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_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d7)); + assert(is_de_contiguous_container_asan_correct(short_d7a)); + assert(is_de_contiguous_container_asan_correct(short_d7b)); + assert(is_de_contiguous_container_asan_correct(mid_d7)); + assert(is_de_contiguous_container_asan_correct(long_d7)); +} +#endif + +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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3)); + assert(is_de_contiguous_container_asan_correct(long_d3)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3)); + assert(is_de_contiguous_container_asan_correct(long_d3)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(short_d4a)); + assert(is_de_contiguous_container_asan_correct(short_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4)); + assert(is_de_contiguous_container_asan_correct(long_d4)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + empty_d1 = mid_d1; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + empty_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + empty_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(long_d1)); + empty_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + + empty_d2 = long_d1; + assert(is_de_contiguous_container_asan_correct(empty_d2)); + + mid_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = mid_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + long_d1 = empty_d1; + assert(is_de_contiguous_container_asan_correct(long_d1)); + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + + empty_d1 = D(); + assert(is_de_contiguous_container_asan_correct(empty_d1)); + mid_d1 = D(); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + long_d1 = D(); + assert(is_de_contiguous_container_asan_correct(long_d1)); + + mid_d1 = mid_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + + // deque& operator=( deque&& other ) + +#if TEST_STD_VER >= 11 + mid_d1 = std::move(mid_d2); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_contiguous_container_asan_correct(mid_d2)); + long_d1 = std::move(long_d2); + assert(is_de_contiguous_container_asan_correct(long_d1)); + assert(is_de_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_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(long_d4a)); + assert(is_de_contiguous_container_asan_correct(long_d4b)); +#endif + + // 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_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6)); + assert(is_de_contiguous_container_asan_correct(long_d6)); +} + +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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3c)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_contiguous_container_asan_correct(long_d3b)); + assert(is_de_contiguous_container_asan_correct(long_d3c)); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(short_d4a)); + assert(is_de_contiguous_container_asan_correct(short_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4a)); + assert(is_de_contiguous_container_asan_correct(mid_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4c)); + assert(is_de_contiguous_container_asan_correct(long_d4a)); + assert(is_de_contiguous_container_asan_correct(long_d4b)); + assert(is_de_contiguous_container_asan_correct(long_d4c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5a)); + assert(is_de_contiguous_container_asan_correct(mid_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5c)); + assert(is_de_contiguous_container_asan_correct(long_d5a)); + assert(is_de_contiguous_container_asan_correct(long_d5b)); + assert(is_de_contiguous_container_asan_correct(long_d5c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6a)); + assert(is_de_contiguous_container_asan_correct(mid_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6c)); + assert(is_de_contiguous_container_asan_correct(long_d6a)); + assert(is_de_contiguous_container_asan_correct(long_d6b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d7)); + assert(is_de_contiguous_container_asan_correct(short_d7a)); + assert(is_de_contiguous_container_asan_correct(short_d7b)); + assert(mid_d7a.size() == 16); + assert(is_de_contiguous_container_asan_correct(mid_d7a)); + assert(mid_d7b.size() == 17); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d8)); + assert(is_de_contiguous_container_asan_correct(short_d8a)); + assert(is_de_contiguous_container_asan_correct(short_d8b)); + assert(mid_d8a.size() == 16); + assert(is_de_contiguous_container_asan_correct(mid_d8a)); + assert(mid_d8b.size() == 17); + assert(is_de_contiguous_container_asan_correct(mid_d8b)); +#endif + + D empty_d9a((std::allocator())), empty_d9b(empty_d8.get_allocator()); + assert(is_de_contiguous_container_asan_correct(empty_d9a)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d10)); + assert(is_de_contiguous_container_asan_correct(short_d10a)); + assert(is_de_contiguous_container_asan_correct(short_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10a)); + assert(is_de_contiguous_container_asan_correct(mid_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10c)); + assert(is_de_contiguous_container_asan_correct(long_d10a)); + assert(is_de_contiguous_container_asan_correct(long_d10b)); + assert(is_de_contiguous_container_asan_correct(long_d10c)); + + assert(is_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3c)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_contiguous_container_asan_correct(long_d3b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d11)); + assert(is_de_contiguous_container_asan_correct(short_d11a)); + assert(is_de_contiguous_container_asan_correct(short_d11b)); + assert(is_de_contiguous_container_asan_correct(mid_d11a)); + assert(is_de_contiguous_container_asan_correct(mid_d11b)); + assert(is_de_contiguous_container_asan_correct(mid_d11c)); + assert(is_de_contiguous_container_asan_correct(long_d11a)); + assert(is_de_contiguous_container_asan_correct(long_d11b)); + assert(is_de_contiguous_container_asan_correct(long_d11c)); + + assert(is_de_contiguous_container_asan_correct(empty_d10)); + assert(is_de_contiguous_container_asan_correct(short_d10a)); + assert(is_de_contiguous_container_asan_correct(short_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10a)); + assert(is_de_contiguous_container_asan_correct(mid_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10c)); + assert(is_de_contiguous_container_asan_correct(long_d10a)); + assert(is_de_contiguous_container_asan_correct(long_d10b)); + assert(is_de_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_de_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_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + while (d3c.size() > 3) { + d3c.erase(d3c.begin() + 2); + assert(is_de_contiguous_container_asan_correct(d3c)); + } + while (d3d.size() > 4) { + d3d.erase(d3d.end() - 3); + assert(is_de_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_de_contiguous_container_asan_correct(d4a)); + } + + while (d4b.size() > 5) { + d4b.erase(d4b.end() - 4, d4b.end() - 2); + assert(is_de_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_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_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_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_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_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_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_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_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_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_back(); + assert(is_de_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_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + d1.pop_front(); + + while (!d1.empty()) { + d1.pop_back(); + assert(is_de_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_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_front(); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + D d2(34 * N + 1); + while (!d2.empty()) { + d2.pop_front(); + assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); + d2.push_back(T()); + assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); + d2.emplace_back(T()); + assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); + d2.push_front(T()); + assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); + d2.emplace_front(T()); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + std::swap(empty_d1a, empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + + std::swap(empty_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + std::swap(empty_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + + std::swap(empty_d1a, mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + std::swap(empty_d1a, mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + + std::swap(empty_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(empty_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(empty_d1a, long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + std::swap(empty_d1a, long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + + std::swap(empty_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(empty_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(short_d1a, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + std::swap(short_d1a, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + std::swap(short_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(short_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(short_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(short_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(mid_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(mid_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(mid_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(mid_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(long_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(long_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(empty_d1a, empty_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + + std::swap(short_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + std::swap(short_d1b, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + std::swap(long_d1a, long_d1a); + assert(is_de_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_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + empty_d1a.swap(empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + + empty_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + empty_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + + empty_d1a.swap(mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + empty_d1a.swap(mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + + empty_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + empty_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + empty_d1a.swap(long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + empty_d1a.swap(long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + + empty_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + empty_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + short_d1a.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + short_d1a.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + short_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + short_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + short_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + short_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + mid_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + mid_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + mid_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + mid_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + long_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + long_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + empty_d1a.swap(empty_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + + short_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + short_d1b.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + long_d1a.swap(long_d1a); + assert(is_de_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,11 +9,23 @@ #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) extern "C" int __sanitizer_verify_contiguous_container ( const void *beg, const void *mid, const void *end ); +extern "C" int +__sanitizer_verify_de_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 +# include template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &c ) @@ -26,13 +38,21 @@ return true; } +template +TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct(const std::deque<_Tp, _Allocator>& c) { + return c.__verify_asan_annotations(); +} #else template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) { return true; } -#endif +template +TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct(const std::deque<_Tp, _Allocator>&) { + return true; +} +#endif #endif // ASAN_TESTING_H diff --git a/upstream-deque-rev-2 b/upstream-deque-rev-2 new file mode 100644 --- /dev/null +++ b/upstream-deque-rev-2 @@ -0,0 +1,4124 @@ +commit 9a8b9041217b32d6a3f952140175b1fbf26b3be4 +Author: Advenam Tacet +Date: Wed Aug 17 21:47:13 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..ab6173a73ba1 100644 +--- a/libcxx/include/deque ++++ b/libcxx/include/deque +@@ -1280,6 +1280,8 @@ template */> + class _LIBCPP_TEMPLATE_VIS deque + : private __deque_base<_Tp, _Allocator> + { ++private: ++ typedef allocator<_Tp> __default_allocator_type; + public: + // types: + +@@ -1312,8 +1314,9 @@ public: + _LIBCPP_INLINE_VISIBILITY + deque() + _NOEXCEPT_(is_nothrow_default_constructible::value) +- {} +- _LIBCPP_INLINE_VISIBILITY explicit deque(const allocator_type& __a) : __base(__a) {} ++ { __annotate_new(0); } ++ _LIBCPP_INLINE_VISIBILITY 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,6 +1326,7 @@ public: + template ::value> > + deque(size_type __n, const value_type& __v, const allocator_type& __a) : __base(__a) + { ++ __annotate_new(0); + if (__n > 0) + __append(__n, __v); + } +@@ -1529,9 +1533,325 @@ public: + } + + private: ++ // 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. ++#ifndef _LIBCPP_HAS_NO_ASAN ++ _LIBCPP_INLINE_VISIBILITY ++ ++ 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 ++ // Note that we don't maintain front annotations of a std::deque here ++ // as this is done in a more specific functions below and this one is only ++ // used by them. ++ if (__beg && is_same::value) ++ __sanitizer_annotate_de_contiguous_container_front(__beg, __end, __new_con_beg, __old_con_beg, __con_end); ++ ++ } ++ 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 ++ // Note that we don't maintain front annotations of a std::deque here ++ // as this is done in a more specific functions below and this one is only ++ // used by them. ++ if (__beg && is_same::value) ++ __sanitizer_annotate_de_contiguous_container_back(__beg, __end, __old_con_end, __new_con_end, __con_beg); ++ ++ } ++#else ++ _LIBCPP_INLINE_VISIBILITY ++ void __annotate_contiguous_container_front(const void*, const void*, const void*, ++ const void*, const void*) const _NOEXCEPT {} ++ _LIBCPP_INLINE_VISIBILITY ++ void __annotate_contiguous_container_back(const void*, const void*, const void*, ++ const void*, const void *) const _NOEXCEPT {} ++#endif ++ ++ _LIBCPP_INLINE_VISIBILITY ++ // __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 = _VSTD::__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 block's end ++ const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ // Pointer to block's beginning ++ const void *__p_b = _VSTD::__to_address(*__mp); ++ __annotate_contiguous_container_front(__p_b, __p_e, __p_e, __p, __p_e); // poison [__p, __p_e] ++ ++ __mp += 1; ++ __p = _VSTD::__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 = _VSTD::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); ++ const void *__p_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__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) ++ __annotate_contiguous_container_front(__p_b, __p_t_e, __p_e, __p, __p_e); ++ else { ++ // Due to current limitations of ASan, it only matters if container is empty or not, ++ // therefore we do not calculate true end of the container in the block (performance reasons), ++ // but if poisoning prefixes will be implemented in Asan, we should pass correct end of memory in use ++ // inside that chunk, instead of just end of the allocated memory. (Last argument.) ++ __annotate_contiguous_container_front(__p_b, __p_t_e, __p_e, __p, __p_t_e); ++ } ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); ++ while (__mp != __last_mp) ++ { ++ // Pointer to block's end ++ const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ // Pointer to block's beginning ++ const void *__p_b = _VSTD::__to_address(*__mp); ++ __annotate_contiguous_container_front(__p_b, __p_e, __p, __p_e, __p_e); ++ ++ __mp += 1; ++ __p = _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_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__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_b, __p_e, __p, __p_e, __p_e); ++ else ++ { ++ // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. ++ __annotate_contiguous_container_front(__p_b, __p_t_e, __p, __p_e, __p_t_e); ++ } ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); ++ const void *__p_t_b = size() == 0 ? __p : _VSTD::__to_address(*__mp); ++ ++ while (__mp != __last_mp) ++ { ++ const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ const void *__p_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_b, __p_t_e, __p_e, __p, __p_t_b); ++ ++ __mp += 1; ++ __p_t_b = __p = _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_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_b, __p_t_e, __p_e, __p, __p_t_b); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ 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 = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); ++ const void *__p_t_b = _VSTD::__to_address(*__mp); ++ ++ while (__mp != __last_mp) ++ { ++ const void *__p_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ const void *__p_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_b, __p_t_e, __p, __p_e, __p_t_b); ++ ++ __mp += 1; ++ __p_t_b = __p = _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_b = _VSTD::__to_address(*__mp); ++ const void *__p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); ++ __annotate_contiguous_container_back(__p_b, __p_t_e, __p, __p_e, __p_t_b); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ 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_INLINE_VISIBILITY ++ 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_INLINE_VISIBILITY ++ void __annotate_increase_front(size_type __n) const _NOEXCEPT ++ { ++ __annotate_unpoison_from_to_front(__base::__start_ - __n, __base::__start_); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ void __annotate_increase_back(size_type __n) const _NOEXCEPT ++ { ++ __annotate_unpoison_from_to_back(__base::__start_ + __base::size(), __base::__start_ + __base::size() + __n); ++ } ++ ++ _LIBCPP_INLINE_VISIBILITY ++ 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_INLINE_VISIBILITY ++ 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 ++ 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_de_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_de_contiguous_container(*__it, *__it, *__it, (*__it + __base::__block_size))) return false;} ++ ++ 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 (!__sanitizer_verify_de_contiguous_container(*__it, __con_beg, __con_end, (*__it + __base::__block_size))) return false;} ++ } ++ } ++ ++ return true; ++ } ++ private: ++#endif ++ + _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(); +@@ -1544,6 +1864,7 @@ public: + _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(); +@@ -1598,6 +1919,8 @@ public: + 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,6 +1944,7 @@ deque(_InputIterator, _InputIterator, _Alloc) + template + deque<_Tp, _Allocator>::deque(size_type __n) + { ++ __annotate_new(0); + if (__n > 0) + __append(__n); + } +@@ -1630,6 +1954,7 @@ template + deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) + : __base(__a) + { ++ __annotate_new(0); + if (__n > 0) + __append(__n); + } +@@ -1638,6 +1963,7 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) + template + deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) + { ++ __annotate_new(0); + if (__n > 0) + __append(__n, __v); + } +@@ -1647,6 +1973,7 @@ template + deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + { ++ __annotate_new(0); + __append(__f, __l); + } + +@@ -1656,6 +1983,7 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, const allocator_ty + typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + : __base(__a) + { ++ __annotate_new(0); + __append(__f, __l); + } + +@@ -1663,6 +1991,7 @@ template + deque<_Tp, _Allocator>::deque(const deque& __c) + : __base(__alloc_traits::select_on_container_copy_construction(__c.__alloc())) + { ++ __annotate_new(0); + __append(__c.begin(), __c.end()); + } + +@@ -1670,6 +1999,7 @@ template + deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t& __a) + : __base(__a) + { ++ __annotate_new(0); + __append(__c.begin(), __c.end()); + } + +@@ -1690,6 +2020,7 @@ deque<_Tp, _Allocator>::operator=(const deque& __c) + template + deque<_Tp, _Allocator>::deque(initializer_list __il) + { ++ __annotate_new(0); + __append(__il.begin(), __il.end()); + } + +@@ -1697,6 +2028,7 @@ template + deque<_Tp, _Allocator>::deque(initializer_list __il, const allocator_type& __a) + : __base(__a) + { ++ __annotate_new(0); + __append(__il.begin(), __il.end()); + } + +@@ -1839,12 +2171,14 @@ deque<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT + allocator_type& __a = __base::__alloc(); + if (empty()) + { ++ __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 +2272,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 +2285,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 +2300,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 +2318,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 +2335,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 +2355,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 +2376,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 +2400,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 +2434,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 +2459,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 +2496,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 +2523,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 +2559,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 +2584,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 +2647,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 +2678,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 +2729,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 +2747,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 +2765,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 +2807,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 +2833,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 +2870,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 +2881,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_. +@@ -2540,11 +2897,21 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) + { + #endif // _LIBCPP_NO_EXCEPTIONS + 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(_VSTD::__to_address(__buf.back()), ++ _VSTD::__to_address(__buf.back() + __base::__block_size), ++ _VSTD::__to_address(__buf.back() + __base::__block_size), ++ _VSTD::__to_address(__buf.back()), ++ _VSTD::__to_address(__buf.back()) ++ ); ++ } + #ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { ++ __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); + __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); +@@ -2596,6 +2963,7 @@ 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 +2987,7 @@ 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 +3024,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); ++ } + // Done allocating, reorder capacity + __base::__start_ -= __base::__block_size * __front_capacity; + for (; __front_capacity > 0; --__front_capacity) +@@ -2682,11 +3055,21 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) + { + #endif // _LIBCPP_NO_EXCEPTIONS + 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(_VSTD::__to_address(__buf.back()), ++ _VSTD::__to_address(__buf.back() + __base::__block_size), ++ _VSTD::__to_address(__buf.back() + __base::__block_size), ++ _VSTD::__to_address(__buf.back()), ++ _VSTD::__to_address(__buf.back()) ++ ); ++ } + #ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { ++ __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); + __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); +@@ -2713,12 +3096,15 @@ template + void + deque<_Tp, _Allocator>::pop_front() + { ++ 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(); + } + +@@ -2727,12 +3113,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,6 +3261,8 @@ template + typename deque<_Tp, _Allocator>::iterator + deque<_Tp, _Allocator>::erase(const_iterator __f) + { ++ 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; +@@ -2882,6 +3273,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f) + __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); + --__base::size(); + ++__base::__start_; ++ __annotate_shrink_front(__old_sz, __old_start); + __maybe_remove_front_spare(); + } + else +@@ -2889,6 +3281,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f) + 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,6 +3291,8 @@ template + typename deque<_Tp, _Allocator>::iterator + deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) + { ++ 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; +@@ -2912,6 +3307,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) + __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()) { + } + } +@@ -2921,6 +3317,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) + 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()) { + } + } +@@ -2932,6 +3329,8 @@ template + void + deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) + { ++ size_type __old_sz = __base::size(); ++ size_type __old_start = __base::__start_; + iterator __e = __base::end(); + difference_type __n = __e - __f; + if (__n > 0) +@@ -2942,6 +3341,7 @@ deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) + 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()) { + } + } +@@ -2966,7 +3366,9 @@ inline + void + deque<_Tp, _Allocator>::clear() _NOEXCEPT + { ++ __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..30d23d512535 +--- /dev/null ++++ b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp +@@ -0,0 +1,428 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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_de_contiguous_container_asan_correct(empty_d5)); ++ assert(is_de_contiguous_container_asan_correct(short_d5a)); ++ assert(is_de_contiguous_container_asan_correct(short_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); ++ assert(is_de_contiguous_container_asan_correct(short_d5a)); ++ assert(is_de_contiguous_container_asan_correct(short_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); ++ assert(is_de_contiguous_container_asan_correct(short_d6a)); ++ assert(is_de_contiguous_container_asan_correct(short_d6b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d6)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d7)); ++ assert(is_de_contiguous_container_asan_correct(short_d7a)); ++ assert(is_de_contiguous_container_asan_correct(short_d7b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d7)); ++ assert(is_de_contiguous_container_asan_correct(long_d7)); ++} ++#endif ++ ++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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); ++ assert(is_de_contiguous_container_asan_correct(short_d3a)); ++ assert(is_de_contiguous_container_asan_correct(short_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3)); ++ assert(is_de_contiguous_container_asan_correct(long_d3)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); ++ assert(is_de_contiguous_container_asan_correct(short_d3a)); ++ assert(is_de_contiguous_container_asan_correct(short_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3)); ++ assert(is_de_contiguous_container_asan_correct(long_d3)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d4)); ++ assert(is_de_contiguous_container_asan_correct(short_d4a)); ++ assert(is_de_contiguous_container_asan_correct(short_d4b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d4)); ++ assert(is_de_contiguous_container_asan_correct(long_d4)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(empty_d2)); ++ empty_d1 = mid_d1; ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ empty_d1 = empty_d2; ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(empty_d2)); ++ empty_d1 = long_d1; ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ empty_d1 = empty_d2; ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(empty_d2)); ++ ++ empty_d2 = long_d1; ++ assert(is_de_contiguous_container_asan_correct(empty_d2)); ++ ++ mid_d1 = long_d1; ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = empty_d2; ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = long_d1; ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ mid_d1 = mid_d2; ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ ++ long_d1 = long_d2; ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ long_d1 = empty_d1; ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ long_d1 = long_d2; ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ ++ empty_d1 = D(); ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ mid_d1 = D(); ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ long_d1 = D(); ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ ++ mid_d1 = mid_d2; ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ long_d1 = long_d2; ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ ++ // deque& operator=( deque&& other ) ++ ++#if TEST_STD_VER >= 11 ++ mid_d1 = std::move(mid_d2); ++ assert(is_de_contiguous_container_asan_correct(mid_d1)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2)); ++ long_d1 = std::move(long_d2); ++ assert(is_de_contiguous_container_asan_correct(long_d1)); ++ assert(is_de_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_de_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_de_contiguous_container_asan_correct(long_d3a)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(empty_d4)); ++ assert(is_de_contiguous_container_asan_correct(long_d4a)); ++ assert(is_de_contiguous_container_asan_correct(long_d4b)); ++#endif ++ ++ // 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_de_contiguous_container_asan_correct(empty_d5)); ++ assert(is_de_contiguous_container_asan_correct(short_d5a)); ++ assert(is_de_contiguous_container_asan_correct(short_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); ++ assert(is_de_contiguous_container_asan_correct(short_d5a)); ++ assert(is_de_contiguous_container_asan_correct(short_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); ++ assert(is_de_contiguous_container_asan_correct(short_d6a)); ++ assert(is_de_contiguous_container_asan_correct(short_d6b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d6)); ++ assert(is_de_contiguous_container_asan_correct(long_d6)); ++} ++ ++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..b7a4a87ddfb2 +--- /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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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..acf560dc96bd +--- /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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_contiguous_container_asan_correct(long_d2c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d3)); ++ assert(is_de_contiguous_container_asan_correct(short_d3a)); ++ assert(is_de_contiguous_container_asan_correct(short_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3c)); ++ assert(is_de_contiguous_container_asan_correct(long_d3a)); ++ assert(is_de_contiguous_container_asan_correct(long_d3b)); ++ assert(is_de_contiguous_container_asan_correct(long_d3c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d4)); ++ assert(is_de_contiguous_container_asan_correct(short_d4a)); ++ assert(is_de_contiguous_container_asan_correct(short_d4b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d4a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d4b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d4c)); ++ assert(is_de_contiguous_container_asan_correct(long_d4a)); ++ assert(is_de_contiguous_container_asan_correct(long_d4b)); ++ assert(is_de_contiguous_container_asan_correct(long_d4c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d5)); ++ assert(is_de_contiguous_container_asan_correct(short_d5a)); ++ assert(is_de_contiguous_container_asan_correct(short_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d5c)); ++ assert(is_de_contiguous_container_asan_correct(long_d5a)); ++ assert(is_de_contiguous_container_asan_correct(long_d5b)); ++ assert(is_de_contiguous_container_asan_correct(long_d5c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d6)); ++ assert(is_de_contiguous_container_asan_correct(short_d6a)); ++ assert(is_de_contiguous_container_asan_correct(short_d6b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d6a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d6b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d6c)); ++ assert(is_de_contiguous_container_asan_correct(long_d6a)); ++ assert(is_de_contiguous_container_asan_correct(long_d6b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d7)); ++ assert(is_de_contiguous_container_asan_correct(short_d7a)); ++ assert(is_de_contiguous_container_asan_correct(short_d7b)); ++ assert(mid_d7a.size() == 16); ++ assert(is_de_contiguous_container_asan_correct(mid_d7a)); ++ assert(mid_d7b.size() == 17); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d8)); ++ assert(is_de_contiguous_container_asan_correct(short_d8a)); ++ assert(is_de_contiguous_container_asan_correct(short_d8b)); ++ assert(mid_d8a.size() == 16); ++ assert(is_de_contiguous_container_asan_correct(mid_d8a)); ++ assert(mid_d8b.size() == 17); ++ assert(is_de_contiguous_container_asan_correct(mid_d8b)); ++#endif ++ ++ D empty_d9a((std::allocator())), empty_d9b(empty_d8.get_allocator()); ++ assert(is_de_contiguous_container_asan_correct(empty_d9a)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d10)); ++ assert(is_de_contiguous_container_asan_correct(short_d10a)); ++ assert(is_de_contiguous_container_asan_correct(short_d10b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10c)); ++ assert(is_de_contiguous_container_asan_correct(long_d10a)); ++ assert(is_de_contiguous_container_asan_correct(long_d10b)); ++ assert(is_de_contiguous_container_asan_correct(long_d10c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d3)); ++ assert(is_de_contiguous_container_asan_correct(short_d3a)); ++ assert(is_de_contiguous_container_asan_correct(short_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d3c)); ++ assert(is_de_contiguous_container_asan_correct(long_d3a)); ++ assert(is_de_contiguous_container_asan_correct(long_d3b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d11)); ++ assert(is_de_contiguous_container_asan_correct(short_d11a)); ++ assert(is_de_contiguous_container_asan_correct(short_d11b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d11a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d11b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d11c)); ++ assert(is_de_contiguous_container_asan_correct(long_d11a)); ++ assert(is_de_contiguous_container_asan_correct(long_d11b)); ++ assert(is_de_contiguous_container_asan_correct(long_d11c)); ++ ++ assert(is_de_contiguous_container_asan_correct(empty_d10)); ++ assert(is_de_contiguous_container_asan_correct(short_d10a)); ++ assert(is_de_contiguous_container_asan_correct(short_d10b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d10c)); ++ assert(is_de_contiguous_container_asan_correct(long_d10a)); ++ assert(is_de_contiguous_container_asan_correct(long_d10b)); ++ assert(is_de_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..4fcaea0194da +--- /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_de_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..56b2d19f19b3 +--- /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_de_contiguous_container_asan_correct(d1a)); ++ assert(is_de_contiguous_container_asan_correct(d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_contiguous_container_asan_correct(d2d)); ++ ++ d2c.erase(d2c.begin() + 2); ++ d2d.erase(d2d.end() - 3); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_contiguous_container_asan_correct(d2d)); ++ ++ d2c.erase(d2c.begin() + 2); ++ d2d.erase(d2d.end() - 3); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d3a)); ++ assert(is_de_contiguous_container_asan_correct(d3b)); ++ while (d3c.size() > 3) { ++ d3c.erase(d3c.begin() + 2); ++ assert(is_de_contiguous_container_asan_correct(d3c)); ++ } ++ while (d3d.size() > 4) { ++ d3d.erase(d3d.end() - 3); ++ assert(is_de_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_de_contiguous_container_asan_correct(d4a)); ++ } ++ ++ while (d4b.size() > 5) { ++ d4b.erase(d4b.end() - 4, d4b.end() - 2); ++ assert(is_de_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..d3c5667271c2 +--- /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_de_contiguous_container_asan_correct(d1a)); ++ assert(is_de_contiguous_container_asan_correct(d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d3a)); ++ assert(is_de_contiguous_container_asan_correct(d3b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d3a)); ++ assert(is_de_contiguous_container_asan_correct(d3b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d3a)); ++ assert(is_de_contiguous_container_asan_correct(d3b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d1a)); ++ assert(is_de_contiguous_container_asan_correct(d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_contiguous_container_asan_correct(d2d)); ++ ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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_de_contiguous_container_asan_correct(d2a)); ++ assert(is_de_contiguous_container_asan_correct(d2b)); ++ assert(is_de_contiguous_container_asan_correct(d2c)); ++ assert(is_de_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..7257750bee33 +--- /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_de_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ while (!d1.empty()) { ++ d1.pop_back(); ++ assert(is_de_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_de_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ d1.pop_front(); ++ ++ while (!d1.empty()) { ++ d1.pop_back(); ++ assert(is_de_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..a87e90b48a5f +--- /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_de_contiguous_container_asan_correct(single_d)); ++ ++ D d1(34 * N); ++ while (!d1.empty()) { ++ d1.pop_front(); ++ assert(is_de_contiguous_container_asan_correct(d1)); ++ } ++ ++ D d2(34 * N + 1); ++ while (!d2.empty()) { ++ d2.pop_front(); ++ assert(is_de_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..bda9a4fbcd1b +--- /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_de_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_de_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_de_contiguous_container_asan_correct(d2)); ++ d2.push_back(T()); ++ assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); ++ d2.emplace_back(T()); ++ assert(is_de_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..22bab2fa4cb7 +--- /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_de_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_de_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_de_contiguous_container_asan_correct(d2)); ++ d2.push_front(T()); ++ assert(is_de_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_de_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_de_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_de_contiguous_container_asan_correct(d2)); ++ d2.emplace_front(T()); ++ assert(is_de_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..9e3c8d6f3fa5 +--- /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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_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..5398c382c82c +--- /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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1c)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d2)); ++ assert(is_de_contiguous_container_asan_correct(short_d2a)); ++ assert(is_de_contiguous_container_asan_correct(short_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2b)); ++ assert(is_de_contiguous_container_asan_correct(mid_d2c)); ++ assert(is_de_contiguous_container_asan_correct(long_d2a)); ++ assert(is_de_contiguous_container_asan_correct(long_d2b)); ++ assert(is_de_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..2263121cdc72 +--- /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_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(empty_d1b)); ++ std::swap(empty_d1a, empty_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(empty_d1b)); ++ ++ std::swap(empty_d1a, short_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ std::swap(empty_d1a, short_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ ++ std::swap(empty_d1a, mid_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ std::swap(empty_d1a, mid_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ ++ std::swap(empty_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(empty_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(empty_d1a, long_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ std::swap(empty_d1a, long_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ ++ std::swap(empty_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ std::swap(empty_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(short_d1a, short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ std::swap(short_d1a, short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ ++ std::swap(short_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(short_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(short_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ std::swap(short_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(mid_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ std::swap(mid_d1a, mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ std::swap(mid_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ std::swap(mid_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(long_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ std::swap(long_d1a, long_d1b); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ std::swap(empty_d1a, empty_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ ++ std::swap(short_d1a, short_d1a); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ std::swap(short_d1b, short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ ++ std::swap(long_d1a, long_d1a); ++ assert(is_de_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_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(empty_d1b)); ++ empty_d1a.swap(empty_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(empty_d1b)); ++ ++ empty_d1a.swap(short_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ empty_d1a.swap(short_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ ++ empty_d1a.swap(mid_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ empty_d1a.swap(mid_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ ++ empty_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ empty_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ empty_d1a.swap(long_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ empty_d1a.swap(long_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ ++ empty_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ empty_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ short_d1a.swap(short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ short_d1a.swap(short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ ++ short_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ short_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ short_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ short_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ mid_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ mid_d1a.swap(mid_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(mid_d1b)); ++ ++ mid_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ mid_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(mid_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ long_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ long_d1a.swap(long_d1b); ++ assert(is_de_contiguous_container_asan_correct(long_d1a)); ++ assert(is_de_contiguous_container_asan_correct(long_d1b)); ++ ++ empty_d1a.swap(empty_d1a); ++ assert(is_de_contiguous_container_asan_correct(empty_d1a)); ++ ++ short_d1a.swap(short_d1a); ++ assert(is_de_contiguous_container_asan_correct(short_d1a)); ++ short_d1b.swap(short_d1b); ++ assert(is_de_contiguous_container_asan_correct(short_d1b)); ++ ++ long_d1a.swap(long_d1a); ++ assert(is_de_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..f9663cdc1cbb 100644 +--- a/libcxx/test/support/asan_testing.h ++++ b/libcxx/test/support/asan_testing.h +@@ -9,11 +9,23 @@ + #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) + extern "C" int __sanitizer_verify_contiguous_container + ( const void *beg, const void *mid, const void *end ); ++extern "C" int ++__sanitizer_verify_de_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 ++#include + + template + TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &c ) +@@ -26,13 +38,21 @@ TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector ++TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct ( const std::deque<_Tp, _Allocator>& c) { ++ return c.__verify_asan_annotations(); ++} + #else + template + TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) + { + return true; + } +-#endif + ++template ++TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct ( const std::deque<_Tp, _Allocator> &) { ++ return true; ++} ++#endif + + #endif // ASAN_TESTING_H