Recommit rL245802: Cleanup fancy pointer rebinding in list using __rebind_pointer.

Currently we need an #ifdef branch every time we use pointer traits to rebind a pointer because
it is done differently in C++11 and C++03. This patch introduces the __rebind_pointer utility to
clean this up.

Also add a test that list and it's iterators can be instantiated with incomplete element types.


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@245806 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/list b/include/list
index 14201a8..28d5055 100644
--- a/include/list
+++ b/include/list
@@ -191,19 +191,10 @@
 template <class _Tp, class _VoidPtr>
 struct __list_node_base
 {
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-        rebind<__list_node<_Tp, _VoidPtr> > pointer;
-#else
-        rebind<__list_node<_Tp, _VoidPtr> >::other pointer;
-#endif
-
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-        rebind<__list_node_base> __base_pointer;
-#else
-        rebind<__list_node_base>::other __base_pointer;
-#endif
+    typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type
+        pointer;
+    typedef typename __rebind_pointer<_VoidPtr, __list_node_base>::type
+        __base_pointer;
 
     pointer __prev_;
     pointer __next_;
@@ -232,12 +223,8 @@
 template <class _Tp, class _VoidPtr>
 class _LIBCPP_TYPE_VIS_ONLY __list_iterator
 {
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-        rebind<__list_node<_Tp, _VoidPtr> > __node_pointer;
-#else
-        rebind<__list_node<_Tp, _VoidPtr> >::other __node_pointer;
-#endif
+    typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type
+        __node_pointer;
 
     __node_pointer __ptr_;
 
@@ -262,13 +249,7 @@
     typedef bidirectional_iterator_tag       iterator_category;
     typedef _Tp                              value_type;
     typedef value_type&                      reference;
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-            rebind<value_type>
-#else
-            rebind<value_type>::other
-#endif
-                                             pointer;
+    typedef typename __rebind_pointer<_VoidPtr, value_type>::type pointer;
     typedef typename pointer_traits<pointer>::difference_type difference_type;
 
     _LIBCPP_INLINE_VISIBILITY
@@ -365,12 +346,8 @@
 template <class _Tp, class _VoidPtr>
 class _LIBCPP_TYPE_VIS_ONLY __list_const_iterator
 {
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-        rebind<__list_node<_Tp, _VoidPtr> > __node_pointer;
-#else
-        rebind<__list_node<_Tp, _VoidPtr> >::other __node_pointer;
-#endif
+    typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type
+        __node_pointer;
 
     __node_pointer __ptr_;
 
@@ -392,13 +369,7 @@
     typedef bidirectional_iterator_tag       iterator_category;
     typedef _Tp                              value_type;
     typedef const value_type&                reference;
-    typedef typename pointer_traits<_VoidPtr>::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-            rebind<const value_type>
-#else
-            rebind<const value_type>::other
-#endif
-                                             pointer;
+    typedef typename __rebind_pointer<_VoidPtr, const value_type>::type pointer;
     typedef typename pointer_traits<pointer>::difference_type difference_type;
 
     _LIBCPP_INLINE_VISIBILITY
diff --git a/include/memory b/include/memory
index 38ce433..9d214be 100644
--- a/include/memory
+++ b/include/memory
@@ -932,6 +932,15 @@
         {return _VSTD::addressof(__r);}
 };
 
+template <class _From, class _To>
+struct __rebind_pointer {
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+    typedef typename pointer_traits<_From>::template rebind<_To>        type;
+#else
+    typedef typename pointer_traits<_From>::template rebind<_To>::other type;
+#endif
+};
+
 // allocator_traits
 
 namespace __has_pointer_type_imp
diff --git a/test/std/containers/sequences/list/incomplete_type.pass.cpp b/test/std/containers/sequences/list/incomplete_type.pass.cpp
new file mode 100644
index 0000000..adfb4d4
--- /dev/null
+++ b/test/std/containers/sequences/list/incomplete_type.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <list>
+
+// Check that std::list and it's iterators can be instantiated with an incomplete
+// type.
+
+#include <list>
+
+struct A {
+    std::list<A> l;
+    std::list<A>::iterator it;
+    std::list<A>::const_iterator cit;
+    std::list<A>::reverse_iterator rit;
+    std::list<A>::const_reverse_iterator crit;
+};
+
+int main() {
+    A a;
+}