diff --git a/libcxx/include/__config b/libcxx/include/__config
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -902,6 +902,12 @@
 #  ifndef _LIBCPP_HAS_NO_ASAN
     extern "C" _LIBCPP_FUNC_VIS void
     __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*);
+#    if _LIBCPP_CLANG_VER >= 1600
+extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_double_ended_contiguous_container(
+    const void*, const void*, const void*, const void*, const void*, const void*);
+extern "C" _LIBCPP_FUNC_VIS int
+__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*);
+#    endif
 #  endif
 
 // Try to find out if RTTI is disabled.
diff --git a/libcxx/include/deque b/libcxx/include/deque
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -457,6 +457,9 @@
 template <class _Tp, class _Allocator /*= allocator<_Tp>*/>
 class _LIBCPP_TEMPLATE_VIS deque
 {
+private:
+  using __default_allocator_type = allocator<_Tp>;
+
 public:
     // types:
 
@@ -480,6 +483,7 @@
   using __map_alloc_traits        = allocator_traits<__pointer_allocator>;
   using __map_pointer             = typename __map_alloc_traits::pointer;
   using __map_const_pointer       = typename allocator_traits<__const_pointer_allocator>::const_pointer;
+  using __map_const_iterator      = typename __map::const_iterator;
 
   using reference       = value_type&;
   using const_reference = const value_type&;
@@ -579,10 +583,13 @@
     // construct/copy/destroy:
     _LIBCPP_HIDE_FROM_ABI
     deque() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
-        : __start_(0), __size_(0, __default_init_tag()) {}
+        : __start_(0), __size_(0, __default_init_tag()) {
+      __annotate_new(0);
+    }
 
     _LIBCPP_HIDE_FROM_ABI ~deque() {
       clear();
+      __annotate_delete();
       typename __map::iterator __i = __map_.begin();
       typename __map::iterator __e = __map_.end();
       for (; __i != __e; ++__i)
@@ -590,7 +597,9 @@
     }
 
     _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a)
-        : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {}
+        : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {
+      __annotate_new(0);
+    }
 
     explicit _LIBCPP_HIDE_FROM_ABI deque(size_type __n);
 #if _LIBCPP_STD_VER >= 14
@@ -602,6 +611,7 @@
     _LIBCPP_HIDE_FROM_ABI deque(size_type __n, const value_type& __v, const allocator_type& __a)
         : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a)
     {
+        __annotate_new(0);
         if (__n > 0)
             __append(__n, __v);
     }
@@ -862,7 +872,7 @@
             return false;
         if (__map_.size() >= size_type(-1) / __block_size)
             return false;
-        for (typename __map::const_iterator __i = __map_.begin(), __e = __map_.end();
+        for (__map_const_iterator __i = __map_.begin(), __e = __map_.end();
             __i != __e; ++__i)
             if (*__i == nullptr)
                 return false;
@@ -949,9 +959,259 @@
     }
 
  private:
