Make tuple's constructor and std::get<>(tuple) constexpr. Final stage of fixing bug #16599. Thanks to Howard for the review and updates.

llvm-svn: 186834
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp
index 37d58b8..d6fbdae 100644
--- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp
+++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/UTypes.pass.cpp
@@ -19,6 +19,17 @@
 
 #include "../MoveOnly.h"
 
+#if _LIBCPP_STD_VER > 11
+
+struct Empty {};
+struct A
+{
+    int id_;
+    explicit constexpr A(int i) : id_(i) {}
+};
+
+#endif
+
 int main()
 {
     {
@@ -52,4 +63,13 @@
         assert(std::get<1>(t) == MoveOnly());
         assert(std::get<2>(t) == MoveOnly());
     }
+#if _LIBCPP_STD_VER > 11
+    {
+        constexpr std::tuple<Empty> t0{Empty()};
+    }
+    {
+        constexpr std::tuple<A, A> t(3, 2);
+        static_assert(std::get<0>(t).id_ == 3, "");
+    }
+#endif
 }
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp
index 188d632..04cb3d5 100644
--- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp
+++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_Types.pass.cpp
@@ -23,11 +23,28 @@
         std::tuple<int> t(2);
         assert(std::get<0>(t) == 2);
     }
+#if _LIBCPP_STD_VER > 11 
+    {
+        constexpr std::tuple<int> t(2);
+        static_assert(std::get<0>(t) == 2, "");
+    }
+    {
+        constexpr std::tuple<int> t;
+        static_assert(std::get<0>(t) == 0, "");
+    }
+#endif
     {
         std::tuple<int, char*> t(2, 0);
         assert(std::get<0>(t) == 2);
         assert(std::get<1>(t) == nullptr);
     }
+#if _LIBCPP_STD_VER > 11 
+    {
+        constexpr std::tuple<int, char*> t(2, nullptr);
+        static_assert(std::get<0>(t) == 2, "");
+        static_assert(std::get<1>(t) == nullptr, "");
+    }
+#endif
     {
         std::tuple<int, char*> t(2, nullptr);
         assert(std::get<0>(t) == 2);
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp
index 54807f1..d40196b 100644
--- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp
+++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/const_pair.pass.cpp
@@ -27,4 +27,16 @@
         assert(std::get<0>(t1) == 2);
         assert(std::get<1>(t1) == short('a'));
     }
+#if _LIBCPP_STD_VER > 11 
+    {
+        typedef std::pair<double, char> P0;
+        typedef std::tuple<int, short> T1;
+        constexpr P0 p0(2.5, 'a');
+        constexpr T1 t1 = p0;
+        static_assert(std::get<0>(t1) != std::get<0>(p0), "");
+        static_assert(std::get<1>(t1) == std::get<1>(p0), "");
+        static_assert(std::get<0>(t1) == 2, "");
+        static_assert(std::get<1>(t1) == short('a'), "");
+    }
+#endif
 }
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp
index 33aed89..bcdb9d9 100644
--- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp
+++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp
@@ -30,6 +30,26 @@
     explicit D(int i) : B(i) {}
 };
 
+#if _LIBCPP_STD_VER > 11 
+
+struct A
+{
+    int id_;
+
+    constexpr A(int i) : id_(i) {}
+    friend constexpr bool operator==(const A& x, const A& y) {return x.id_ == y.id_;}
+};
+
+struct C
+{
+    int id_;
+
+    constexpr explicit C(int i) : id_(i) {}
+    friend constexpr bool operator==(const C& x, const C& y) {return x.id_ == y.id_;}
+};
+
+#endif
+
 int main()
 {
     {
@@ -39,6 +59,22 @@
         T1 t1 = t0;
         assert(std::get<0>(t1) == 2);
     }
+#if _LIBCPP_STD_VER > 11 
+    {
+        typedef std::tuple<double> T0;
+        typedef std::tuple<A> T1;
+        constexpr T0 t0(2.5);
+        constexpr T1 t1 = t0;
+        static_assert(std::get<0>(t1) == 2, "");
+    }
+    {
+        typedef std::tuple<int> T0;
+        typedef std::tuple<C> T1;
+        constexpr T0 t0(2);
+        constexpr T1 t1{t0};
+        static_assert(std::get<0>(t1) == C(2), "");
+    }
+#endif
     {
         typedef std::tuple<double, char> T0;
         typedef std::tuple<int, int> T1;
diff --git a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp
index 7de3ef6..fd953f8 100644
--- a/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp
+++ b/libcxx/test/utilities/tuple/tuple.tuple/tuple.cnstr/copy.pass.cpp
@@ -17,6 +17,8 @@
 #include <string>
 #include <cassert>
 
+struct Empty {};
+
 int main()
 {
     {
@@ -45,4 +47,17 @@
         assert(std::get<1>(t) == 'a');
         assert(std::get<2>(t) == "some text");
     }
+#if _LIBCPP_STD_VER > 11 
+    {
+        typedef std::tuple<int> T;
+        constexpr T t0(2);
+        constexpr T t = t0;
+        static_assert(std::get<0>(t) == 2, "");
+    }
+    {
+        typedef std::tuple<Empty> T;
+        constexpr T t0;
+        constexpr T t = t0;
+    }
+#endif
 }