Recommit r276548 - Make pair/tuples assignment operators SFINAE properly.

I think I've solved issues with is_assignable and references to incomplete
types. The updated patch adds tests for this case.

llvm-svn: 276603
diff --git a/libcxx/include/utility b/libcxx/include/utility
index 022a641..456a5f7 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -348,8 +348,23 @@
   // Use the implicitly declared copy constructor in C++03
 #endif
 
+#if !defined(_LIBCPP_CXX03_LANG)
+    typedef typename conditional<
+           is_copy_assignable<_T1>::value
+        && is_copy_assignable<_T2>::value,
+        pair, __nat
+    >::type _CopyAssignT;
+    typedef typename conditional<
+           is_move_assignable<_T1>::value
+        && is_move_assignable<_T2>::value,
+        pair, __nat
+    >::type _MoveAssignT;
+#else
+    typedef pair _CopyAssignT;
+#endif
+
     _LIBCPP_INLINE_VISIBILITY
-    pair& operator=(const pair& __p)
+    pair& operator=(_CopyAssignT const& __p)
         _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
                    is_nothrow_copy_assignable<second_type>::value)
     {
@@ -358,6 +373,18 @@
         return *this;
     }
 
+#ifndef _LIBCPP_CXX03_LANG
+    _LIBCPP_INLINE_VISIBILITY
+    pair& operator=(_MoveAssignT&& __p)
+        _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
+                   is_nothrow_move_assignable<second_type>::value)
+    {
+        first = _VSTD::forward<first_type>(__p.first);
+        second = _VSTD::forward<second_type>(__p.second);
+        return *this;
+    }
+#endif
+
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
     template <class _U1, class _U2,
@@ -377,18 +404,9 @@
             : first(_VSTD::forward<_U1>(__p.first)),
               second(_VSTD::forward<_U2>(__p.second)) {}
 
-    _LIBCPP_INLINE_VISIBILITY
-    pair&
-    operator=(pair&& __p) _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
-                                     is_nothrow_move_assignable<second_type>::value)
-    {
-        first = _VSTD::forward<first_type>(__p.first);
-        second = _VSTD::forward<second_type>(__p.second);
-        return *this;
-    }
+
 
 #ifndef _LIBCPP_HAS_NO_VARIADICS
-
     template<class _Tuple,
              class = typename enable_if<__tuple_convertible<_Tuple, pair>::value>::type>
         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
@@ -411,7 +429,7 @@
             {}
 
     template <class _Tuple,
-              class = typename enable_if<__tuple_assignable<_Tuple, pair>::value>::type>
+              class = typename enable_if<!is_same<typename decay<_Tuple>::type, pair>::value && __tuple_assignable<_Tuple, pair>::value>::type>
         _LIBCPP_INLINE_VISIBILITY
         pair&
         operator=(_Tuple&& __p)