+   enum __asan_annotation_type {
+     __asan_unposion,
+     __asan_poison
+   };
+
+   enum __asan_annotation_place {
+     __asan_front_moved,
+     __asan_back_moved,
+   };
+
+// The following functions are no-ops outside of AddressSanitizer mode.
+// We call annotations only for the default Allocator.
+#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600
+    // TODO LLVM18: Remove the special-casing
+    _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
+        const void* __beg,
+        const void* __end,
+        const void* __old_con_beg,
+        const void* __old_con_end,
+        const void* __new_con_beg,
+        const void* __new_con_end) const {
+        if (__beg && is_same<allocator_type, __default_allocator_type>::value)
+            __sanitizer_annotate_double_ended_contiguous_container(
+                __beg, __end, __old_con_beg, __old_con_end, __new_con_beg, __new_con_end);
+    }
+#else
+    _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
+        const void*, const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {}
+#endif // !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_from_to(size_type __beg, size_type __end, __asan_annotation_type __annotation_type, __asan_annotation_place __place) const _NOEXCEPT {
+        // __beg - index of the first item to annotate
+        // __end - index behind the last item to annotate (so last item + 1)
+        // __annotation_type - __asan_unposion or __asan_poison
+        // __place - __asan_front_moved or __asan_back_moved
+        // Note: All indexes in __map_
+        if (__beg == __end)
+            return;
+        // __annotations_beg_map - first chunk which annotations we want to modify
+        // __annotations_end_map - last chunk which annotations we want to modify
+        // NOTE: if __end % __block_size == 0, __annotations_end_map points at the next block, which may not exist
+        __map_const_iterator __annotations_beg_map = __map_.begin() + __beg / __block_size;
+        __map_const_iterator __annotations_end_map = __map_.begin() + __end / __block_size;
+
+        bool const __poisoning = __annotation_type == __asan_poison;
+        // __old_c_beg_index - index of the first element in old container
+        // __old_c_end_index - index of the end of old container (last + 1)
+        // Note: may be outside the area we are annotating
+        size_t __old_c_beg_index = (__poisoning && __place == __asan_front_moved) ? __beg : __start_;
+        size_t __old_c_end_index = (__poisoning && __place == __asan_back_moved)  ? __end : __start_ + size();
+        bool const __front = __place == __asan_front_moved;
+
+        if (__poisoning && empty()) {
+            // Special case: we shouldn't trust __start_
+            __old_c_beg_index = __beg;
+            __old_c_end_index = __end;
+        }
+        // __old_c_beg_map - memory block (chunk) with first element
+        // __old_c_end_map - memory block (chunk) with end of old container
+        // Note: if __old_c_end_index % __block_size == 0, __old_c_end_map points at the next block,
+        // which may not exist
+        __map_const_iterator __old_c_beg_map = __map_.begin() + __old_c_beg_index / __block_size;
+        __map_const_iterator __old_c_end_map = __map_.begin() + __old_c_end_index / __block_size;
+
+        // One edge (front/end) of the container was moved and one was not modified.
+        // __new_edge_index - index of new edge
+        // __new_edge_map    - memory block (chunk) with new edge, it always equals to
+        //                    __annotations_beg_map or __annotations_end_map
+        // __old_edge_map    - memory block (chunk) with old edge, it always equals to
+        //                    __old_c_beg_map or __old_c_end_map
+        size_t __new_edge_index                      = (__poisoning ^ __front) ? __beg : __end;
+        __map_const_iterator __new_edge_map = __map_.begin() + __new_edge_index / __block_size;
+        __map_const_iterator __old_edge_map = __front ? __old_c_end_map : __old_c_beg_map;
+
+        // We iterate over map pointers (chunks) and fully poison all memory blocks between the first and the last.
+        // First and last chunk may be partially poisoned.
+        // __annotate_end_map may point at not existing chunk, therefore we have to have a check for it.
+        for (__map_const_iterator __map_it = __annotations_beg_map; __map_it <= __annotations_end_map; ++__map_it) {
+            if (__map_it == __annotations_end_map && __end % __block_size == 0)
+                // Chunk may not exist, but nothing to do here anyway
+                break;
+
+            // The beginning and the end of the current memory block
+            const void* __mem_beg = std::__to_address(*__map_it);
+            const void* __mem_end = std::__to_address(*__map_it + __block_size);
+
+            // The beginning of memory-in-use in the memory block before container modification
+            const void* __old_beg =
+                (__map_it == __old_c_beg_map) ? std::__to_address(*__map_it + (__old_c_beg_index % __block_size)) : __mem_beg;
+
+            // The end of memory-in-use in the memory block before container modification
+            const void* __old_end;
+            if (__map_it < __old_c_beg_map || __map_it > __old_c_end_map || (!__poisoning && empty()))
+                __old_end = __old_beg;
+            else
+                __old_end = (__map_it == __old_c_end_map) ? std::__to_address(*__map_it + (__old_c_end_index % __block_size))
+                                                   : __mem_end;
+
+            // New edge of the container in current memory block
+            // If the edge is in a different chunk it points on corresponding end of the memory block
+            const void* __new_edge;
+            if (__map_it == __new_edge_map)
+                __new_edge = std::__to_address(*__map_it + (__new_edge_index % __block_size));
+            else
+                __new_edge = (__poisoning ^ __front) ? __mem_beg : __mem_end;
+
+            // Not modified edge of the container
+            // If the edge is in a different chunk it points on corresponding end of the memory block
+            const void* __old_edge;
+            if (__map_it == __old_edge_map)
+                __old_edge = __front ? __old_end : __old_beg;
+            else
+                __old_edge = __front ? __mem_end : __mem_beg;
+
+            // __new_beg - the beginning of memory-in-use in the memory block after container modification
+            // __new_end - the end of memory-in-use in the memory block after container modification
+            const void* __new_beg = __front ? __new_edge : __old_edge;
+            const void* __new_end = __front ? __old_edge : __new_edge;
+
+            __annotate_double_ended_contiguous_container(__mem_beg, __mem_end, __old_beg, __old_end, __new_beg, __new_end);
+        }
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_new(size_type __current_size) const _NOEXCEPT {
+        if (__current_size == 0)
+            __annotate_from_to(0, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
+        else {
+            __annotate_from_to(0, __start_, __asan_poison, __asan_front_moved);
+            __annotate_from_to(__start_ + __current_size, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
+        }
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_delete() const _NOEXCEPT {
+        if (empty()) {
+            for(size_t i = 0; i < __map_.size(); ++i) {
+                __annotate_whole_block(i, __asan_unposion);
+            }
+        }
+        else {
+            __annotate_from_to(0, __start_, __asan_unposion, __asan_front_moved);
+            __annotate_from_to(__start_ + size(), __map_.size() * __block_size, __asan_unposion, __asan_back_moved);
+        }
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_increase_front(size_type __n) const _NOEXCEPT {
+        __annotate_from_to(__start_ - __n, __start_, __asan_unposion, __asan_front_moved);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_increase_back(size_type __n) const _NOEXCEPT {
+        __annotate_from_to(__start_ + size(), __start_ + size() + __n, __asan_unposion, __asan_back_moved);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT {
+        __annotate_from_to(__old_start, __old_start + (__old_size - size()), __asan_poison, __asan_front_moved);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT {
+        __annotate_from_to(__old_start + size(), __old_start + __old_size, __asan_poison, __asan_back_moved);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_poison_block(const void *__beginning, const void *__end) const _NOEXCEPT {
+        __annotate_double_ended_contiguous_container(__beginning, __end, __beginning, __end, __end, __end);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI
+    void __annotate_whole_block(size_t __block_index, __asan_annotation_type __annotation_type) const _NOEXCEPT {
+        __map_const_iterator __block_it = __map_.begin() + __block_index;
+        const void* __block_start = std::__to_address(*__block_it);
+        const void* __block_end = std::__to_address(*__block_it + __block_size);
+
+        if(__annotation_type == __asan_poison)
+            __annotate_poison_block(__block_start, __block_end);
+        else {
+            __annotate_double_ended_contiguous_container(
+                __block_start, __block_end, __block_start, __block_start, __block_start, __block_end);
+        }
+    }
+#if !defined(_LIBCPP_HAS_NO_ASAN)
+
+  public:
+    _LIBCPP_HIDE_FROM_ABI
+    bool __verify_asan_annotations() const _NOEXCEPT {
+        // This function tests deque object annotations.
+        if (empty()) {
+            for (__map_const_iterator __it = __map_.begin(); __it != __map_.end(); ++__it) {
+                if (!__sanitizer_verify_double_ended_contiguous_container(
+                        std::__to_address(*__it),
+                        std::__to_address(*__it),
+                        std::__to_address(*__it),
+                        std::__to_address(*__it + __block_size)))
+                  return false;
+            }
+
+            return true;
+        }
+
+        size_type __end                           = __start_ + size();
+        __map_const_iterator __first_mp = __map_.begin() + __start_ / __block_size;
+        __map_const_iterator __last_mp  = __map_.begin() + (__end - 1) / __block_size;
+
+        // Pointers to first and after last elements
+        // Those can be in different deque blocks
+        const void* __p_beg = std::__to_address(*__first_mp + (__start_ % __block_size));
+        const void* __p_end =
+            std::__to_address(*__last_mp + ((__end % __block_size == 0) ? __block_size : __end % __block_size));
+
+        for (__map_const_iterator __it = __map_.begin(); __it != __map_.end(); ++__it) {
+            // Go over all blocks, find the place we are in and verify its annotations
+            // Note that __p_end points *behind* the last item.
+
+            // - blocks before the first block with container elements
+            // - first block with items
+            // - last block with items
+            // - blocks after last block with ciontainer elements
+
+            // Is the block before or after deque blocks that contain elements?
+            if (__it < __first_mp || __it > __last_mp) {
+                if (!__sanitizer_verify_double_ended_contiguous_container(
+                        std::__to_address(*__it),
+                        std::__to_address(*__it),
+                        std::__to_address(*__it),
+                        std::__to_address(*__it + __block_size)))
+                  return false;
+            } else {
+                const void* __containers_buffer_beg = (__it == __first_mp) ? __p_beg : (const void*)std::__to_address(*__it);
+                const void* __containers_buffer_end =
+                    (__it == __last_mp) ? __p_end : (const void*)std::__to_address(*__it + __block_size);
+                if (!__sanitizer_verify_double_ended_contiguous_container(
+                        std::__to_address(*__it),
+                        __containers_buffer_beg,
+                        __containers_buffer_end,
+                        std::__to_address(*__it + __block_size))) {
+                  return false;
+                }
+            }
+        }
+        return true;
+    }
+
+  private:
+#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS
     _LIBCPP_HIDE_FROM_ABI
     bool __maybe_remove_front_spare(bool __keep_one = true) {
       if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) {
+        __annotate_whole_block(0, __asan_unposion);
         __alloc_traits::deallocate(__alloc(), __map_.front(),
                                    __block_size);
         __map_.pop_front();
@@ -964,6 +1224,7 @@
     _LIBCPP_HIDE_FROM_ABI
     bool __maybe_remove_back_spare(bool __keep_one = true) {
       if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) {
+        __annotate_whole_block(__map_.size() - 1, __asan_unposion);
         __alloc_traits::deallocate(__alloc(), __map_.back(),
                                    __block_size);
         __map_.pop_back();
@@ -1087,6 +1348,7 @@
 deque<_Tp, _Allocator>::deque(size_type __n)
     : __start_(0), __size_(0, __default_init_tag())
 {
+    __annotate_new(0);
     if (__n > 0)
         __append(__n);
 }
@@ -1096,6 +1358,7 @@
 deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a)
     : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a)
 {
+    __annotate_new(0);
     if (__n > 0)
         __append(__n);
 }
@@ -1105,6 +1368,7 @@
 deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v)
     : __start_(0), __size_(0, __default_init_tag())
 {
+    __annotate_new(0);
     if (__n > 0)
         __append(__n, __v);
 }
@@ -1115,6 +1379,7 @@
               typename enable_if<__has_input_iterator_category<_InputIter>::value>::type*)
     : __start_(0), __size_(0, __default_init_tag())
 {
+    __annotate_new(0);
     __append(__f, __l);
 }
 
@@ -1124,6 +1389,7 @@
               typename enable_if<__has_input_iterator_category<_InputIter>::value>::type*)
     : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a)
 {
+    __annotate_new(0);
     __append(__f, __l);
 }
 
@@ -1133,6 +1399,7 @@
       __start_(0),
       __size_(0, __map_.__alloc())
 {
+    __annotate_new(0);
     __append(__c.begin(), __c.end());
 }
 
@@ -1140,6 +1407,7 @@
 deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t<allocator_type>& __a)
     : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a)
 {
+    __annotate_new(0);
     __append(__c.begin(), __c.end());
 }
 
@@ -1161,6 +1429,7 @@
 deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il)
     : __start_(0), __size_(0, __default_init_tag())
 {
+    __annotate_new(0);
     __append(__il.begin(), __il.end());
 }
 
@@ -1168,6 +1437,7 @@
 deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il, const allocator_type& __a)
     : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a)
 {
+    __annotate_new(0);
     __append(__il.begin(), __il.end());
 }
 
@@ -1355,6 +1625,7 @@
     allocator_type& __a = __alloc();
     if (empty())
     {
+        __annotate_delete();
         while (__map_.size() > 0)
         {
             __alloc_traits::deallocate(__a, __map_.back(), __block_size);
@@ -1454,6 +1725,7 @@
     if (__back_spare() == 0)
         __add_back_capacity();
     // __back_spare() >= 1
+    __annotate_increase_back(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*end()), __v);
     ++__size();
 }
@@ -1466,6 +1738,7 @@
     if (__front_spare() == 0)
         __add_front_capacity();
     // __front_spare() >= 1
+    __annotate_increase_front(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v);
     --__start_;
     ++__size();
@@ -1480,6 +1753,7 @@
     if (__back_spare() == 0)
         __add_back_capacity();
     // __back_spare() >= 1
+    __annotate_increase_back(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*end()), _VSTD::move(__v));
     ++__size();
 }
