Allow deque to handle incomplete types.

Allow deque and deque::iterator instantiation with incomplete element
type. This is an ABI breaking change, and it is only enabled if
LIBCXX_ABI_VERSION >= 2 or LIBCXX_ABI_UNSTABLE=ON.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@252350 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/__config b/include/__config
index 1fe96d0..7f6fbf0 100644
--- a/include/__config
+++ b/include/__config
@@ -34,7 +34,11 @@
 #endif
 
 #if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2
+// Change short string represention so that string data starts at offset 0,
+// improving its alignment in some cases.
 #define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
+// Fix deque iterator type in order to support incomplete types.
+#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
 #endif
 
 #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
diff --git a/include/deque b/include/deque
index 87ff8bf..c10bd36 100644
--- a/include/deque
+++ b/include/deque
@@ -261,8 +261,21 @@
               __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l,
               __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r);
 
+template <class _ValueType, class _DiffType>
+struct __deque_block_size {
+  static const _DiffType value = sizeof(_ValueType) < 256 ? 4096 / sizeof(_ValueType) : 16;
+};
+
 template <class _ValueType, class _Pointer, class _Reference, class _MapPointer,
-          class _DiffType, _DiffType _BlockSize>
+          class _DiffType, _DiffType _BS =
+#ifdef _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
+// Keep template parameter to avoid changing all template declarations thoughout
+// this file.
+                               0
+#else
+                               __deque_block_size<_ValueType, _DiffType>::value
+#endif
+          >
 class _LIBCPP_TYPE_VIS_ONLY __deque_iterator
 {
     typedef _MapPointer __map_iterator;
@@ -273,7 +286,7 @@
     __map_iterator __m_iter_;
     pointer        __ptr_;
 
-    static const difference_type __block_size = _BlockSize;
+    static const difference_type __block_size;
 public:
     typedef _ValueType                  value_type;
     typedef random_access_iterator_tag  iterator_category;
@@ -287,7 +300,7 @@
 
     template <class _Pp, class _Rp, class _MP>
     _LIBCPP_INLINE_VISIBILITY
-    __deque_iterator(const __deque_iterator<value_type, _Pp, _Rp, _MP, difference_type, __block_size>& __it,
+    __deque_iterator(const __deque_iterator<value_type, _Pp, _Rp, _MP, difference_type, _BS>& __it,
                 typename enable_if<is_convertible<_Pp, pointer>::value>::type* = 0) _NOEXCEPT
         : __m_iter_(__it.__m_iter_), __ptr_(__it.__ptr_) {}
 
@@ -520,6 +533,12 @@
                   __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r);
 };
 
+template <class _ValueType, class _Pointer, class _Reference, class _MapPointer,
+          class _DiffType, _DiffType _BlockSize>
+const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer,
+                                 _DiffType, _BlockSize>::__block_size =
+    __deque_block_size<_ValueType, _DiffType>::value;
+
 // copy
 
 template <class _RAIter,
@@ -532,10 +551,11 @@
 {
     typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type;
     typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size;
     while (__f != __l)
     {
         pointer __rb = __r.__ptr_;
-        pointer __re = *__r.__m_iter_ + _B2;
+        pointer __re = *__r.__m_iter_ + __block_size;
         difference_type __bs = __re - __rb;
         difference_type __n = __l - __f;
         _RAIter __m = __l;
@@ -560,11 +580,12 @@
 {
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
     difference_type __n = __l - __f;
     while (__n > 0)
     {
         pointer __fb = __f.__ptr_;
-        pointer __fe = *__f.__m_iter_ + _B1;
+        pointer __fe = *__f.__m_iter_ + __block_size;
         difference_type __bs = __fe - __fb;
         if (__bs > __n)
         {
@@ -587,11 +608,12 @@
 {
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
     difference_type __n = __l - __f;
     while (__n > 0)
     {
         pointer __fb = __f.__ptr_;
-        pointer __fe = *__f.__m_iter_ + _B1;
+        pointer __fe = *__f.__m_iter_ + __block_size;
         difference_type __bs = __fe - __fb;
         if (__bs > __n)
         {
@@ -705,10 +727,11 @@
 {
     typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type;
     typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size;
     while (__f != __l)
     {
         pointer __rb = __r.__ptr_;
-        pointer __re = *__r.__m_iter_ + _B2;
+        pointer __re = *__r.__m_iter_ + __block_size;
         difference_type __bs = __re - __rb;
         difference_type __n = __l - __f;
         _RAIter __m = __l;
@@ -733,11 +756,12 @@
 {
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
     difference_type __n = __l - __f;
     while (__n > 0)
     {
         pointer __fb = __f.__ptr_;
-        pointer __fe = *__f.__m_iter_ + _B1;
+        pointer __fe = *__f.__m_iter_ + __block_size;
         difference_type __bs = __fe - __fb;
         if (__bs > __n)
         {
@@ -760,11 +784,12 @@
 {
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
     typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
+    const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
     difference_type __n = __l - __f;
     while (__n > 0)
     {
         pointer __fb = __f.__ptr_;
-        pointer __fe = *__f.__m_iter_ + _B1;
+        pointer __fe = *__f.__m_iter_ + __block_size;
         difference_type __bs = __fe - __fb;
         if (__bs > __n)
         {
@@ -909,7 +934,7 @@
     typedef typename __alloc_traits::pointer         pointer;
     typedef typename __alloc_traits::const_pointer   const_pointer;
 
-    static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
+    static const difference_type __block_size;
 
     typedef typename __rebind_alloc_helper<__alloc_traits, pointer>::type __pointer_allocator;
     typedef allocator_traits<__pointer_allocator>        __map_traits;
@@ -919,9 +944,9 @@
     typedef __split_buffer<pointer, __pointer_allocator> __map;
 
     typedef __deque_iterator<value_type, pointer, reference, __map_pointer,
-                             difference_type, __block_size>    iterator;
+                             difference_type>    iterator;
     typedef __deque_iterator<value_type, const_pointer, const_reference, __map_const_pointer,
-                             difference_type, __block_size>    const_iterator;
+                             difference_type>    const_iterator;
 
     __map __map_;
     size_type __start_;
@@ -997,6 +1022,11 @@
 };
 
 template <class _Tp, class _Allocator>
+const typename __deque_base<_Tp, _Allocator>::difference_type
+    __deque_base<_Tp, _Allocator>::__block_size =
+        __deque_block_size<value_type, difference_type>::value;
+
+template <class _Tp, class _Allocator>
 bool
 __deque_base<_Tp, _Allocator>::__invariants() const
 {
diff --git a/test/libcxx/containers/sequences/deque/incomplete.pass.cpp b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp
new file mode 100644
index 0000000..dbeea5f
--- /dev/null
+++ b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// deque()
+// deque::iterator()
+
+#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
+#include <deque>
+#include <cassert>
+
+struct A {
+  std::deque<A> d;
+  std::deque<A>::iterator it;
+  std::deque<A>::reverse_iterator it2;
+};
+
+int main()
+{
+  A a;
+  assert(a.d.size() == 0);
+  a.it = a.d.begin();
+  a.it2 = a.d.rend();
+}