@@ -1497,6 +1771,7 @@
     if (__back_spare() == 0)
         __add_back_capacity();
     // __back_spare() >= 1
+    __annotate_increase_back(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*end()),
                               _VSTD::forward<_Args>(__args)...);
     ++__size();
@@ -1513,6 +1788,7 @@
     if (__front_spare() == 0)
         __add_front_capacity();
     // __front_spare() >= 1
+    __annotate_increase_front(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v));
     --__start_;
     ++__size();
@@ -1532,6 +1808,7 @@
     if (__front_spare() == 0)
         __add_front_capacity();
     // __front_spare() >= 1
+    __annotate_increase_front(1);
     __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...);
     --__start_;
     ++__size();
@@ -1552,6 +1829,7 @@
         if (__front_spare() == 0)
             __add_front_capacity();
         // __front_spare() >= 1
+        __annotate_increase_front(1);
         if (__pos == 0)
         {
             __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v));
@@ -1575,6 +1853,7 @@
         if (__back_spare() == 0)
             __add_back_capacity();
         // __back_capacity >= 1
+        __annotate_increase_back(1);
         size_type __de = size() - __pos;
         if (__de == 0)
         {
@@ -1608,6 +1887,7 @@
         if (__front_spare() == 0)
             __add_front_capacity();
         // __front_spare() >= 1
+        __annotate_increase_front(1);
         if (__pos == 0)
         {
             __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...);
@@ -1632,6 +1912,7 @@
         if (__back_spare() == 0)
             __add_back_capacity();
         // __back_capacity >= 1
+        __annotate_increase_back(1);
         size_type __de = size() - __pos;
         if (__de == 0)
         {
@@ -1668,6 +1949,7 @@
         if (__front_spare() == 0)
             __add_front_capacity();
         // __front_spare() >= 1
+        __annotate_increase_front(1);
         if (__pos == 0)
         {
             __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v);
@@ -1694,6 +1976,7 @@
         if (__back_spare() == 0)
             __add_back_capacity();
         // __back_capacity >= 1
+        __annotate_increase_back(1);
         size_type __de = size() - __pos;
         if (__de == 0)
         {
@@ -1729,6 +2012,7 @@
         if (__n > __front_spare())
             __add_front_capacity(__n - __front_spare());
         // __n <= __front_spare()
+        __annotate_increase_front(__n);
         iterator __old_begin = begin();
         iterator __i = __old_begin;
         if (__n > __pos)
@@ -1753,6 +2037,7 @@
         if (__n > __back_capacity)
             __add_back_capacity(__n - __back_capacity);
         // __n <= __back_capacity
+        __annotate_increase_back(__n);
         iterator __old_end = end();
         iterator __i = __old_end;
         size_type __de = size() - __pos;
@@ -1845,6 +2130,7 @@
         if (__n > __front_spare())
             __add_front_capacity(__n - __front_spare());
         // __n <= __front_spare()
+        __annotate_increase_front(__n);
         iterator __old_begin = begin();
         iterator __i = __old_begin;
         _BiIter __m = __f;
@@ -1875,6 +2161,7 @@
         if (__n > __back_capacity)
             __add_back_capacity(__n - __back_capacity);
         // __n <= __back_capacity
+        __annotate_increase_back(__n);
         iterator __old_end = end();
         iterator __i = __old_end;
         _BiIter __m = __l;
@@ -1939,6 +2226,7 @@
         __add_back_capacity(__n - __back_capacity);
 
     // __n <= __back_capacity
+    __annotate_increase_back(__n);
     for (__deque_block_range __br : __deque_range(end(), end() + __n)) {
       _ConstructTransaction __tx(this, __br);
       for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) {
@@ -1956,6 +2244,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(end(), end() + __n)) {
       _ConstructTransaction __tx(this, __br);
       for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
@@ -1973,6 +2262,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(end(), end() + __n)) {
       _ConstructTransaction __tx(this, __br);
       for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
@@ -2040,6 +2330,7 @@
                                __block_size / 2 :
                                __start_ + __block_size;
     }
+    __annotate_whole_block(0, __asan_poison);
 }
 
 // Create front capacity for __n elements.
@@ -2075,6 +2366,7 @@
             if (__map_.__front_spare() == 0)
                 break;
             __map_.push_front(__alloc_traits::allocate(__a, __block_size));
+            __annotate_whole_block(0, __asan_poison);
         }
         for (; __nb > 0; --__nb, ++__back_capacity)
             __map_.push_back(__alloc_traits::allocate(__a, __block_size));
@@ -2085,6 +2377,7 @@
             pointer __pt = __map_.back();
             __map_.pop_back();
             __map_.push_front(__pt);
+            __annotate_whole_block(0, __asan_poison);
         }
     }
     // Else need to allocate __nb buffers, *and* we need to reallocate __map_.
@@ -2099,12 +2392,18 @@
         try
         {
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
-            for (; __nb > 0; --__nb)
+            for (; __nb > 0; --__nb) {
                 __buf.push_back(__alloc_traits::allocate(__a, __block_size));
+                // ASan: this is empty container, we have to poison whole block
+                __annotate_poison_block(
+                    std::__to_address(__buf.back()),
+                    std::__to_address(__buf.back() + __block_size));
+            }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
         catch (...)
         {
+            __annotate_delete();
             for (__map_pointer __i = __buf.begin();
                     __i != __buf.end(); ++__i)
                 __alloc_traits::deallocate(__a, *__i, __block_size);
@@ -2156,6 +2455,7 @@
             __map_.pop_front();
             __map_.push_back(__pt);
         }
+        __annotate_whole_block(__map_.size() - 1, __asan_poison);
     }
     // Else need to allocate 1 buffer, *and* we need to reallocate __map_.
     else
@@ -2179,6 +2479,7 @@
         _VSTD::swap(__map_.__begin_, __buf.__begin_);
         _VSTD::swap(__map_.__end_, __buf.__end_);
         _VSTD::swap(__map_.__end_cap(), __buf.__end_cap());
+        __annotate_whole_block(__map_.size() - 1, __asan_poison);
     }
 }
 
@@ -2215,10 +2516,13 @@
             if (__map_.__back_spare() == 0)
                 break;
             __map_.push_back(__alloc_traits::allocate(__a, __block_size));
+            __annotate_whole_block(__map_.size() - 1, __asan_poison);
         }
         for (; __nb > 0; --__nb, ++__front_capacity, __start_ +=
-                                 __block_size - (__map_.size() == 1))
+                                 __block_size - (__map_.size() == 1)) {
             __map_.push_front(__alloc_traits::allocate(__a, __block_size));
+            __annotate_whole_block(0, __asan_poison);
+        }
         // Done allocating, reorder capacity
         __start_ -= __block_size * __front_capacity;
         for (; __front_capacity > 0; --__front_capacity)
@@ -2241,12 +2545,18 @@
         try
         {
 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
-            for (; __nb > 0; --__nb)
+            for (; __nb > 0; --__nb) {
                 __buf.push_back(__alloc_traits::allocate(__a, __block_size));
+                // ASan: this is an empty container, we have to poison the whole block
+                __annotate_poison_block(
+                    std::__to_address(__buf.back()),
+                    std::__to_address(__buf.back() + __block_size));
+            }
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
         }
         catch (...)
         {
+            __annotate_delete();
             for (__map_pointer __i = __buf.begin();
                     __i != __buf.end(); ++__i)
                 __alloc_traits::deallocate(__a, *__i, __block_size);
@@ -2273,12 +2583,15 @@
 void
 deque<_Tp, _Allocator>::pop_front()
 {
+    size_type __old_sz    = size();
+    size_type __old_start = __start_;
     allocator_type& __a = __alloc();
     __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() +
                                                     __start_ / __block_size) +
                                                     __start_ % __block_size));
     --__size();
     ++__start_;
+    __annotate_shrink_front(__old_sz, __old_start);
     __maybe_remove_front_spare();
 }
 
@@ -2287,12 +2600,15 @@
 deque<_Tp, _Allocator>::pop_back()
 {
     _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque");
+    size_type __old_sz    = size();
+    size_type __old_start = __start_;
     allocator_type& __a = __alloc();
     size_type __p = size() + __start_ - 1;
     __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() +
                                                     __p / __block_size) +
                                                     __p % __block_size));
     --__size();
+    __annotate_shrink_back(__old_sz, __old_start);
     __maybe_remove_back_spare();
 }
 
@@ -2432,6 +2748,8 @@
 typename deque<_Tp, _Allocator>::iterator
 deque<_Tp, _Allocator>::erase(const_iterator __f)
 {
+    size_type __old_sz    = size();
+    size_type __old_start = __start_;
     iterator __b = begin();
     difference_type __pos = __f - __b;
     iterator __p = __b + __pos;
@@ -2442,6 +2760,7 @@
         __alloc_traits::destroy(__a, _VSTD::addressof(*__b));
         --__size();
         ++__start_;
+        __annotate_shrink_front(__old_sz, __old_start);
         __maybe_remove_front_spare();
     }
     else
@@ -2449,6 +2768,7 @@
         iterator __i = _VSTD::move(_VSTD::next(__p), end(), __p);
         __alloc_traits::destroy(__a, _VSTD::addressof(*__i));
         --__size();
+        __annotate_shrink_back(__old_sz, __old_start);
         __maybe_remove_back_spare();
     }
     return begin() + __pos;
@@ -2458,6 +2778,8 @@
 typename deque<_Tp, _Allocator>::iterator
 deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l)
 {
+    size_type __old_sz    = size();
+    size_type __old_start = __start_;
     difference_type __n = __l - __f;
     iterator __b = begin();
     difference_type __pos = __f - __b;
@@ -2472,6 +2794,7 @@
                 __alloc_traits::destroy(__a, _VSTD::addressof(*__b));
             __size() -= __n;
             __start_ += __n;
+            __annotate_shrink_front(__old_sz, __old_start);
             while (__maybe_remove_front_spare()) {
             }
         }
@@ -2481,6 +2804,7 @@
             for (iterator __e = end(); __i != __e; ++__i)
                 __alloc_traits::destroy(__a, _VSTD::addressof(*__i));
             __size() -= __n;
+            __annotate_shrink_back(__old_sz, __old_start);
             while (__maybe_remove_back_spare()) {
             }
         }
@@ -2492,6 +2816,8 @@
 void
 deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f)
 {
+    size_type __old_sz    = size();
+    size_type __old_start = __start_;
     iterator __e = end();
     difference_type __n = __e - __f;
     if (__n > 0)
@@ -2502,6 +2828,7 @@
         for (iterator __p = __b + __pos; __p != __e; ++__p)
             __alloc_traits::destroy(__a, _VSTD::addressof(*__p));
         __size() -= __n;
+        __annotate_shrink_back(__old_sz, __old_start);
         while (__maybe_remove_back_spare()) {
         }
     }
@@ -2529,6 +2856,7 @@
 void
 deque<_Tp, _Allocator>::clear() _NOEXCEPT
 {
+    __annotate_delete();
     allocator_type& __a = __alloc();
     for (iterator __i = begin(), __e = end(); __i != __e; ++__i)
         __alloc_traits::destroy(__a, _VSTD::addressof(*__i));
@@ -2547,6 +2875,7 @@
         __start_ = __block_size;
         break;
     }
+    __annotate_new(0);
 }
 
 template <class _Tp, class _Allocator>
diff --git a/libcxx/test/libcxx/containers/sequences/deque/asan.pass.cpp b/libcxx/test/libcxx/containers/sequences/deque/asan.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/deque/asan.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: asan
+
+// <deque>
+
+// reference operator[](size_type n);
+
+#include "asan_testing.h"
+#include <deque>
+#include <cassert>
+#include <cstdlib>
+
+#include "min_allocator.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+extern "C" void __sanitizer_set_death_callback(void (*callback)(void));
+
+void do_exit() {
+  exit(0);
+}
+
+int main(int, char**)
+{
+    {
+        typedef cpp17_input_iterator<int*> MyInputIter;
+        // Sould not trigger ASan.
+        std::deque<int> v;
+        int i[] = {42};
+        v.insert(v.begin(), MyInputIter(i), MyInputIter(i + 1));
+        assert(v[0] == 42);
+        assert(is_double_ended_contiguous_container_asan_correct(v));
+    }
+    __sanitizer_set_death_callback(do_exit);
+    {
+        typedef int T;
+        typedef std::deque<T> C;
+        const T t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        C c(std::begin(t), std::end(t));
+        assert(is_double_ended_contiguous_container_asan_correct(c));
+        T* ptr = &c[0];
+        for(size_t i = 0; i < (8 + sizeof(T) - 1)/sizeof(T); ++i)
+          c.pop_front();
+        *ptr = 1;
+        volatile T foo = c[c.size()]; // should trigger ASAN. Use volatile to prevent being optimized away.
+        assert(false);          // if we got here, ASAN didn't trigger
+        ((void)foo);
+    }
+}
diff --git a/libcxx/test/libcxx/containers/sequences/deque/asan_annotate.begin.end.pass.cpp b/libcxx/test/libcxx/containers/sequences/deque/asan_annotate.begin.end.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/deque/asan_annotate.begin.end.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// Regression test to error in deque::__annotate_from_to in deque.
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03
+// XFAIL: availability-verbose_abort-missing
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+#include <deque>
+#include <cstdio>
+#include "check_assertion.h"
+
+void test1() {
+  std::deque<char> test;
+  char buff[100000];
+  test.insert(test.end(), buff, buff + 64000);
+
+  for (int i = 0; i < 1100; i += 1) {
+    test.insert(test.begin(), buff, buff + 320);
+    test.erase(test.end(), test.end() - 320);
+  }
+
+  test.insert(test.end(), buff, buff + 32000);
+}
+
+void test2() {
+  std::deque<char> test;
+  char buff[100000];
+  test.insert(test.end(), buff, buff + 64000);
+
+  for (int i = 0; i < 1100; i += 1) {
+    test.insert(test.end(), buff, buff + 320);
+    test.erase(test.begin(), test.begin() + 320);
+  }
+
+  test.insert(test.end(), buff, buff + 32000);
+}
+
+int main(int, char**) {
+  test1();
+  test2();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp
@@ -21,6 +21,7 @@
 // const_reference back() const;
 // libc++ marks these as 'noexcept'
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -66,6 +67,7 @@
             assert(c.at(i) == i);
         assert(c.front() == 0);
         assert(c.back() == 9);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
     {
         typedef std::deque<int> C;
@@ -82,6 +84,7 @@
             assert(c.at(i) == i);
         assert(c.front() == 0);
         assert(c.back() == 9);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #if TEST_STD_VER >= 11
     {
@@ -99,6 +102,7 @@
             assert(c.at(i) == i);
         assert(c.front() == 0);
         assert(c.back() == 9);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
     {
         typedef std::deque<int, min_allocator<int>> C;
@@ -115,6 +119,7 @@
             assert(c.at(i) == i);
         assert(c.front() == 0);
         assert(c.back() == 9);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp
@@ -12,6 +12,7 @@
 
 // bool empty() const noexcept;
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -27,8 +28,10 @@
     assert(c.empty());
     c.push_back(C::value_type(1));
     assert(!c.empty());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.clear();
     assert(c.empty());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #if TEST_STD_VER >= 11
     {
@@ -38,8 +41,10 @@
     assert(c.empty());
     c.push_back(C::value_type(1));
     assert(!c.empty());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.clear();
     assert(c.empty());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp
@@ -10,6 +10,7 @@
 
 // size_type max_size() const;
 
+#include "asan_testing.h"
 #include <cassert>
 #include <deque>
 #include <limits>
@@ -25,6 +26,7 @@
     C c;
     assert(c.max_size() <= 10);
     LIBCPP_ASSERT(c.max_size() == 10);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
   }
   {
     typedef limited_allocator<int, (std::size_t)-1> A;
@@ -34,6 +36,7 @@
     C c;
     assert(c.max_size() <= max_dist);
     LIBCPP_ASSERT(c.max_size() == max_dist);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
   }
   {
     typedef std::deque<char> C;
@@ -42,6 +45,7 @@
     C c;
     assert(c.max_size() <= max_dist);
     assert(c.max_size() <= alloc_max_size(c.get_allocator()));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
   }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp
@@ -10,6 +10,7 @@
 
 // void resize(size_type n);
 
+#include "asan_testing.h"
 #include <deque>
 #include <algorithm>
 #include <iterator>
@@ -34,10 +35,13 @@
     C c(init, 0);
     for (int i = 0; i < init-start; ++i)
         c.pop_back();
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     for (int i = 0; i < size; ++i)
         c.push_back(i);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     for (int i = 0; i < start; ++i)
         c.pop_front();
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     return c;
 }
 
@@ -50,6 +54,7 @@
     c1.resize(size);
     assert(c1.size() == static_cast<std::size_t>(size));
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     CI i = c1.begin();
     for (int j = 0; static_cast<std::size_t>(j) < std::min(c1_osize, c1.size()); ++j, ++i)
         assert(*i == j);
@@ -84,6 +89,14 @@
             for (int k = 0; k < N; ++k)
                 testN<std::deque<int, min_allocator<int>>>(rng[i], rng[j], rng[k]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            for (int k = 0; k < N; ++k)
+                testN<std::deque<int, safe_allocator<int>>>(rng[i], rng[j], rng[k]);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp
@@ -10,6 +10,7 @@
 
 // void resize(size_type n, const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <algorithm>
 #include <iterator>
@@ -34,10 +35,13 @@
     C c(init, 0);
     for (int i = 0; i < init-start; ++i)
         c.pop_back();
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     for (int i = 0; i < size; ++i)
         c.push_back(i);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     for (int i = 0; i < start; ++i)
         c.pop_front();
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     return c;
 }
 
@@ -50,6 +54,7 @@
     c1.resize(size, x);
     assert(c1.size() == static_cast<std::size_t>(size));
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     CI i = c1.begin();
     for (int j = 0; static_cast<std::size_t>(j) < std::min(c1_osize, c1.size()); ++j, ++i)
         assert(*i == j);
@@ -84,6 +89,14 @@
             for (int k = 0; k < N; ++k)
                 testN<std::deque<int, min_allocator<int>>>(rng[i], rng[j], rng[k]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            for (int k = 0; k < N; ++k)
+                testN<std::deque<int, safe_allocator<int>>>(rng[i], rng[j], rng[k]);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp
@@ -10,6 +10,7 @@
 
 // void shrink_to_fit();
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -45,6 +46,7 @@
     C s = c1;
     c1.shrink_to_fit();
     assert(c1 == s);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
 }
 
 template <class C>
@@ -72,6 +74,13 @@
         for (int j = 0; j < N; ++j)
             testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j]);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp
@@ -12,6 +12,7 @@
 
 // size_type size() const noexcept;
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -25,18 +26,25 @@
     C c;
     ASSERT_NOEXCEPT(c.size());
     assert(c.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(2));
     assert(c.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(1));
     assert(c.size() == 2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(3));
     assert(c.size() == 3);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #if TEST_STD_VER >= 11
     {
@@ -44,18 +52,25 @@
     C c;
     ASSERT_NOEXCEPT(c.size());
     assert(c.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(2));
     assert(c.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(1));
     assert(c.size() == 2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.push_back(C::value_type(3));
     assert(c.size() == 3);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     c.erase(c.begin());
     assert(c.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
@@ -10,6 +10,7 @@
 
 // explicit deque(const allocator_type& a);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -25,6 +26,7 @@
     std::deque<T, Allocator> d(a);
     assert(d.size() == 0);
     assert(d.get_allocator() == a);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
 }
 
 int main(int, char**)
@@ -33,7 +35,9 @@
     test<NotConstructible>(test_allocator<NotConstructible>(3));
 #if TEST_STD_VER >= 11
     test<int>(min_allocator<int>());
+    test<int>(safe_allocator<int>());
     test<NotConstructible>(min_allocator<NotConstructible>{});
+    test<NotConstructible>(safe_allocator<NotConstructible>{});
     test<int>(explicit_allocator<int>());
     test<NotConstructible>(explicit_allocator<NotConstructible>{});
 #endif
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp
@@ -12,6 +12,7 @@
 
 // void assign(initializer_list<value_type> il);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -28,6 +29,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
     {
     std::deque<int, min_allocator<int>> d;
@@ -37,6 +39,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp
@@ -11,6 +11,7 @@
 // template <class InputIterator>
 //   void assign(InputIterator f, InputIterator l);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -51,6 +52,8 @@
     c1.assign(c2.begin(), c2.end());
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 template <class C>
@@ -71,6 +74,8 @@
     c1.assign(ICI(c2.begin()), ICI(c2.end()));
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 template <class C>
@@ -103,6 +108,15 @@
                 testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j], rng[k]);
     testNI<std::deque<int, min_allocator<int>> >(1500, 2000, 1000);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            for (int k = 0; k < N; ++k)
+                testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j], rng[k]);
+    testNI<std::deque<int, safe_allocator<int>> >(1500, 2000, 1000);
+    }
 #endif
 }
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp
@@ -10,6 +10,7 @@
 
 // void assign(size_type n, const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -48,6 +49,7 @@
     c1.assign(size, v);
     assert(c1.size() == static_cast<std::size_t>(size));
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     for (CI i = c1.begin(); i != c1.end(); ++i)
         assert(*i == v);
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque(const deque&);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -23,6 +24,8 @@
 {
     C c(x);
     assert(c == x);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(x));
 }
 
 int main(int, char**)
@@ -37,6 +40,8 @@
         std::deque<int, test_allocator<int> > v2 = v;
         assert(v2 == v);
         assert(v2.get_allocator() == v.get_allocator());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2));
     }
 #if TEST_STD_VER >= 11
     {
@@ -44,6 +49,8 @@
         std::deque<int, other_allocator<int> > v2 = v;
         assert(v2 == v);
         assert(v2.get_allocator() == other_allocator<int>(-2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -55,6 +62,8 @@
         std::deque<int, min_allocator<int> > v2 = v;
         assert(v2 == v);
         assert(v2.get_allocator() == v.get_allocator());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque(const deque& c, const allocator_type& a);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -24,6 +25,7 @@
     C c(x, a);
     assert(c == x);
     assert(c.get_allocator() == a);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 }
 
 int main(int, char**)
@@ -47,6 +49,12 @@
         test(std::deque<int, min_allocator<int> >(ab, an, min_allocator<int>()),
                                                           min_allocator<int>());
     }
+    {
+        int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
+        int* an = ab + sizeof(ab)/sizeof(ab[0]);
+        test(std::deque<int, safe_allocator<int> >(ab, an, safe_allocator<int>()),
+                                                          safe_allocator<int>());
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
@@ -17,6 +17,7 @@
 //   deque(from_range_t, R&&, Allocator = Allocator())
 //     -> deque<ranges::range_value_t<R>, Allocator>; // C++23
 
+#include "asan_testing.h"
 #include <array>
 #include <cassert>
 #include <climits> // INT_MAX
@@ -41,6 +42,7 @@
 
     static_assert(std::is_same_v<decltype(deq), std::deque<int>>, "");
     assert(std::equal(deq.begin(), deq.end(), std::begin(arr), std::end(arr)));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -51,6 +53,7 @@
     assert(deq[0] == INT_MAX);
     assert(deq[1] == 1L);
     assert(deq[2] == 2L);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
 //  Test the implicit deduction guides
@@ -65,6 +68,7 @@
     static_assert(std::is_same_v<decltype(deq)::value_type, A>, "");
     static_assert(std::is_same_v<decltype(deq)::allocator_type, std::allocator<A>>, "");
     assert(deq.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -72,6 +76,7 @@
     static_assert(std::is_same_v<decltype(deq)::value_type, A>, "");
     static_assert(std::is_same_v<decltype(deq)::allocator_type, test_allocator<A>>, "");
     assert(deq.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -79,6 +84,7 @@
     static_assert(std::is_same_v<decltype(deq)::value_type, unsigned>, "");
     assert(deq.size() == 5);
     assert(deq[2] == 3U);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -87,6 +93,7 @@
     static_assert(std::is_same_v<decltype(deq)::allocator_type, test_allocator<double>>, "");
     assert(deq.size() == 4);
     assert(deq[3] == 4.0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -95,6 +102,7 @@
     static_assert(std::is_same_v<decltype(deq)::value_type, long double>, "");
     static_assert(std::is_same_v<decltype(deq)::allocator_type, std::allocator<long double>>, "");
     assert(deq.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
     }
 
     {
@@ -105,24 +113,32 @@
         std::deque<short, Alloc> source;
         std::deque deq(source, Alloc(2));
         static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source));
         }
 
         {
         std::deque<short, Alloc> source;
         std::deque deq(source, ConvertibleToAlloc(2));
         static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source));
         }
 
         {
         std::deque<short, Alloc> source;
         std::deque deq(std::move(source), Alloc(2));
         static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source));
         }
 
         {
         std::deque<short, Alloc> source;
         std::deque deq(std::move(source), ConvertibleToAlloc(2));
         static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source));
         }
     }
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque()
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -24,9 +25,11 @@
 {
     std::deque<T, Allocator> d;
     assert(d.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
 #if TEST_STD_VER >= 11
     std::deque<T, Allocator> d1 = {};
     assert(d1.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d1));
 #endif
 }
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque(initializer_list<value_type> il);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -27,6 +28,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
     {
     std::deque<int, min_allocator<int>> d = {3, 4, 5, 6};
@@ -35,6 +37,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque(initializer_list<value_type> il, const Allocator& a = allocator_type());
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -29,6 +30,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
     {
     std::deque<int, min_allocator<int>> d({3, 4, 5, 6}, min_allocator<int>());
@@ -38,6 +40,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
@@ -10,6 +10,7 @@
 
 // template <class InputIterator> deque(InputIterator f, InputIterator l);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -33,6 +34,7 @@
     C d(f, l);
     assert(d.size() == static_cast<std::size_t>(std::distance(f, l)));
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f)
         assert(*i == *f);
 }
@@ -47,6 +49,7 @@
     C d(f, l);
     assert(d.size() == static_cast<std::size_t>(std::distance(f, l)));
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f)
         assert(*i == *f);
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp
@@ -11,6 +11,7 @@
 // template <class InputIterator>
 //   deque(InputIterator f, InputIterator l, const allocator_type& a);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -34,6 +35,7 @@
     assert(d.get_allocator() == a);
     assert(d.size() == static_cast<std::size_t>(std::distance(f, l)));
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f)
         assert(*i == *f);
 }
@@ -66,12 +68,14 @@
     {
       std::deque<T> v(It(arr1), It(std::end(arr1)), a);
       assert(v[0].value == 42);
+      LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
     {
       std::deque<T> v(It(arr2), It(std::end(arr2)), a);
       assert(v[0].value == 1);
       assert(v[1].value == 101);
       assert(v[2].value == 42);
+      LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
   }
   {
@@ -82,6 +86,7 @@
       std::deque<T> v(It(arr1), It(std::end(arr1)), a);
       assert(v[0].copied == 0);
       assert(v[0].value == 42);
+      LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
     {
       std::deque<T> v(It(arr2), It(std::end(arr2)), a);
@@ -91,6 +96,7 @@
       assert(v[1].value == 101);
       assert(v[2].copied == 0);
       assert(v[2].value == 42);
+      LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
   }
 #endif
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque(deque&&);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -38,6 +39,9 @@
         assert(c1.size() == 0);
         assert(c3.get_allocator() == old_a);
         assert(c1.get_allocator() == A(test_alloc_base::moved_value));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -53,6 +57,9 @@
         assert(c2 == c3);
         assert(c1.size() == 0);
         assert(c3.get_allocator() == c1.get_allocator());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -68,6 +75,9 @@
         assert(c2 == c3);
         assert(c1.size() == 0);
         assert(c3.get_allocator() == c1.get_allocator());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque(deque&& c, const allocator_type& a);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -36,6 +37,9 @@
         assert(c2 == c3);
         assert(c3.get_allocator() == A(3));
         LIBCPP_ASSERT(c1.size() != 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -51,6 +55,9 @@
         assert(c2 == c3);
         assert(c3.get_allocator() == A(1));
         LIBCPP_ASSERT(c1.size() == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -66,6 +73,9 @@
         assert(c2 == c3);
         assert(c3.get_allocator() == A(3));
         LIBCPP_ASSERT(c1.size() != 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -81,6 +91,9 @@
         assert(c2 == c3);
         assert(c3.get_allocator() == A());
         LIBCPP_ASSERT(c1.size() == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque& operator=(deque&& c);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -37,6 +38,9 @@
         assert(c2 == c3);
         assert(c1.size() == 0);
         assert(c3.get_allocator() == A(5));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -53,6 +57,9 @@
         assert(c2 == c3);
         assert(c1.size() != 0);
         assert(c3.get_allocator() == A(6));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -69,6 +76,9 @@
         assert(c2 == c3);
         assert(c1.size() == 0);
         assert(c3.get_allocator() == A(5));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
     {
         int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45};
@@ -85,6 +95,9 @@
         assert(c2 == c3);
         assert(c1.size() == 0);
         assert(c3.get_allocator() == A());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque& operator=(const deque& c);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include "test_macros.h"
@@ -23,6 +24,8 @@
     C c;
     c = x;
     assert(c == x);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(x));
 }
 
 int main(int, char**)
@@ -38,6 +41,8 @@
         l2 = l;
         assert(l2 == l);
         assert(l2.get_allocator() == test_allocator<int>(3));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2));
     }
     {
         std::deque<int, other_allocator<int> > l(3, 2, other_allocator<int>(5));
@@ -45,6 +50,8 @@
         l2 = l;
         assert(l2 == l);
         assert(l2.get_allocator() == other_allocator<int>(5));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2));
     }
 #if TEST_STD_VER >= 11
     {
@@ -58,6 +65,8 @@
         l2 = l;
         assert(l2 == l);
         assert(l2.get_allocator() == min_allocator<int>());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp
@@ -12,6 +12,7 @@
 
 // deque& operator=(initializer_list<value_type> il);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -28,6 +29,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
     {
     std::deque<int, min_allocator<int>> d;
@@ -37,6 +39,7 @@
     assert(d[1] == 4);
     assert(d[2] == 5);
     assert(d[3] == 6);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp
@@ -10,6 +10,7 @@
 
 // explicit deque(size_type n);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -32,6 +33,7 @@
     assert(static_cast<unsigned>(DefaultOnly::count) == n);
     assert(d.size() == n);
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == T());
     }
@@ -53,6 +55,7 @@
     assert(static_cast<unsigned>(DefaultOnly::count) == n);
     assert(d.size() == n);
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
 #if TEST_STD_VER >= 11
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == T());
@@ -71,6 +74,7 @@
     C d(n, alloc);
     assert(d.size() == n);
     assert(d.get_allocator() == alloc);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 #else
     ((void)n);
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque(size_type n, const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -27,6 +28,7 @@
     C d(n, x);
     assert(d.size() == n);
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == x);
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
@@ -10,6 +10,7 @@
 
 // deque(size_type n, const value_type& v, const allocator_type& a);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -27,6 +28,7 @@
     assert(d.get_allocator() == a);
     assert(d.size() == n);
     assert(static_cast<std::size_t>(std::distance(d.begin(), d.end())) == d.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == x);
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
@@ -13,6 +13,7 @@
 //   typename deque<T, Allocator>::size_type
 //   erase(deque<T, Allocator>& c, const U& value);
 
+#include "asan_testing.h"
 #include <deque>
 #include <optional>
 
@@ -25,6 +26,7 @@
   ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase(s, val)));
   assert(expected_erased_count == std::erase(s, val));
   assert(s == expected);
+  LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(s));
 }
 
 template <class S>
@@ -67,6 +69,7 @@
 {
     test<std::deque<int>>();
     test<std::deque<int, min_allocator<int>>> ();
+    test<std::deque<int, safe_allocator<int>>> ();
     test<std::deque<int, test_allocator<int>>> ();
 
     test<std::deque<long>>();
diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
@@ -13,6 +13,7 @@
 //   typename deque<T, Allocator>::size_type
 //   erase_if(deque<T, Allocator>& c, Predicate pred);
 
+#include "asan_testing.h"
 #include <deque>
 
 #include "test_macros.h"
@@ -24,6 +25,7 @@
   ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase_if(s, p)));
   assert(expected_erased_count == std::erase_if(s, p));
   assert(s == expected);
+  LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(s));
 }
 
 template <typename S>
@@ -69,6 +71,7 @@
 {
     test<std::deque<int>>();
     test<std::deque<int, min_allocator<int>>> ();
+    test<std::deque<int, safe_allocator<int>>> ();
     test<std::deque<int, test_allocator<int>>> ();
 
     test<std::deque<long>>();
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp
@@ -10,6 +10,7 @@
 
 // void clear() noexcept;
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -26,6 +27,7 @@
         ASSERT_NOEXCEPT(c.clear());
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
     {
         typedef int T;
@@ -36,9 +38,11 @@
         ASSERT_NOEXCEPT(c.clear());
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #if TEST_STD_VER >= 11
     {
@@ -48,6 +52,7 @@
         ASSERT_NOEXCEPT(c.clear());
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
     {
         typedef int T;
@@ -58,9 +63,11 @@
         ASSERT_NOEXCEPT(c.clear());
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 
         c.clear();
         assert(std::distance(c.begin(), c.end()) == 0);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp
@@ -12,6 +12,7 @@
 
 // UNSUPPORTED: c++03
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -54,6 +55,7 @@
     assert(c1.size() == c1_osize + 1);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
     assert(*i == Emplaceable(1, 2.5));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
 }
 
 template <class C>
@@ -103,6 +105,13 @@
         for (int j = 0; j < N; ++j)
             testN<std::deque<Emplaceable, min_allocator<Emplaceable>> >(rng[i], rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<Emplaceable, safe_allocator<Emplaceable>> >(rng[i], rng[j]);
+    }
 
   return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp
@@ -13,6 +13,7 @@
 // template <class... Args> reference emplace_back(Args&&... args);
 // return type is 'reference' in C++17; 'void' before
 
+#include "asan_testing.h"
 #include <deque>
 #include <cstddef>
 #include <cassert>
@@ -61,6 +62,7 @@
                == static_cast<std::ptrdiff_t>(c1.size()));
     I i = c1.end();
     assert(*--i == Emplaceable(1, 2.5));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
 #if TEST_STD_VER > 14
     assert(&(*i) == &ref);
 #endif
@@ -94,12 +96,16 @@
         std::deque<Tag_X, TaggingAllocator<Tag_X>> c;
         c.emplace_back();
         assert(c.size() == 1);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_back(1, 2, 3);
         assert(c.size() == 2);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_front();
         assert(c.size() == 3);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_front(1, 2, 3);
         assert(c.size() == 4);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp
@@ -13,6 +13,7 @@
 // template <class... Args> reference emplace_front(Args&&... args);
 // return type is 'reference' in C++17; 'void' before
 
+#include "asan_testing.h"
 #include <deque>
 #include <cstddef>
 #include <cassert>
@@ -61,6 +62,7 @@
                == static_cast<std::ptrdiff_t>(c1.size()));
     I i = c1.begin();
     assert(*i == Emplaceable(1, 2.5));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
 #if TEST_STD_VER > 14
     assert(&res_ref == &(*i));
 #endif
@@ -95,12 +97,16 @@
         std::deque<Tag_X, TaggingAllocator<Tag_X>> c;
         c.emplace_front();
         assert(c.size() == 1);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_front(1, 2, 3);
         assert(c.size() == 2);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_front();
         assert(c.size() == 3);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         c.emplace_front(1, 2, 3);
         assert(c.size() == 4);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp
@@ -13,6 +13,7 @@
 //  Erasing items from the beginning or the end of a deque shall not invalidate iterators
 //  to items that were not erased.
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -54,6 +55,7 @@
     assert(  it2 ==   it4);
     assert( *it2 ==  *it4);
     assert(&*it2 == &*it4);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp
@@ -10,6 +10,7 @@
 
 // iterator erase(const_iterator p)
 
+#include "asan_testing.h"
 #include <deque>
 #include <algorithm>
 #include <iterator>
@@ -119,6 +120,7 @@
     v.erase(--v.end());
     v.erase(v.begin());
     assert(v.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp
@@ -14,6 +14,7 @@
 //  to items that were not erased.
 
 
+#include "asan_testing.h"
 #include <deque>
 #include <cstdint>
 #include <cassert>
@@ -38,6 +39,7 @@
     assert(  it2 ==   it4);
     assert( *it2 ==  *it4);
     assert(&*it2 == &*it4);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 }
 
 template <typename C>
@@ -58,6 +60,7 @@
     assert(  it2 ==   it4);
     assert( *it2 ==  *it4);
     assert(&*it2 == &*it4);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 }
 
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp
@@ -12,6 +12,7 @@
 
 // iterator erase(const_iterator f, const_iterator l)
 
+#include "asan_testing.h"
 #include <deque>
 #include <algorithm>
 #include <iterator>
@@ -71,6 +72,7 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize - size);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     i = c1.begin();
     int j = 0;
     for (; j < P; ++j, ++i)
@@ -123,8 +125,10 @@
     Throws::sThrows = true;
     v.erase(v.begin(), --v.end());
     assert(v.size() == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     v.erase(v.begin(), v.end());
     assert(v.size() == 0);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v));
     }
 #endif
 
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp
@@ -12,6 +12,7 @@
 
 // iterator insert(const_iterator p, initializer_list<value_type> il);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -39,6 +40,7 @@
     assert(d[11] == 1);
     assert(d[12] == 1);
     assert(d[13] == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
     {
     std::deque<int, min_allocator<int>> d(10, 1);
@@ -59,6 +61,7 @@
     assert(d[11] == 1);
     assert(d[12] == 1);
     assert(d[13] == 1);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
@@ -13,6 +13,7 @@
 // template <class InputIterator>
 //   iterator insert (const_iterator p, InputIterator f, InputIterator l);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -58,6 +59,8 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize + c2.size());
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     i = c1.begin();
     for (int j = 0; j < P; ++j, ++i)
         assert(*i == j);
@@ -173,6 +176,8 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize + c2.size());
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     i = c1.begin();
     for (int j = 0; j < P; ++j, ++i)
         assert(*i == j);
@@ -284,6 +289,16 @@
     testNI<std::deque<int> >(1500, 2000, 1000);
     test_move<std::deque<MoveOnly, min_allocator<MoveOnly> > >();
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            for (int k = 0; k < N; ++k)
+                testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j], rng[k]);
+    testNI<std::deque<int> >(1500, 2000, 1000);
+    test_move<std::deque<MoveOnly, safe_allocator<MoveOnly> > >();
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp
@@ -12,6 +12,7 @@
 
 // UNSUPPORTED: c++03
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -53,6 +54,7 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize + 1);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     i = c1.begin();
     for (int j = 0; j < P; ++j, (void) ++i)
         assert(*i == MoveOnly(j));
@@ -108,6 +110,13 @@
         for (int j = 0; j < N; ++j)
             testN<std::deque<MoveOnly, min_allocator<MoveOnly>> >(rng[i], rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<MoveOnly, safe_allocator<MoveOnly>> >(rng[i], rng[j]);
+    }
 
   return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp
@@ -12,6 +12,7 @@
 
 // iterator insert (const_iterator p, size_type n, const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -51,6 +52,7 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize + size);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     i = c1.begin();
     for (int j = 0; j < P; ++j, ++i)
         assert(*i == j);
@@ -153,6 +155,15 @@
                 testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j], rng[k]);
     self_reference_test<std::deque<int, min_allocator<int>> >();
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            for (int k = 0; k < N; ++k)
+                testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j], rng[k]);
+    self_reference_test<std::deque<int, safe_allocator<int>> >();
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp
@@ -10,6 +10,7 @@
 
 // iterator insert (const_iterator p, const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -49,6 +50,7 @@
     assert(i == c1.begin() + P);
     assert(c1.size() == c1_osize + 1);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     i = c1.begin();
     for (int j = 0; j < P; ++j, ++i)
         assert(*i == j);
@@ -133,6 +135,14 @@
             testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j]);
     self_reference_test<std::deque<int, min_allocator<int>> >();
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j]);
+    self_reference_test<std::deque<int, safe_allocator<int>> >();
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp
@@ -13,6 +13,7 @@
 //  Erasing items from the beginning or the end of a deque shall not invalidate iterators
 //  to items that were not erased.
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -34,18 +35,20 @@
     assert(  it2 ==   it4);
     assert( *it2 ==  *it4);
     assert(&*it2 == &*it4);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
 }
 
 int main(int, char**)
 {
     std::deque<int> queue;
-    for (int i = 0; i < 20; ++i)
+    for (int i = 0; i < 4098; ++i)
         queue.push_back(i);
 
     while (queue.size() > 1)
     {
         test(queue);
         queue.pop_back();
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(queue));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp
@@ -10,6 +10,7 @@
 
 // void pop_back()
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -48,6 +49,7 @@
     c1.pop_back();
     assert(c1.size() == c1_osize - 1);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     I i = c1.begin();
     for (int j = 0; static_cast<std::size_t>(j) < c1.size(); ++j, ++i)
         assert(*i == j);
@@ -81,6 +83,13 @@
         for (int j = 0; j < N; ++j)
             testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j]);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp
@@ -13,6 +13,7 @@
 //  Erasing items from the beginning or the end of a deque shall not invalidate iterators
 //  to items that were not erased.
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -39,13 +40,14 @@
 int main(int, char**)
 {
     std::deque<int> queue;
-    for (int i = 0; i < 20; ++i)
+    for (int i = 0; i < 4098; ++i)
         queue.push_back(i);
 
     while (queue.size() > 1)
     {
         test(queue);
         queue.pop_back();
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(queue));
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp
@@ -10,6 +10,7 @@
 
 // void pop_front()
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -48,6 +49,7 @@
     c1.pop_front();
     assert(c1.size() == c1_osize - 1);
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     I i = c1.begin();
     for (int j = 1; static_cast<std::size_t>(j) < c1.size(); ++j, ++i)
         assert(*i == j);
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp
@@ -12,6 +12,7 @@
 // void pop_back();
 // void pop_front();
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -49,6 +50,7 @@
     {
         C c = make<C>(size, rng[j]);
         typename C::const_iterator it = c.begin();
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         for (int i = 0; i < size; ++i, ++it)
             assert(*it == i);
     }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp
@@ -14,6 +14,7 @@
 // void pop_back();
 // void pop_front();
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -53,6 +54,7 @@
     {
         C c = make<C>(size, rng[j]);
         typename C::const_iterator it = c.begin();
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c));
         for (int i = 0; i < size; ++i, (void) ++it)
             assert(*it == MoveOnly(i));
     }
@@ -73,6 +75,12 @@
     for (int j = 0; j < N; ++j)
         test<std::deque<MoveOnly, min_allocator<MoveOnly>> >(rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2046, 2047, 2048, 2049, 4094, 4095, 4096};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int j = 0; j < N; ++j)
+        test<std::deque<MoveOnly, safe_allocator<MoveOnly>> >(rng[j]);
+    }
 
   return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp
@@ -10,6 +10,7 @@
 
 // void push_front(const value_type& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -50,6 +51,7 @@
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
     I i = c1.begin();
     assert(*i == x);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     ++i;
     for (int j = 0; static_cast<std::size_t>(j) < c1_osize; ++j, ++i)
         assert(*i == j);
@@ -80,6 +82,13 @@
         for (int j = 0; j < N; ++j)
             testN<std::deque<int, min_allocator<int>> >(rng[i], rng[j]);
     }
+    {
+    int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049};
+    const int N = sizeof(rng)/sizeof(rng[0]);
+    for (int i = 0; i < N; ++i)
+        for (int j = 0; j < N; ++j)
+            testN<std::deque<int, safe_allocator<int>> >(rng[i], rng[j]);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp
@@ -12,6 +12,7 @@
 
 // void push_front(value_type&& v);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include <cstddef>
@@ -54,6 +55,7 @@
     assert(static_cast<std::size_t>(std::distance(c1.begin(), c1.end())) == c1.size());
     I i = c1.begin();
     assert(*i == MoveOnly(x));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
     ++i;
     for (int j = 0; static_cast<std::size_t>(j) < c1_osize; ++j, (void) ++i)
         assert(*i == MoveOnly(j));
@@ -82,7 +84,7 @@
     const int N = sizeof(rng)/sizeof(rng[0]);
     for (int i = 0; i < N; ++i)
         for (int j = 0; j < N; ++j)
-            testN<std::deque<MoveOnly, min_allocator<MoveOnly>> >(rng[i], rng[j]);
+            testN<std::deque<MoveOnly, safe_allocator<MoveOnly>> >(rng[i], rng[j]);
     }
 
   return 0;
diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp
@@ -14,6 +14,7 @@
 //   OutputIterator
 //   copy(InputIterator first, InputIterator last, OutputIterator result);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -55,16 +56,28 @@
     C c2 = make<C>(N);
     assert(std::copy(c1.cbegin(), c1.cend(), c2.begin()) == c2.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy(c2.cbegin(), c2.cend(), c1.begin()) == c1.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy(c1.cbegin(), c1.cend(), RAI(c2.begin())) == RAI(c2.end()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy(c2.cbegin(), c2.cend(), RAI(c1.begin())) == RAI(c1.end()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy(RACI(c1.cbegin()), RACI(c1.cend()), c2.begin()) == c2.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy(ICI(c2.cbegin()), ICI(c2.cend()), c1.begin()) == c1.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp
@@ -14,6 +14,7 @@
 //   OutputIterator
 //   copy_backward(InputIterator first, InputIterator last, OutputIterator result);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -54,16 +55,28 @@
     C c2 = make<C>(N);
     assert(std::copy_backward(c1.cbegin(), c1.cend(), c2.end()) == c2.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy_backward(c2.cbegin(), c2.cend(), c1.end()) == c1.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy_backward(c1.cbegin(), c1.cend(), RAI(c2.end())) == RAI(c2.begin()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy_backward(c2.cbegin(), c2.cend(), RAI(c1.end())) == RAI(c1.begin()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy_backward(RACI(c1.cbegin()), RACI(c1.cend()), c2.end()) == c2.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::copy_backward(RACI(c2.cbegin()), RACI(c2.cend()), c1.end()) == c1.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp
@@ -14,6 +14,7 @@
 //   OutputIterator
 //   move(InputIterator first, InputIterator last, OutputIterator result);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -54,16 +55,28 @@
     C c2 = make<C>(N);
     assert(std::move(c1.cbegin(), c1.cend(), c2.begin()) == c2.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move(c2.cbegin(), c2.cend(), c1.begin()) == c1.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move(c1.cbegin(), c1.cend(), RAI(c2.begin())) == RAI(c2.end()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move(c2.cbegin(), c2.cend(), RAI(c1.begin())) == RAI(c1.end()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move(RACI(c1.cbegin()), RACI(c1.cend()), c2.begin()) == c2.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move(RACI(c2.cbegin()), RACI(c2.cend()), c1.begin()) == c1.end());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp
@@ -14,6 +14,7 @@
 //   OutputIterator
 //   move_backward(InputIterator first, InputIterator last, OutputIterator result);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 
@@ -54,16 +55,28 @@
     C c2 = make<C>(N);
     assert(std::move_backward(c1.cbegin(), c1.cend(), c2.end()) == c2.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move_backward(c2.cbegin(), c2.cend(), c1.end()) == c1.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move_backward(c1.cbegin(), c1.cend(), RAI(c2.end())) == RAI(c2.begin()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move_backward(c2.cbegin(), c2.cend(), RAI(c1.end())) == RAI(c1.begin()));
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move_backward(RACI(c1.cbegin()), RACI(c1.cend()), c2.end()) == c2.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     assert(std::move_backward(RACI(c2.cbegin()), RACI(c2.cend()), c1.end()) == c1.begin());
     assert(c1 == c2);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
 }
 
 int main(int, char**)
diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp
@@ -11,6 +11,7 @@
 // template <class T, class A>
 //   void swap(deque<T, A>& x, deque<T, A>& y);
 
+#include "asan_testing.h"
 #include <deque>
 #include <cassert>
 #include "test_macros.h"
@@ -49,6 +50,10 @@
     swap(c1, c2);
     assert(c1 == c2_save);
     assert(c2 == c1_save);
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1_save));
+    LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2_save));
 }
 
 int main(int, char**)
@@ -72,6 +77,8 @@
         assert(c1.get_allocator().get_id() == 1);
         assert((c2 == std::deque<int, A>(a1, a1+sizeof(a1)/sizeof(a1[0]))));
         assert(c2.get_allocator().get_id() == 2);
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     }
     {
         int a1[] = {1, 3, 7, 9, 10};
@@ -84,6 +91,8 @@
         assert(c1.get_allocator() == A(2));
         assert((c2 == std::deque<int, A>(a1, a1+sizeof(a1)/sizeof(a1[0]))));
         assert(c2.get_allocator() == A(1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     }
 #if TEST_STD_VER >= 11
     {
@@ -105,6 +114,8 @@
         assert(c1.get_allocator() == A());
         assert((c2 == std::deque<int, A>(a1, a1+sizeof(a1)/sizeof(a1[0]))));
         assert(c2.get_allocator() == A());
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1));
+        LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2));
     }
 #endif
 
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
@@ -10,6 +10,7 @@
 #define ASAN_TESTING_H
 
 #include "test_macros.h"
+#include <vector>
 
 #if TEST_HAS_FEATURE(address_sanitizer)
 extern "C" int __sanitizer_verify_contiguous_container
@@ -25,14 +26,34 @@
             c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0;
     return true;
 }
-
 #else
 template <typename T, typename Alloc>
 TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &)
 {
     return true;
 }
-#endif
+#endif // TEST_HAS_FEATURE(address_sanitizer)
 
+#if TEST_HAS_FEATURE(address_sanitizer) && _LIBCPP_CLANG_VER >= 1600
+extern "C" int __sanitizer_verify_double_ended_contiguous_container(
+    const void* beg, const void* con_beg, const void* con_end, const void* end);
+extern "C" bool __sanitizer_is_annotable(const void* address, const unsigned long size);
+#include <deque>
+
+template <class T, class Alloc>
+TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque<T, Alloc>& c) {
+  if (TEST_IS_CONSTANT_EVALUATED)
+    return true;
+  if (std::is_same<Alloc, std::allocator<T> >::value)
+    return c.__verify_asan_annotations();
+  return true;
+}
+#else
+#  include <deque>
+template <class T, class Alloc>
+TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque<T, Alloc>&) {
+  return true;
+}
+#endif
 
 #endif // ASAN_TESTING_H