[libcxx] r287728 - Add <variant> tests but disable them for libc++

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 22 17:02:52 PST 2016


Author: ericwf
Date: Tue Nov 22 19:02:51 2016
New Revision: 287728

URL: http://llvm.org/viewvc/llvm-project?rev=287728&view=rev
Log:
Add <variant> tests but disable them for libc++

Added:
    libcxx/trunk/test/std/utilities/variant/
    libcxx/trunk/test/std/utilities/variant/lit.local.cfg
    libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/
    libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.general/
    libcxx/trunk/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.get/
    libcxx/trunk/test/std/utilities/variant/variant.get/get_if_index.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.get/get_if_type.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.get/get_index.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.get/get_type.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.hash/
    libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.helpers/
    libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.monostate/
    libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/
    libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.monostate/monostate.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.relops/
    libcxx/trunk/test/std/utilities/variant/variant.relops/relops.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.synopsis/
    libcxx/trunk/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant_array.fail.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant_void.fail.cpp
    libcxx/trunk/test/std/utilities/variant/variant.visit/
    libcxx/trunk/test/std/utilities/variant/variant.visit/visit.pass.cpp
    libcxx/trunk/test/support/variant_test_helpers.hpp
Modified:
    libcxx/trunk/test/libcxx/test/config.py
    libcxx/trunk/test/support/archetypes.ipp

Modified: libcxx/trunk/test/libcxx/test/config.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/test/config.py?rev=287728&r1=287727&r2=287728&view=diff
==============================================================================
--- libcxx/trunk/test/libcxx/test/config.py (original)
+++ libcxx/trunk/test/libcxx/test/config.py Tue Nov 22 19:02:51 2016
@@ -233,6 +233,7 @@ class Configuration(object):
             self.lit_config.fatal(
                 'unsupported value for "cxx_stdlib_under_test": %s'
                 % self.cxx_stdlib_under_test)
+        self.config.available_features.add(self.cxx_stdlib_under_test)
         if self.cxx_stdlib_under_test == 'libstdc++':
             self.config.available_features.add('libstdc++')
             # Manually enable the experimental and filesystem tests for libstdc++

Added: libcxx/trunk/test/std/utilities/variant/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/lit.local.cfg?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/lit.local.cfg (added)
+++ libcxx/trunk/test/std/utilities/variant/lit.local.cfg Tue Nov 22 19:02:51 2016
@@ -0,0 +1,5 @@
+
+# FIXME: Libc++ does not yet implement variant but other STLs benefit from
+# having our tests in-tree. This must be removed when <variant> is added.
+if 'libc++' in config.available_features:
+  config.unsupported = True

Added: libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.bad_variant_access/bad_variant_access.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+/*
+
+ class bad_variant_access : public exception {
+public:
+  bad_variant_access() noexcept;
+  virtual const char* what() const noexcept;
+};
+
+*/
+
+#include <cassert>
+#include <exception>
+#include <type_traits>
+#include <variant>
+
+int main() {
+  static_assert(std::is_base_of<std::exception, std::bad_variant_access>::value,
+                "");
+  static_assert(noexcept(std::bad_variant_access{}), "must be noexcept");
+  static_assert(noexcept(std::bad_variant_access{}.what()), "must be noexcept");
+  std::bad_variant_access ex;
+  assert(ex.what());
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.general/nothing_to_do.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+int main() {}

Added: libcxx/trunk/test/std/utilities/variant/variant.get/get_if_index.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.get/get_if_index.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.get/get_if_index.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.get/get_if_index.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,132 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <size_t I, class... Types>
+//  constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
+//   get_if(variant<Types...>* v) noexcept;
+// template <size_t I, class... Types>
+//  constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
+//   get_if(const variant<Types...>* v) noexcept;
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include <cassert>
+#include <memory>
+#include <variant>
+
+void test_const_get_if() {
+  {
+    using V = std::variant<int>;
+    constexpr const V *v = nullptr;
+    static_assert(std::get_if<0>(v) == nullptr, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42);
+    ASSERT_NOEXCEPT(std::get_if<0>(&v));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int const *);
+    static_assert(*std::get_if<0>(&v) == 42, "");
+    static_assert(std::get_if<1>(&v) == nullptr, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), long const *);
+    static_assert(*std::get_if<1>(&v) == 42, "");
+    static_assert(std::get_if<0>(&v) == nullptr, "");
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+#endif
+}
+
+void test_get_if() {
+  {
+    using V = std::variant<int>;
+    V *v = nullptr;
+    assert(std::get_if<0>(v) == nullptr);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42);
+    ASSERT_NOEXCEPT(std::get_if<0>(&v));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *);
+    assert(*std::get_if<0>(&v) == 42);
+    assert(std::get_if<1>(&v) == nullptr);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), long *);
+    assert(*std::get_if<1>(&v) == 42);
+    assert(std::get_if<0>(&v) == nullptr);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *);
+    assert(std::get_if<0>(&v) == &x);
+  }
+#endif
+}
+
+int main() {
+  test_const_get_if();
+  test_get_if();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.get/get_if_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.get/get_if_type.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.get/get_if_type.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.get/get_if_type.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+//  template <class T, class... Types>
+//  constexpr add_pointer_t<T> get_if(variant<Types...>* v) noexcept;
+// template <class T, class... Types>
+//  constexpr add_pointer_t<const T> get_if(const variant<Types...>* v)
+//  noexcept;
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include <cassert>
+#include <variant>
+
+void test_const_get_if() {
+  {
+    using V = std::variant<int>;
+    constexpr const V *v = nullptr;
+    static_assert(std::get_if<int>(v) == nullptr, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42);
+    ASSERT_NOEXCEPT(std::get_if<int>(&v));
+    ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int const *);
+    static_assert(*std::get_if<int>(&v) == 42, "");
+    static_assert(std::get_if<long>(&v) == nullptr, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get_if<long>(&v)), long const *);
+    static_assert(*std::get_if<long>(&v) == 42, "");
+    static_assert(std::get_if<int>(&v) == nullptr, "");
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *);
+    assert(std::get_if<int &>(&v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *);
+    assert(std::get_if<int &&>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *);
+    assert(std::get_if<const int &&>(&v) == &x);
+  }
+#endif
+}
+
+void test_get_if() {
+  {
+    using V = std::variant<int>;
+    V *v = nullptr;
+    assert(std::get_if<int>(v) == nullptr);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42);
+    ASSERT_NOEXCEPT(std::get_if<int>(&v));
+    ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int *);
+    assert(*std::get_if<int>(&v) == 42);
+    assert(std::get_if<long>(&v) == nullptr);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get_if<long>(&v)), long *);
+    assert(*std::get_if<long>(&v) == 42);
+    assert(std::get_if<int>(&v) == nullptr);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *);
+    assert(std::get_if<int &>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get_if<const int &>(&v)), const int *);
+    assert(std::get_if<const int &>(&v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *);
+    assert(std::get_if<int &&>(&v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *);
+    assert(std::get_if<const int &&>(&v) == &x);
+  }
+#endif
+}
+
+int main() {
+  test_const_get_if();
+  test_get_if();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.get/get_index.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.get/get_index.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.get/get_index.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.get/get_index.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,268 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <size_t I, class... Types>
+//   constexpr variant_alternative_t<I, variant<Types...>>&
+//   get(variant<Types...>& v);
+// template <size_t I, class... Types>
+//   constexpr variant_alternative_t<I, variant<Types...>>&&
+//   get(variant<Types...>&& v);
+// template <size_t I, class... Types>
+//   constexpr variant_alternative_t<I, variant<Types...>> const& get(const
+//   variant<Types...>& v);
+// template <size_t I, class... Types>
+//  constexpr variant_alternative_t<I, variant<Types...>> const&& get(const
+//  variant<Types...>&& v);
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include <cassert>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+void test_const_lvalue_get() {
+  {
+    using V = std::variant<int>;
+    constexpr V v(42);
+    // ASSERT_NOT_NOEXCEPT(std::get<0>(v));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int const &);
+    static_assert(std::get<0>(v) == 42, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<1>(v)), long const &);
+    static_assert(std::get<1>(v) == 42, "");
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
+    assert(&std::get<0>(v) == &x);
+  }
+#endif
+}
+
+void test_lvalue_get() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<0>(v));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
+    assert(std::get<0>(v) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<1>(v)), long &);
+    assert(std::get<1>(v) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
+    assert(&std::get<0>(v) == &x);
+  }
+#endif
+}
+
+void test_rvalue_get() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
+    assert(std::get<0>(std::move(v)) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), long &&);
+    assert(std::get<1>(std::move(v)) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
+    assert(&std::get<0>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
+    assert(&std::get<0>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
+    int &&xref = std::get<0>(std::move(v));
+    assert(&xref == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
+    const int &&xref = std::get<0>(std::move(v));
+    assert(&xref == &x);
+  }
+#endif
+}
+
+void test_const_rvalue_get() {
+  {
+    using V = std::variant<int>;
+    const V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
+    assert(std::get<0>(std::move(v)) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    const V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
+    assert(std::get<1>(std::move(v)) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
+    assert(&std::get<0>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
+    assert(&std::get<0>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
+    int &&xref = std::get<0>(std::move(v));
+    assert(&xref == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
+    const int &&xref = std::get<0>(std::move(v));
+    assert(&xref == &x);
+  }
+#endif
+}
+
+template <std::size_t I> using Idx = std::integral_constant<size_t, I>;
+
+void test_throws_for_all_value_categories() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<int, long>;
+  V v0(42);
+  const V &cv0 = v0;
+  assert(v0.index() == 0);
+  V v1(42l);
+  const V &cv1 = v1;
+  assert(v1.index() == 1);
+  std::integral_constant<size_t, 0> zero;
+  std::integral_constant<size_t, 1> one;
+  auto test = [](auto idx, auto &&v) {
+    using Idx = decltype(idx);
+    try {
+      std::get<Idx::value>(std::forward<decltype(v)>(v));
+    } catch (std::bad_variant_access const &) {
+      return true;
+    } catch (...) { /* ... */
+    }
+    return false;
+  };
+  { // lvalue test cases
+    assert(test(one, v0));
+    assert(test(zero, v1));
+  }
+  { // const lvalue test cases
+    assert(test(one, cv0));
+    assert(test(zero, cv1));
+  }
+  { // rvalue test cases
+    assert(test(one, std::move(v0)));
+    assert(test(zero, std::move(v1)));
+  }
+  { // const rvalue test cases
+    assert(test(one, std::move(cv0)));
+    assert(test(zero, std::move(cv1)));
+  }
+#endif
+}
+
+int main() {
+  test_const_lvalue_get();
+  test_lvalue_get();
+  test_rvalue_get();
+  test_const_rvalue_get();
+  test_throws_for_all_value_categories();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.get/get_type.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.get/get_type.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.get/get_type.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.get/get_type.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,266 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class T, class... Types> constexpr T& get(variant<Types...>& v);
+// template <class T, class... Types> constexpr T&& get(variant<Types...>&& v);
+// template <class T, class... Types> constexpr const T& get(const
+// variant<Types...>& v);
+// template <class T, class... Types> constexpr const T&& get(const
+// variant<Types...>&& v);
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include <cassert>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+void test_const_lvalue_get() {
+  {
+    using V = std::variant<int>;
+    constexpr V v(42);
+    // ASSERT_NOT_NOEXCEPT(std::get<int>(v));
+    ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int const &);
+    static_assert(std::get<int>(v) == 42, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<long>(v)), long const &);
+    static_assert(std::get<long>(v) == 42, "");
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &);
+    assert(&std::get<int &>(v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &);
+    assert(&std::get<int &&>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &);
+    assert(&std::get<const int &&>(v) == &x);
+  }
+#endif
+}
+
+void test_lvalue_get() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<int>(v));
+    ASSERT_SAME_TYPE(decltype(std::get<int>(v)), int &);
+    assert(std::get<int>(v) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<long>(v)), long &);
+    assert(std::get<long>(v) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &);
+    assert(&std::get<int &>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<const int &>(v)), const int &);
+    assert(&std::get<const int &>(v) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &);
+    assert(&std::get<int &&>(v) == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &);
+    assert(&std::get<const int &&>(v) == &x);
+  }
+#endif
+}
+
+void test_rvalue_get() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
+    ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), int &&);
+    assert(std::get<int>(std::move(v)) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<long>(std::move(v))), long &&);
+    assert(std::get<long>(std::move(v)) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &);
+    assert(&std::get<int &>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))),
+                     const int &);
+    assert(&std::get<const int &>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&);
+    int &&xref = std::get<int &&>(std::move(v));
+    assert(&xref == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))),
+                     const int &&);
+    const int &&xref = std::get<const int &&>(std::move(v));
+    assert(&xref == &x);
+  }
+#endif
+}
+
+void test_const_rvalue_get() {
+  {
+    using V = std::variant<int>;
+    const V v(42);
+    ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
+    ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), const int &&);
+    assert(std::get<int>(std::move(v)) == 42);
+  }
+  {
+    using V = std::variant<int, long>;
+    const V v(42l);
+    ASSERT_SAME_TYPE(decltype(std::get<long>(std::move(v))), const long &&);
+    assert(std::get<long>(std::move(v)) == 42);
+  }
+// FIXME: Remove these once reference support is reinstated
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &);
+    assert(&std::get<int &>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<const int &>;
+    int x = 42;
+    const V v(x);
+    ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))),
+                     const int &);
+    assert(&std::get<const int &>(std::move(v)) == &x);
+  }
+  {
+    using V = std::variant<int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&);
+    int &&xref = std::get<int &&>(std::move(v));
+    assert(&xref == &x);
+  }
+  {
+    using V = std::variant<const int &&>;
+    int x = 42;
+    const V v(std::move(x));
+    ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))),
+                     const int &&);
+    const int &&xref = std::get<const int &&>(std::move(v));
+    assert(&xref == &x);
+  }
+#endif
+}
+
+template <class Tp> struct identity { using type = Tp; };
+
+void test_throws_for_all_value_categories() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<int, long>;
+  V v0(42);
+  const V &cv0 = v0;
+  assert(v0.index() == 0);
+  V v1(42l);
+  const V &cv1 = v1;
+  assert(v1.index() == 1);
+  identity<int> zero;
+  identity<long> one;
+  auto test = [](auto idx, auto &&v) {
+    using Idx = decltype(idx);
+    try {
+      std::get<typename Idx::type>(std::forward<decltype(v)>(v));
+    } catch (std::bad_variant_access const &) {
+      return true;
+    } catch (...) { /* ... */
+    }
+    return false;
+  };
+  { // lvalue test cases
+    assert(test(one, v0));
+    assert(test(zero, v1));
+  }
+  { // const lvalue test cases
+    assert(test(one, cv0));
+    assert(test(zero, cv1));
+  }
+  { // rvalue test cases
+    assert(test(one, std::move(v0)));
+    assert(test(zero, std::move(v1)));
+  }
+  { // const rvalue test cases
+    assert(test(one, std::move(cv0)));
+    assert(test(zero, std::move(cv1)));
+  }
+#endif
+}
+
+int main() {
+  test_const_lvalue_get();
+  test_lvalue_get();
+  test_rvalue_get();
+  test_const_rvalue_get();
+  test_throws_for_all_value_categories();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.get/holds_alternative.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class T, class... Types>
+// constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
+
+#include <variant>
+
+int main() {
+  {
+    using V = std::variant<int>;
+    constexpr V v;
+    static_assert(std::holds_alternative<int>(v), "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v;
+    static_assert(std::holds_alternative<int>(v), "");
+    static_assert(!std::holds_alternative<long>(v), "");
+  }
+  { // noexcept test
+    using V = std::variant<int>;
+    const V v;
+    static_assert(noexcept(std::holds_alternative<int>(v)), "must be noexcept");
+  }
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class... Types> struct hash<variant<Types...>>;
+// template <> struct hash<monostate>;
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+namespace std {
+template <> struct hash<::MakeEmptyT> {
+  size_t operator()(::MakeEmptyT const &) const {
+    assert(false);
+    return 0;
+  }
+};
+}
+#endif
+
+void test_hash_variant() {
+  {
+    using V = std::variant<int, long, int>;
+    using H = std::hash<V>;
+    const V v(std::in_place_index<0>, 42);
+    const V v_copy = v;
+    V v2(std::in_place_index<0>, 100);
+    const V v3(std::in_place_index<2>, 42);
+    const H h{};
+    assert(h(v) == h(v));
+    assert(h(v) != h(v2));
+    assert(h(v) == h(v_copy));
+    {
+      ASSERT_SAME_TYPE(decltype(h(v)), std::size_t);
+      static_assert(std::is_copy_constructible<H>::value, "");
+    }
+  }
+  {
+    using V = std::variant<std::monostate, int, long, const char *>;
+    using H = std::hash<V>;
+    const char *str = "hello";
+    const V v0;
+    const V v0_other;
+    const V v1(42);
+    const V v1_other(100);
+    V v2(100l);
+    V v2_other(999l);
+    V v3(str);
+    V v3_other("not hello");
+    const H h{};
+    assert(h(v0) == h(v0));
+    assert(h(v0) == h(v0_other));
+    assert(h(v1) == h(v1));
+    assert(h(v1) != h(v1_other));
+    assert(h(v2) == h(v2));
+    assert(h(v2) != h(v2_other));
+    assert(h(v3) == h(v3));
+    assert(h(v3) != h(v3_other));
+    assert(h(v0) != h(v1));
+    assert(h(v0) != h(v2));
+    assert(h(v0) != h(v3));
+    assert(h(v1) != h(v2));
+    assert(h(v1) != h(v3));
+    assert(h(v2) != h(v3));
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    using H = std::hash<V>;
+    V v;
+    makeEmpty(v);
+    V v2;
+    makeEmpty(v2);
+    const H h{};
+    assert(h(v) == h(v2));
+  }
+#endif
+}
+
+void test_hash_monostate() {
+  using H = std::hash<std::monostate>;
+  const H h{};
+  std::monostate m1{};
+  const std::monostate m2{};
+  assert(h(m1) == h(m1));
+  assert(h(m2) == h(m2));
+  assert(h(m1) == h(m2));
+  {
+    ASSERT_SAME_TYPE(decltype(h(m1)), std::size_t);
+    static_assert(std::is_copy_constructible<H>::value, "");
+  }
+}
+
+int main() {
+  test_hash_variant();
+  test_hash_monostate();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <size_t I, class T> struct variant_alternative; // undefined
+// template <size_t I, class T> struct variant_alternative<I, const T>;
+// template <size_t I, class T> struct variant_alternative<I, volatile T>;
+// template <size_t I, class T> struct variant_alternative<I, const volatile T>;
+// template <size_t I, class T>
+//   using variant_alternative_t = typename variant_alternative<I, T>::type;
+//
+// template <size_t I, class... Types>
+//    struct variant_alternative<I, variant<Types...>>;
+
+#include <memory>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+template <class V, size_t I, class E> void test() {
+  static_assert(
+      std::is_same_v<typename std::variant_alternative<I, V>::type, E>, "");
+  static_assert(
+      std::is_same_v<typename std::variant_alternative<I, const V>::type,
+                     const E>,
+      "");
+  static_assert(
+      std::is_same_v<typename std::variant_alternative<I, volatile V>::type,
+                     volatile E>,
+      "");
+  static_assert(
+      std::is_same_v<
+          typename std::variant_alternative<I, const volatile V>::type,
+          const volatile E>,
+      "");
+  static_assert(std::is_same_v<std::variant_alternative_t<I, V>, E>, "");
+  static_assert(std::is_same_v<std::variant_alternative_t<I, const V>, const E>,
+                "");
+  static_assert(
+      std::is_same_v<std::variant_alternative_t<I, volatile V>, volatile E>,
+      "");
+  static_assert(std::is_same_v<std::variant_alternative_t<I, const volatile V>,
+                               const volatile E>,
+                "");
+}
+
+int main() {
+  {
+    using V = std::variant<int, void *, const void *, long double>;
+    test<V, 0, int>();
+    test<V, 1, void *>();
+    test<V, 2, const void *>();
+    test<V, 3, long double>();
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, int &, int const &, int &&, long double>;
+    test<V, 0, int>();
+    test<V, 1, int &>();
+    test<V, 2, int const &>();
+    test<V, 3, int &&>();
+    test<V, 4, long double>();
+  }
+#endif
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.helpers/variant_size.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class T> struct variant_size; // undefined
+// template <class T> struct variant_size<const T>;
+// template <class T> struct variant_size<volatile T>;
+// template <class T> struct variant_size<const volatile T>;
+// template <class T> constexpr size_t variant_size_v
+//     = variant_size<T>::value;
+
+#include <memory>
+#include <type_traits>
+#include <variant>
+
+template <class V, size_t E> void test() {
+  static_assert(std::variant_size<V>::value == E, "");
+  static_assert(std::variant_size<const V>::value == E, "");
+  static_assert(std::variant_size<volatile V>::value == E, "");
+  static_assert(std::variant_size<const volatile V>::value == E, "");
+  static_assert(std::variant_size_v<V> == E, "");
+  static_assert(std::variant_size_v<const V> == E, "");
+  static_assert(std::variant_size_v<volatile V> == E, "");
+  static_assert(std::variant_size_v<const volatile V> == E, "");
+  static_assert(std::is_base_of<std::integral_constant<std::size_t, E>,
+                                std::variant_size<V>>::value,
+                "");
+};
+
+int main() {
+  test<std::variant<>, 0>();
+  test<std::variant<void *>, 1>();
+  test<std::variant<long, long, void *, double>, 4>();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.monostate.relops/relops.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// constexpr bool operator<(monostate, monostate) noexcept { return false; }
+// constexpr bool operator>(monostate, monostate) noexcept { return false; }
+// constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+// constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+// constexpr bool operator==(monostate, monostate) noexcept { return true; }
+// constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+int main() {
+  using M = std::monostate;
+  constexpr M m1{};
+  constexpr M m2{};
+  {
+    static_assert((m1 < m2) == false, "");
+    static_assert(noexcept(m1 < m2), "");
+  }
+  {
+    static_assert((m1 > m2) == false, "");
+    static_assert(noexcept(m1 > m2), "");
+  }
+  {
+    static_assert((m1 <= m2) == true, "");
+    static_assert(noexcept(m1 <= m2), "");
+  }
+  {
+    static_assert((m1 >= m2) == true, "");
+    static_assert(noexcept(m1 >= m2), "");
+  }
+  {
+    static_assert((m1 == m2) == true, "");
+    static_assert(noexcept(m1 == m2), "");
+  }
+  {
+    static_assert((m1 != m2) == false, "");
+    static_assert(noexcept(m1 != m2), "");
+  }
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.monostate/monostate.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.monostate/monostate.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.monostate/monostate.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.monostate/monostate.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// struct monostate {};
+
+#include <type_traits>
+#include <variant>
+
+int main() {
+  using M = std::monostate;
+  static_assert(std::is_trivially_default_constructible<M>::value, "");
+  static_assert(std::is_trivially_copy_constructible<M>::value, "");
+  static_assert(std::is_trivially_copy_assignable<M>::value, "");
+  static_assert(std::is_trivially_destructible<M>::value, "");
+  constexpr M m{};
+  ((void)m);
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.relops/relops.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.relops/relops.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.relops/relops.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.relops/relops.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,227 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types>
+// constexpr bool
+// operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
+//
+// template <class ...Types>
+// constexpr bool
+// operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
+//
+// template <class ...Types>
+// constexpr bool
+// operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
+//
+// template <class ...Types>
+// constexpr bool
+// operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
+//
+// template <class ...Types>
+// constexpr bool
+// operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
+//
+// template <class ...Types>
+// constexpr bool
+// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
+
+#include <cassert>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct MakeEmptyT {
+  MakeEmptyT() = default;
+  MakeEmptyT(MakeEmptyT &&) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
+};
+inline bool operator==(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+inline bool operator!=(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+inline bool operator<(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+inline bool operator<=(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+inline bool operator>(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+inline bool operator>=(MakeEmptyT const &, MakeEmptyT const &) {
+  assert(false);
+  return false;
+}
+
+template <class Variant> void makeEmpty(Variant &v) {
+  Variant v2(std::in_place_type<MakeEmptyT>);
+  try {
+    v = std::move(v2);
+    assert(false);
+  } catch (...) {
+    assert(v.valueless_by_exception());
+  }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+void test_equality() {
+  {
+    using V = std::variant<int, long>;
+    constexpr V v1(42);
+    constexpr V v2(42);
+    static_assert(v1 == v2, "");
+    static_assert(v2 == v1, "");
+    static_assert(!(v1 != v2), "");
+    static_assert(!(v2 != v1), "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v1(42);
+    constexpr V v2(43);
+    static_assert(!(v1 == v2), "");
+    static_assert(!(v2 == v1), "");
+    static_assert(v1 != v2, "");
+    static_assert(v2 != v1, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v1(42);
+    constexpr V v2(42l);
+    static_assert(!(v1 == v2), "");
+    static_assert(!(v2 == v1), "");
+    static_assert(v1 != v2, "");
+    static_assert(v2 != v1, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v1(42l);
+    constexpr V v2(42l);
+    static_assert(v1 == v2, "");
+    static_assert(v2 == v1, "");
+    static_assert(!(v1 != v2), "");
+    static_assert(!(v2 != v1), "");
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    V v2;
+    makeEmpty(v2);
+    assert(!(v1 == v2));
+    assert(!(v2 == v1));
+    assert(v1 != v2);
+    assert(v2 != v1);
+  }
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    makeEmpty(v1);
+    V v2;
+    assert(!(v1 == v2));
+    assert(!(v2 == v1));
+    assert(v1 != v2);
+    assert(v2 != v1);
+  }
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    makeEmpty(v1);
+    V v2;
+    makeEmpty(v2);
+    assert(v1 == v2);
+    assert(v2 == v1);
+    assert(!(v1 != v2));
+    assert(!(v2 != v1));
+  }
+#endif
+}
+
+template <class Var>
+constexpr bool test_less(Var const &l, Var const &r, bool expect_less,
+                         bool expect_greater) {
+  return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
+         ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
+}
+
+void test_relational() {
+  { // same index, same value
+    using V = std::variant<int, long>;
+    constexpr V v1(1);
+    constexpr V v2(1);
+    static_assert(test_less(v1, v2, false, false), "");
+  }
+  { // same index, value < other_value
+    using V = std::variant<int, long>;
+    constexpr V v1(0);
+    constexpr V v2(1);
+    static_assert(test_less(v1, v2, true, false), "");
+  }
+  { // same index, value > other_value
+    using V = std::variant<int, long>;
+    constexpr V v1(1);
+    constexpr V v2(0);
+    static_assert(test_less(v1, v2, false, true), "");
+  }
+  { // LHS.index() < RHS.index()
+    using V = std::variant<int, long>;
+    constexpr V v1(0);
+    constexpr V v2(0l);
+    static_assert(test_less(v1, v2, true, false), "");
+  }
+  { // LHS.index() > RHS.index()
+    using V = std::variant<int, long>;
+    constexpr V v1(0l);
+    constexpr V v2(0);
+    static_assert(test_less(v1, v2, false, true), "");
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  { // LHS.index() < RHS.index(), RHS is empty
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    V v2;
+    makeEmpty(v2);
+    assert(test_less(v1, v2, false, true));
+  }
+  { // LHS.index() > RHS.index(), LHS is empty
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    makeEmpty(v1);
+    V v2;
+    assert(test_less(v1, v2, true, false));
+  }
+  { // LHS.index() == RHS.index(), LHS and RHS are empty
+    using V = std::variant<int, MakeEmptyT>;
+    V v1;
+    makeEmpty(v1);
+    V v2;
+    makeEmpty(v2);
+    assert(test_less(v1, v2, false, false));
+  }
+#endif
+}
+
+int main() {
+  test_equality();
+  test_relational();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.synopsis/variant_npos.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// constexpr size_t variant_npos = -1;
+
+#include <variant>
+
+int main() {
+  static_assert(std::variant_npos == static_cast<std::size_t>(-1), "");
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,232 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class T>
+// variant& operator=(T&&) noexcept(see below);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+namespace MetaHelpers {
+
+struct Dummy {
+  Dummy() = default;
+};
+
+struct ThrowsCtorT {
+  ThrowsCtorT(int) noexcept(false) {}
+  ThrowsCtorT &operator=(int) noexcept { return *this; }
+};
+
+struct ThrowsAssignT {
+  ThrowsAssignT(int) noexcept {}
+  ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
+};
+
+struct NoThrowT {
+  NoThrowT(int) noexcept {}
+  NoThrowT &operator=(int) noexcept { return *this; }
+};
+
+} // namespace MetaHelpers
+
+namespace RuntimeHelpers {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+
+struct ThrowsCtorT {
+  int value;
+  ThrowsCtorT() : value(0) {}
+  ThrowsCtorT(int) noexcept(false) { throw 42; }
+  ThrowsCtorT &operator=(int v) noexcept {
+    value = v;
+    return *this;
+  }
+};
+
+struct ThrowsAssignT {
+  int value;
+  ThrowsAssignT() : value(0) {}
+  ThrowsAssignT(int v) noexcept : value(v) {}
+  ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
+};
+
+struct NoThrowT {
+  int value;
+  NoThrowT() : value(0) {}
+  NoThrowT(int v) noexcept : value(v) {}
+  NoThrowT &operator=(int v) noexcept {
+    value = v;
+    return *this;
+  }
+};
+
+#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
+} // namespace RuntimeHelpers
+
+void test_T_assignment_noexcept() {
+  using namespace MetaHelpers;
+  {
+    using V = std::variant<Dummy, NoThrowT>;
+    static_assert(std::is_nothrow_assignable<V, int>::value, "");
+  }
+  {
+    using V = std::variant<Dummy, ThrowsCtorT>;
+    static_assert(!std::is_nothrow_assignable<V, int>::value, "");
+  }
+  {
+    using V = std::variant<Dummy, ThrowsAssignT>;
+    static_assert(!std::is_nothrow_assignable<V, int>::value, "");
+  }
+}
+
+void test_T_assignment_sfinae() {
+  {
+    using V = std::variant<long, unsigned>;
+    static_assert(!std::is_assignable<V, int>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<std::string, std::string>;
+    static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<std::string, void *>;
+    static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, int &&>;
+    static_assert(!std::is_assignable<V, int>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<int, int const &>;
+    static_assert(!std::is_assignable<V, int>::value, "ambiguous");
+  }
+#endif
+}
+
+void test_T_assignment_basic() {
+  {
+    std::variant<int> v(43);
+    v = 42;
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == 42);
+  }
+  {
+    std::variant<int, long> v(43l);
+    v = 42;
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == 42);
+    v = 43l;
+    assert(v.index() == 1);
+    assert(std::get<1>(v) == 43);
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &, int &&, long>;
+    int x = 42;
+    V v(43l);
+    v = x;
+    assert(v.index() == 0);
+    assert(&std::get<0>(v) == &x);
+    v = std::move(x);
+    assert(v.index() == 1);
+    assert(&std::get<1>(v) == &x);
+    // 'long' is selected by FUN(int const&) since 'int const&' cannot bind
+    // to 'int&'.
+    int const &cx = x;
+    v = cx;
+    assert(v.index() == 2);
+    assert(std::get<2>(v) == 42);
+  }
+#endif
+}
+
+void test_T_assignment_performs_construction() {
+  using namespace RuntimeHelpers;
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<std::string, ThrowsCtorT>;
+    V v(std::in_place_type<std::string>, "hello");
+    try {
+      v = 42;
+    } catch (...) { /* ... */
+    }
+    assert(v.valueless_by_exception());
+  }
+  {
+    using V = std::variant<ThrowsAssignT, std::string>;
+    V v(std::in_place_type<std::string>, "hello");
+    v = 42;
+    assert(v.index() == 0);
+    assert(std::get<0>(v).value == 42);
+  }
+#endif
+}
+
+void test_T_assignment_performs_assignment() {
+  using namespace RuntimeHelpers;
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<ThrowsCtorT>;
+    V v;
+    v = 42;
+    assert(v.index() == 0);
+    assert(std::get<0>(v).value == 42);
+  }
+  {
+    using V = std::variant<ThrowsCtorT, std::string>;
+    V v;
+    v = 42;
+    assert(v.index() == 0);
+    assert(std::get<0>(v).value == 42);
+  }
+  {
+    using V = std::variant<ThrowsAssignT>;
+    V v(100);
+    try {
+      v = 42;
+      assert(false);
+    } catch (...) { /* ... */
+    }
+    assert(v.index() == 0);
+    assert(std::get<0>(v).value == 100);
+  }
+  {
+    using V = std::variant<std::string, ThrowsAssignT>;
+    V v(100);
+    try {
+      v = 42;
+      assert(false);
+    } catch (...) { /* ... */
+    }
+    assert(v.index() == 1);
+    assert(std::get<1>(v).value == 100);
+  }
+#endif
+}
+
+int main() {
+  test_T_assignment_basic();
+  test_T_assignment_performs_construction();
+  test_T_assignment_performs_assignment();
+  test_T_assignment_noexcept();
+  test_T_assignment_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,396 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// variant& operator=(variant const&);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+
+struct NoCopy {
+  NoCopy(NoCopy const &) = delete;
+  NoCopy &operator=(NoCopy const &) = default;
+};
+
+struct NothrowCopy {
+  NothrowCopy(NothrowCopy const &) noexcept = default;
+  NothrowCopy &operator=(NothrowCopy const &) noexcept = default;
+};
+
+struct CopyOnly {
+  CopyOnly(CopyOnly const &) = default;
+  CopyOnly(CopyOnly &&) = delete;
+  CopyOnly &operator=(CopyOnly const &) = default;
+  CopyOnly &operator=(CopyOnly &&) = delete;
+};
+
+struct MoveOnly {
+  MoveOnly(MoveOnly const &) = delete;
+  MoveOnly(MoveOnly &&) = default;
+  MoveOnly &operator=(MoveOnly const &) = default;
+};
+
+struct MoveOnlyNT {
+  MoveOnlyNT(MoveOnlyNT const &) = delete;
+  MoveOnlyNT(MoveOnlyNT &&) {}
+  MoveOnlyNT &operator=(MoveOnlyNT const &) = default;
+};
+
+struct CopyAssign {
+  static int alive;
+  static int copy_construct;
+  static int copy_assign;
+  static int move_construct;
+  static int move_assign;
+  static void reset() {
+    copy_construct = copy_assign = move_construct = move_assign = alive = 0;
+  }
+  CopyAssign(int v) : value(v) { ++alive; }
+  CopyAssign(CopyAssign const &o) : value(o.value) {
+    ++alive;
+    ++copy_construct;
+  }
+  CopyAssign(CopyAssign &&o) : value(o.value) {
+    o.value = -1;
+    ++alive;
+    ++move_construct;
+  }
+  CopyAssign &operator=(CopyAssign const &o) {
+    value = o.value;
+    ++copy_assign;
+    return *this;
+  }
+  CopyAssign &operator=(CopyAssign &&o) {
+    value = o.value;
+    o.value = -1;
+    ++move_assign;
+    return *this;
+  }
+  ~CopyAssign() { --alive; }
+  int value;
+};
+
+int CopyAssign::alive = 0;
+int CopyAssign::copy_construct = 0;
+int CopyAssign::copy_assign = 0;
+int CopyAssign::move_construct = 0;
+int CopyAssign::move_assign = 0;
+
+struct CopyMaybeThrows {
+  CopyMaybeThrows(CopyMaybeThrows const &);
+  CopyMaybeThrows &operator=(CopyMaybeThrows const &);
+};
+struct CopyDoesThrow {
+  CopyDoesThrow(CopyDoesThrow const &) noexcept(false);
+  CopyDoesThrow &operator=(CopyDoesThrow const &) noexcept(false);
+};
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct CopyThrows {
+  CopyThrows() = default;
+  CopyThrows(CopyThrows const &) { throw 42; }
+  CopyThrows &operator=(CopyThrows const &) { throw 42; }
+};
+
+struct MoveThrows {
+  static int alive;
+  MoveThrows() { ++alive; }
+  MoveThrows(MoveThrows const &) { ++alive; }
+  MoveThrows(MoveThrows &&) { throw 42; }
+  MoveThrows &operator=(MoveThrows const &) { return *this; }
+  MoveThrows &operator=(MoveThrows &&) { throw 42; }
+  ~MoveThrows() { --alive; }
+};
+
+int MoveThrows::alive = 0;
+
+struct MakeEmptyT {
+  static int alive;
+  MakeEmptyT() { ++alive; }
+  MakeEmptyT(MakeEmptyT const &) {
+    ++alive;
+    // Don't throw from the copy constructor since variant's assignment
+    // operator performs a copy before committing to the assignment.
+  }
+  MakeEmptyT(MakeEmptyT &&) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
+  ~MakeEmptyT() { --alive; }
+};
+
+int MakeEmptyT::alive = 0;
+
+template <class Variant> void makeEmpty(Variant &v) {
+  Variant v2(std::in_place_type<MakeEmptyT>);
+  try {
+    v = v2;
+    assert(false);
+  } catch (...) {
+    assert(v.valueless_by_exception());
+  }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+void test_copy_assignment_not_noexcept() {
+  {
+    using V = std::variant<CopyMaybeThrows>;
+    static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, CopyDoesThrow>;
+    static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
+  }
+}
+
+void test_copy_assignment_sfinae() {
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_copy_assignable<V>::value, "");
+  }
+  {
+    // variant only provides copy assignment when beth the copy and move
+    // constructors are well formed
+    using V = std::variant<int, CopyOnly>;
+    static_assert(!std::is_copy_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, NoCopy>;
+    static_assert(!std::is_copy_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(!std::is_copy_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnlyNT>;
+    static_assert(!std::is_copy_assignable<V>::value, "");
+  }
+}
+
+void test_copy_assignment_empty_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, long, MET>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+#endif
+}
+
+void test_copy_assignment_non_empty_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET>;
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_index<2>, "hello");
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+#endif
+}
+
+void test_copy_assignment_empty_non_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_index<0>, 42);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 0);
+    assert(std::get<0>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_type<std::string>, "hello");
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+  }
+#endif
+}
+
+void test_copy_assignment_same_index() {
+  {
+    using V = std::variant<int>;
+    V v1(43);
+    V v2(42);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 0);
+    assert(std::get<0>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, long, unsigned>;
+    V v1(43l);
+    V v2(42l);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, CopyAssign, unsigned>;
+    V v1(std::in_place_type<CopyAssign>, 43);
+    V v2(std::in_place_type<CopyAssign>, 42);
+    CopyAssign::reset();
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1).value == 42);
+    assert(CopyAssign::copy_construct == 0);
+    assert(CopyAssign::move_construct == 0);
+    assert(CopyAssign::copy_assign == 1);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_type<MET>);
+    MET &mref = std::get<1>(v1);
+    V v2(std::in_place_type<MET>);
+    try {
+      v1 = v2;
+      assert(false);
+    } catch (...) {
+    }
+    assert(v1.index() == 1);
+    assert(&std::get<1>(v1) == &mref);
+  }
+#endif
+}
+
+void test_copy_assignment_different_index() {
+  {
+    using V = std::variant<int, long, unsigned>;
+    V v1(43);
+    V v2(42l);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, CopyAssign, unsigned>;
+    CopyAssign::reset();
+    V v1(std::in_place_type<unsigned>, 43);
+    V v2(std::in_place_type<CopyAssign>, 42);
+    assert(CopyAssign::copy_construct == 0);
+    assert(CopyAssign::move_construct == 0);
+    assert(CopyAssign::alive == 1);
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1).value == 42);
+    assert(CopyAssign::alive == 2);
+    assert(CopyAssign::copy_construct == 1);
+    assert(CopyAssign::move_construct == 1);
+    assert(CopyAssign::copy_assign == 0);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    // Test that if copy construction throws then original value is
+    // unchanged.
+    using V = std::variant<int, CopyThrows, std::string>;
+    V v1(std::in_place_type<std::string>, "hello");
+    V v2(std::in_place_type<CopyThrows>);
+    try {
+      v1 = v2;
+      assert(false);
+    } catch (...) { /* ... */
+    }
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+  }
+  {
+    // Test that if move construction throws then the variant is left
+    // valueless by exception.
+    using V = std::variant<int, MoveThrows, std::string>;
+    V v1(std::in_place_type<std::string>, "hello");
+    V v2(std::in_place_type<MoveThrows>);
+    assert(MoveThrows::alive == 1);
+    try {
+      v1 = v2;
+      assert(false);
+    } catch (...) { /* ... */
+    }
+    assert(v1.valueless_by_exception());
+    assert(v2.index() == 1);
+    assert(MoveThrows::alive == 1);
+  }
+  {
+    using V = std::variant<int, CopyThrows, std::string>;
+    V v1(std::in_place_type<CopyThrows>);
+    V v2(std::in_place_type<std::string>, "hello");
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+    assert(v2.index() == 2);
+    assert(std::get<2>(v2) == "hello");
+  }
+  {
+    using V = std::variant<int, MoveThrows, std::string>;
+    V v1(std::in_place_type<MoveThrows>);
+    V v2(std::in_place_type<std::string>, "hello");
+    V &vref = (v1 = v2);
+    assert(&vref == &v1);
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+    assert(v2.index() == 2);
+    assert(std::get<2>(v2) == "hello");
+  }
+#endif
+}
+
+int main() {
+  test_copy_assignment_empty_empty();
+  test_copy_assignment_non_empty_empty();
+  test_copy_assignment_empty_non_empty();
+  test_copy_assignment_same_index();
+  test_copy_assignment_different_index();
+  test_copy_assignment_sfinae();
+  test_copy_assignment_not_noexcept();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,319 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// variant& operator=(variant&&) noexcept(see below);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+struct NoCopy {
+  NoCopy(NoCopy const &) = delete;
+  NoCopy &operator=(NoCopy const &) = default;
+};
+
+struct CopyOnly {
+  CopyOnly(CopyOnly const &) = default;
+  CopyOnly(CopyOnly &&) = delete;
+  CopyOnly &operator=(CopyOnly const &) = default;
+  CopyOnly &operator=(CopyOnly &&) = delete;
+};
+
+struct MoveOnly {
+  MoveOnly(MoveOnly const &) = delete;
+  MoveOnly(MoveOnly &&) = default;
+  MoveOnly &operator=(MoveOnly const &) = delete;
+  MoveOnly &operator=(MoveOnly &&) = default;
+};
+
+struct MoveOnlyNT {
+  MoveOnlyNT(MoveOnlyNT const &) = delete;
+  MoveOnlyNT(MoveOnlyNT &&) {}
+  MoveOnlyNT &operator=(MoveOnlyNT const &) = delete;
+  MoveOnlyNT &operator=(MoveOnlyNT &&) = default;
+};
+
+struct MoveOnlyOddNothrow {
+  MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {}
+  MoveOnlyOddNothrow(MoveOnlyOddNothrow const &) = delete;
+  MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default;
+  MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow const &) = delete;
+};
+
+struct MoveAssignOnly {
+  MoveAssignOnly(MoveAssignOnly &&) = delete;
+  MoveAssignOnly &operator=(MoveAssignOnly &&) = default;
+};
+
+struct MoveAssign {
+  static int move_construct;
+  static int move_assign;
+  static void reset() { move_construct = move_assign = 0; }
+  MoveAssign(int v) : value(v) {}
+  MoveAssign(MoveAssign &&o) : value(o.value) {
+    ++move_construct;
+    o.value = -1;
+  }
+  MoveAssign &operator=(MoveAssign &&o) {
+    value = o.value;
+    ++move_assign;
+    o.value = -1;
+    return *this;
+  }
+  int value;
+};
+
+int MoveAssign::move_construct = 0;
+int MoveAssign::move_assign = 0;
+
+void test_move_assignment_noexcept() {
+  {
+    using V = std::variant<int>;
+    static_assert(std::is_nothrow_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<MoveOnly>;
+    static_assert(std::is_nothrow_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_nothrow_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(std::is_nothrow_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<MoveOnlyNT>;
+    static_assert(!std::is_nothrow_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<MoveOnlyOddNothrow>;
+    static_assert(!std::is_nothrow_move_assignable<V>::value, "");
+  }
+}
+
+void test_move_assignment_sfinae() {
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_move_assignable<V>::value, "");
+  }
+  {
+    // variant only provides move assignment when both the move constructor
+    // and move assignment operator are well formed.
+    using V = std::variant<int, CopyOnly>;
+    static_assert(!std::is_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, NoCopy>;
+    static_assert(!std::is_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(std::is_move_assignable<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnlyNT>;
+    static_assert(std::is_move_assignable<V>::value, "");
+  }
+  {
+    // variant only provides move assignment when the types also provide
+    // a move constructor.
+    using V = std::variant<int, MoveAssignOnly>;
+    static_assert(!std::is_move_assignable<V>::value, "");
+  }
+}
+
+void test_move_assignment_empty_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, long, MET>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+#endif
+}
+
+void test_move_assignment_non_empty_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET>;
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_index<2>, "hello");
+    V v2(std::in_place_index<0>);
+    makeEmpty(v2);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+#endif
+}
+
+void test_move_assignment_empty_non_empty() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_index<0>, 42);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 0);
+    assert(std::get<0>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_index<0>);
+    makeEmpty(v1);
+    V v2(std::in_place_type<std::string>, "hello");
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+  }
+#endif
+}
+
+void test_move_assignment_same_index() {
+  {
+    using V = std::variant<int>;
+    V v1(43);
+    V v2(42);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 0);
+    assert(std::get<0>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, long, unsigned>;
+    V v1(43l);
+    V v2(42l);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, MoveAssign, unsigned>;
+    V v1(std::in_place_type<MoveAssign>, 43);
+    V v2(std::in_place_type<MoveAssign>, 42);
+    MoveAssign::reset();
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1).value == 42);
+    assert(MoveAssign::move_construct == 0);
+    assert(MoveAssign::move_assign == 1);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_type<MET>);
+    MET &mref = std::get<1>(v1);
+    V v2(std::in_place_type<MET>);
+    try {
+      v1 = std::move(v2);
+      assert(false);
+    } catch (...) {
+    }
+    assert(v1.index() == 1);
+    assert(&std::get<1>(v1) == &mref);
+  }
+#endif
+}
+
+void test_move_assignment_different_index() {
+  {
+    using V = std::variant<int, long, unsigned>;
+    V v1(43);
+    V v2(42l);
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1) == 42);
+  }
+  {
+    using V = std::variant<int, MoveAssign, unsigned>;
+    V v1(std::in_place_type<unsigned>, 43);
+    V v2(std::in_place_type<MoveAssign>, 42);
+    MoveAssign::reset();
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 1);
+    assert(std::get<1>(v1).value == 42);
+    assert(MoveAssign::move_construct == 1);
+    assert(MoveAssign::move_assign == 0);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using MET = MakeEmptyT;
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_type<int>);
+    V v2(std::in_place_type<MET>);
+    try {
+      v1 = std::move(v2);
+      assert(false);
+    } catch (...) {
+    }
+    assert(v1.valueless_by_exception());
+    assert(v1.index() == std::variant_npos);
+  }
+  {
+    using V = std::variant<int, MET, std::string>;
+    V v1(std::in_place_type<MET>);
+    V v2(std::in_place_type<std::string>, "hello");
+    V &vref = (v1 = std::move(v2));
+    assert(&vref == &v1);
+    assert(v1.index() == 2);
+    assert(std::get<2>(v1) == "hello");
+  }
+#endif
+}
+
+int main() {
+  test_move_assignment_empty_empty();
+  test_move_assignment_non_empty_empty();
+  test_move_assignment_empty_non_empty();
+  test_move_assignment_same_index();
+  test_move_assignment_different_index();
+  test_move_assignment_sfinae();
+  test_move_assignment_noexcept();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class T> constexpr variant(T&&) noexcept(see below);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+struct Dummy {
+  Dummy() = default;
+};
+
+struct ThrowsT {
+  ThrowsT(int) noexcept(false) {}
+};
+
+struct NoThrowT {
+  NoThrowT(int) noexcept(true) {}
+};
+
+void test_T_ctor_noexcept() {
+  {
+    using V = std::variant<Dummy, NoThrowT>;
+    static_assert(std::is_nothrow_constructible<V, int>::value, "");
+  }
+  {
+    using V = std::variant<Dummy, ThrowsT>;
+    static_assert(!std::is_nothrow_constructible<V, int>::value, "");
+  }
+}
+
+void test_T_ctor_sfinae() {
+  {
+    using V = std::variant<long, unsigned>;
+    static_assert(!std::is_constructible<V, int>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<std::string, std::string>;
+    static_assert(!std::is_constructible<V, const char *>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<std::string, void *>;
+    static_assert(!std::is_constructible<V, int>::value,
+                  "no matching constructor");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, int &&>;
+    static_assert(!std::is_constructible<V, int>::value, "ambiguous");
+  }
+  {
+    using V = std::variant<int, int const &>;
+    static_assert(!std::is_constructible<V, int>::value, "ambiguous");
+  }
+#endif
+}
+
+void test_T_ctor_basic() {
+  {
+    constexpr std::variant<int> v(42);
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v) == 42, "");
+  }
+  {
+    constexpr std::variant<int, long> v(42l);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v) == 42, "");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int const &, int &&, long>;
+    static_assert(std::is_convertible<int &, V>::value, "must be implicit");
+    int x = 42;
+    V v(x);
+    assert(v.index() == 0);
+    assert(&std::get<0>(v) == &x);
+  }
+  {
+    using V = std::variant<int const &, int &&, long>;
+    static_assert(std::is_convertible<int, V>::value, "must be implicit");
+    int x = 42;
+    V v(std::move(x));
+    assert(v.index() == 1);
+    assert(&std::get<1>(v) == &x);
+  }
+#endif
+}
+
+int main() {
+  test_T_ctor_basic();
+  test_T_ctor_noexcept();
+  test_T_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// variant(variant const&);
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+
+struct NonT {
+  NonT(int v) : value(v) {}
+  NonT(NonT const &o) : value(o.value) {}
+  int value;
+};
+static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
+
+struct NoCopy {
+  NoCopy(NoCopy const &) = delete;
+};
+
+struct MoveOnly {
+  MoveOnly(MoveOnly const &) = delete;
+  MoveOnly(MoveOnly &&) = default;
+};
+
+struct MoveOnlyNT {
+  MoveOnlyNT(MoveOnlyNT const &) = delete;
+  MoveOnlyNT(MoveOnlyNT &&) {}
+};
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct MakeEmptyT {
+  static int alive;
+  MakeEmptyT() { ++alive; }
+  MakeEmptyT(MakeEmptyT const &) {
+    ++alive;
+    // Don't throw from the copy constructor since variant's assignment
+    // operator performs a copy before committing to the assignment.
+  }
+  MakeEmptyT(MakeEmptyT &&) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
+  ~MakeEmptyT() { --alive; }
+};
+
+int MakeEmptyT::alive = 0;
+
+template <class Variant> void makeEmpty(Variant &v) {
+  Variant v2(std::in_place_type<MakeEmptyT>);
+  try {
+    v = v2;
+    assert(false);
+  } catch (...) {
+    assert(v.valueless_by_exception());
+  }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+void test_copy_ctor_sfinae() {
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_copy_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, NoCopy>;
+    static_assert(!std::is_copy_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(!std::is_copy_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnlyNT>;
+    static_assert(!std::is_copy_constructible<V>::value, "");
+  }
+}
+
+void test_copy_ctor_basic() {
+  {
+    std::variant<int> v(std::in_place_index<0>, 42);
+    std::variant<int> v2 = v;
+    assert(v2.index() == 0);
+    assert(std::get<0>(v2) == 42);
+  }
+  {
+    std::variant<int, long> v(std::in_place_index<1>, 42);
+    std::variant<int, long> v2 = v;
+    assert(v2.index() == 1);
+    assert(std::get<1>(v2) == 42);
+  }
+  {
+    std::variant<NonT> v(std::in_place_index<0>, 42);
+    assert(v.index() == 0);
+    std::variant<NonT> v2(v);
+    assert(v2.index() == 0);
+    assert(std::get<0>(v2).value == 42);
+  }
+  {
+    std::variant<int, NonT> v(std::in_place_index<1>, 42);
+    assert(v.index() == 1);
+    std::variant<int, NonT> v2(v);
+    assert(v2.index() == 1);
+    assert(std::get<1>(v2).value == 42);
+  }
+}
+
+void test_copy_ctor_valueless_by_exception() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<int, MakeEmptyT>;
+  V v1;
+  makeEmpty(v1);
+  V const &cv1 = v1;
+  V v(cv1);
+  assert(v.valueless_by_exception());
+#endif
+}
+
+int main() {
+  test_copy_ctor_basic();
+  test_copy_ctor_valueless_by_exception();
+  test_copy_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// constexpr variant() noexcept(see below);
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+struct NonDefaultConstructible {
+  NonDefaultConstructible(int) {}
+};
+
+struct NotNoexcept {
+  NotNoexcept() noexcept(false) {}
+};
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct DefaultCtorThrows {
+  DefaultCtorThrows() { throw 42; }
+};
+#endif
+
+void test_default_ctor_sfinae() {
+  {
+    using V = std::variant<std::monostate, int>;
+    static_assert(std::is_default_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<NonDefaultConstructible, int>;
+    static_assert(!std::is_default_constructible<V>::value, "");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int &, int>;
+    static_assert(!std::is_default_constructible<V>::value, "");
+  }
+#endif
+}
+
+void test_default_ctor_noexcept() {
+  {
+    using V = std::variant<int>;
+    static_assert(std::is_nothrow_default_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<NotNoexcept>;
+    static_assert(!std::is_nothrow_default_constructible<V>::value, "");
+  }
+}
+
+void test_default_ctor_throws() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<DefaultCtorThrows, int>;
+  try {
+    V v;
+    assert(false);
+  } catch (int const &ex) {
+    assert(ex == 42);
+  } catch (...) {
+    assert(false);
+  }
+#endif
+}
+
+void test_default_ctor_basic() {
+  {
+    std::variant<int> v;
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == 0);
+  }
+  {
+    std::variant<int, long> v;
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == 0);
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v;
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v) == 0, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v;
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v) == 0, "");
+  }
+}
+
+int main() {
+  test_default_ctor_basic();
+  test_default_ctor_sfinae();
+  test_default_ctor_noexcept();
+  test_default_ctor_throws();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <size_t I, class ...Args>
+// constexpr explicit variant(in_place_index_t<I>, Args&&...);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+void test_ctor_sfinae() {
+  {
+    using V = std::variant<int>;
+    static_assert(
+        std::is_constructible<V, std::in_place_index_t<0>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<0>, int>(), "");
+  }
+  {
+    using V = std::variant<int, long, long long>;
+    static_assert(
+        std::is_constructible<V, std::in_place_index_t<1>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<1>, int>(), "");
+  }
+  {
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        std::is_constructible<V, std::in_place_index_t<2>, int *>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<2>, int *>(), "");
+  }
+  { // args not convertible to type
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_index_t<0>, int *>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<0>, int *>(), "");
+  }
+  { // index not in variant
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_index_t<3>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<3>, int>(), "");
+  }
+}
+
+void test_ctor_basic() {
+  {
+    constexpr std::variant<int> v(std::in_place_index<0>, 42);
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v) == 42, "");
+  }
+  {
+    constexpr std::variant<int, long, long> v(std::in_place_index<1>, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v) == 42, "");
+  }
+  {
+    constexpr std::variant<int, const int, long> v(std::in_place_index<1>, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v) == 42, "");
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_index<0>, x);
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == x);
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_index<1>, x);
+    assert(v.index() == 1);
+    assert(std::get<1>(v) == x);
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_index<2>, x);
+    assert(v.index() == 2);
+    assert(std::get<2>(v) == x);
+  }
+}
+
+int main() {
+  test_ctor_basic();
+  test_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <size_t I, class Up, class ...Args>
+// constexpr explicit
+// variant(in_place_index_t<I>, initializer_list<Up>, Args&&...);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+struct InitList {
+  std::size_t size;
+  constexpr InitList(std::initializer_list<int> il) : size(il.size()) {}
+};
+
+struct InitListArg {
+  std::size_t size;
+  int value;
+  constexpr InitListArg(std::initializer_list<int> il, int v)
+      : size(il.size()), value(v) {}
+};
+
+void test_ctor_sfinae() {
+  using IL = std::initializer_list<int>;
+  { // just init list
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(std::is_constructible<V, std::in_place_index_t<0>, IL>::value,
+                  "");
+    static_assert(!test_convertible<V, std::in_place_index_t<0>, IL>(), "");
+  }
+  { // too many arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_index_t<0>, IL, int>::value,
+        "");
+    static_assert(!test_convertible<V, std::in_place_index_t<0>, IL, int>(),
+                  "");
+  }
+  { // too few arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_index_t<1>, IL>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<1>, IL>(), "");
+  }
+  { // init list and arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        std::is_constructible<V, std::in_place_index_t<1>, IL, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<1>, IL, int>(),
+                  "");
+  }
+  { // not constructible from arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_index_t<2>, IL>::value, "");
+    static_assert(!test_convertible<V, std::in_place_index_t<2>, IL>(), "");
+  }
+}
+
+void test_ctor_basic() {
+  {
+    constexpr std::variant<InitList, InitListArg, InitList> v(
+        std::in_place_index<0>, {1, 2, 3});
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v).size == 3, "");
+  }
+  {
+    constexpr std::variant<InitList, InitListArg, InitList> v(
+        std::in_place_index<2>, {1, 2, 3});
+    static_assert(v.index() == 2, "");
+    static_assert(std::get<2>(v).size == 3, "");
+  }
+  {
+    constexpr std::variant<InitList, InitListArg, InitListArg> v(
+        std::in_place_index<1>, {1, 2, 3, 4}, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v).size == 4, "");
+    static_assert(std::get<1>(v).value == 42, "");
+  }
+}
+
+int main() {
+  test_ctor_basic();
+  test_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class Tp, class ...Args>
+// constexpr explicit variant(in_place_type_t<Tp>, Args&&...);
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+void test_ctor_sfinae() {
+  {
+    using V = std::variant<int>;
+    static_assert(
+        std::is_constructible<V, std::in_place_type_t<int>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), "");
+  }
+  {
+    using V = std::variant<int, long, long long>;
+    static_assert(
+        std::is_constructible<V, std::in_place_type_t<long>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_type_t<long>, int>(), "");
+  }
+  {
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        std::is_constructible<V, std::in_place_type_t<int *>, int *>::value,
+        "");
+    static_assert(!test_convertible<V, std::in_place_type_t<int *>, int *>(),
+                  "");
+  }
+  { // duplicate type
+    using V = std::variant<int, long, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_type_t<int>, int>::value, "");
+    static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), "");
+  }
+  { // args not convertible to type
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_type_t<int>, int *>::value, "");
+    static_assert(!test_convertible<V, std::in_place_type_t<int>, int *>(), "");
+  }
+  { // type not in variant
+    using V = std::variant<int, long, int *>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_type_t<long long>, int>::value,
+        "");
+    static_assert(!test_convertible<V, std::in_place_type_t<long long>, int>(),
+                  "");
+  }
+}
+
+void test_ctor_basic() {
+  {
+    constexpr std::variant<int> v(std::in_place_type<int>, 42);
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v) == 42, "");
+  }
+  {
+    constexpr std::variant<int, long> v(std::in_place_type<long>, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v) == 42, "");
+  }
+  {
+    constexpr std::variant<int, const int, long> v(
+        std::in_place_type<const int>, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v) == 42, "");
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_type<const int>, x);
+    assert(v.index() == 0);
+    assert(std::get<0>(v) == x);
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_type<volatile int>, x);
+    assert(v.index() == 1);
+    assert(std::get<1>(v) == x);
+  }
+  {
+    using V = std::variant<const int, volatile int, int>;
+    int x = 42;
+    V v(std::in_place_type<int>, x);
+    assert(v.index() == 2);
+    assert(std::get<2>(v) == x);
+  }
+}
+
+int main() {
+  test_ctor_basic();
+  test_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,110 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class Tp, class Up, class ...Args>
+// constexpr explicit
+// variant(in_place_type_t<Tp>, initializer_list<Up>, Args&&...);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+struct InitList {
+  std::size_t size;
+  constexpr InitList(std::initializer_list<int> il) : size(il.size()) {}
+};
+
+struct InitListArg {
+  std::size_t size;
+  int value;
+  constexpr InitListArg(std::initializer_list<int> il, int v)
+      : size(il.size()), value(v) {}
+};
+
+void test_ctor_sfinae() {
+  using IL = std::initializer_list<int>;
+  { // just init list
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        std::is_constructible<V, std::in_place_type_t<InitList>, IL>::value,
+        "");
+    static_assert(!test_convertible<V, std::in_place_type_t<InitList>, IL>(),
+                  "");
+  }
+  { // too many arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(!std::is_constructible<V, std::in_place_type_t<InitList>, IL,
+                                         int>::value,
+                  "");
+    static_assert(
+        !test_convertible<V, std::in_place_type_t<InitList>, IL, int>(), "");
+  }
+  { // too few arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_type_t<InitListArg>, IL>::value,
+        "");
+    static_assert(!test_convertible<V, std::in_place_type_t<InitListArg>, IL>(),
+                  "");
+  }
+  { // init list and arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(std::is_constructible<V, std::in_place_type_t<InitListArg>,
+                                        IL, int>::value,
+                  "");
+    static_assert(
+        !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), "");
+  }
+  { // not constructible from arguments
+    using V = std::variant<InitList, InitListArg, int>;
+    static_assert(
+        !std::is_constructible<V, std::in_place_type_t<int>, IL>::value, "");
+    static_assert(!test_convertible<V, std::in_place_type_t<int>, IL>(), "");
+  }
+  { // duplicate types in variant
+    using V = std::variant<InitListArg, InitListArg, int>;
+    static_assert(!std::is_constructible<V, std::in_place_type_t<InitListArg>,
+                                         IL, int>::value,
+                  "");
+    static_assert(
+        !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), "");
+  }
+}
+
+void test_ctor_basic() {
+  {
+    constexpr std::variant<InitList, InitListArg> v(
+        std::in_place_type<InitList>, {1, 2, 3});
+    static_assert(v.index() == 0, "");
+    static_assert(std::get<0>(v).size == 3, "");
+  }
+  {
+    constexpr std::variant<InitList, InitListArg> v(
+        std::in_place_type<InitListArg>, {1, 2, 3, 4}, 42);
+    static_assert(v.index() == 1, "");
+    static_assert(std::get<1>(v).size == 4, "");
+    static_assert(std::get<1>(v).value == 42, "");
+  }
+}
+
+int main() {
+  test_ctor_basic();
+  test_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// variant(variant&&) noexcept(see below);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+
+struct ThrowsMove {
+  ThrowsMove(ThrowsMove &&) noexcept(false) {}
+};
+
+struct NoCopy {
+  NoCopy(NoCopy const &) = delete;
+};
+
+struct MoveOnly {
+  int value;
+  MoveOnly(int v) : value(v) {}
+  MoveOnly(MoveOnly const &) = delete;
+  MoveOnly(MoveOnly &&) = default;
+};
+
+struct MoveOnlyNT {
+  int value;
+  MoveOnlyNT(int v) : value(v) {}
+  MoveOnlyNT(MoveOnlyNT const &) = delete;
+  MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; }
+};
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct MakeEmptyT {
+  static int alive;
+  MakeEmptyT() { ++alive; }
+  MakeEmptyT(MakeEmptyT const &) {
+    ++alive;
+    // Don't throw from the copy constructor since variant's assignment
+    // operator performs a copy before committing to the assignment.
+  }
+  MakeEmptyT(MakeEmptyT &&) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
+  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
+  ~MakeEmptyT() { --alive; }
+};
+
+int MakeEmptyT::alive = 0;
+
+template <class Variant> void makeEmpty(Variant &v) {
+  Variant v2(std::in_place_type<MakeEmptyT>);
+  try {
+    v = v2;
+    assert(false);
+  } catch (...) {
+    assert(v.valueless_by_exception());
+  }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+void test_move_noexcept() {
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_nothrow_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(std::is_nothrow_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnlyNT>;
+    static_assert(!std::is_nothrow_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, ThrowsMove>;
+    static_assert(!std::is_nothrow_move_constructible<V>::value, "");
+  }
+}
+
+void test_move_ctor_sfinae() {
+  {
+    using V = std::variant<int, long>;
+    static_assert(std::is_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnly>;
+    static_assert(std::is_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, MoveOnlyNT>;
+    static_assert(std::is_move_constructible<V>::value, "");
+  }
+  {
+    using V = std::variant<int, NoCopy>;
+    static_assert(!std::is_move_constructible<V>::value, "");
+  }
+}
+
+void test_move_ctor_basic() {
+  {
+    std::variant<int> v(std::in_place_index<0>, 42);
+    std::variant<int> v2 = std::move(v);
+    assert(v2.index() == 0);
+    assert(std::get<0>(v2) == 42);
+  }
+  {
+    std::variant<int, long> v(std::in_place_index<1>, 42);
+    std::variant<int, long> v2 = std::move(v);
+    assert(v2.index() == 1);
+    assert(std::get<1>(v2) == 42);
+  }
+  {
+    std::variant<MoveOnly> v(std::in_place_index<0>, 42);
+    assert(v.index() == 0);
+    std::variant<MoveOnly> v2(std::move(v));
+    assert(v2.index() == 0);
+    assert(std::get<0>(v2).value == 42);
+  }
+  {
+    std::variant<int, MoveOnly> v(std::in_place_index<1>, 42);
+    assert(v.index() == 1);
+    std::variant<int, MoveOnly> v2(std::move(v));
+    assert(v2.index() == 1);
+    assert(std::get<1>(v2).value == 42);
+  }
+  {
+    std::variant<MoveOnlyNT> v(std::in_place_index<0>, 42);
+    assert(v.index() == 0);
+    std::variant<MoveOnlyNT> v2(std::move(v));
+    assert(v2.index() == 0);
+    assert(std::get<0>(v).value == -1);
+    assert(std::get<0>(v2).value == 42);
+  }
+  {
+    std::variant<int, MoveOnlyNT> v(std::in_place_index<1>, 42);
+    assert(v.index() == 1);
+    std::variant<int, MoveOnlyNT> v2(std::move(v));
+    assert(v2.index() == 1);
+    assert(std::get<1>(v).value == -1);
+    assert(std::get<1>(v2).value == 42);
+  }
+}
+
+void test_move_ctor_valueless_by_exception() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<int, MakeEmptyT>;
+  V v1;
+  makeEmpty(v1);
+  V v(std::move(v1));
+  assert(v.valueless_by_exception());
+#endif
+}
+
+int main() {
+  test_move_ctor_basic();
+  test_move_ctor_valueless_by_exception();
+  test_move_noexcept();
+  test_move_ctor_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.dtor/dtor.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// ~variant();
+
+#include <cassert>
+#include <type_traits>
+#include <variant>
+
+#include "test_macros.h"
+
+struct NonTDtor {
+  static int count;
+  NonTDtor() = default;
+  ~NonTDtor() { ++count; }
+};
+int NonTDtor::count = 0;
+static_assert(!std::is_trivially_destructible<NonTDtor>::value, "");
+
+struct NonTDtor1 {
+  static int count;
+  NonTDtor1() = default;
+  ~NonTDtor1() { ++count; }
+};
+int NonTDtor1::count = 0;
+static_assert(!std::is_trivially_destructible<NonTDtor1>::value, "");
+
+struct TDtor {
+  TDtor(TDtor const &) {} // non-trivial copy
+  ~TDtor() = default;
+};
+static_assert(!std::is_trivially_copy_constructible<TDtor>::value, "");
+static_assert(std::is_trivially_destructible<TDtor>::value, "");
+
+int main() {
+  {
+    using V = std::variant<int, long, TDtor>;
+    static_assert(std::is_trivially_destructible<V>::value, "");
+  }
+  {
+    using V = std::variant<NonTDtor, int, NonTDtor1>;
+    static_assert(!std::is_trivially_destructible<V>::value, "");
+    {
+      V v(std::in_place_index<0>);
+      assert(NonTDtor::count == 0);
+      assert(NonTDtor1::count == 0);
+    }
+    assert(NonTDtor::count == 1);
+    assert(NonTDtor1::count == 0);
+    NonTDtor::count = 0;
+    { V v(std::in_place_index<1>); }
+    assert(NonTDtor::count == 0);
+    assert(NonTDtor1::count == 0);
+    {
+      V v(std::in_place_index<2>);
+      assert(NonTDtor::count == 0);
+      assert(NonTDtor1::count == 0);
+    }
+    assert(NonTDtor::count == 0);
+    assert(NonTDtor1::count == 1);
+  }
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <size_t I, class ...Args> void emplace(Args&&... args);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_convertible.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+template <class Var, size_t I, class... Args>
+constexpr auto test_emplace_exists_imp(int) -> decltype(
+    std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) {
+  return true;
+}
+
+template <class, size_t, class...>
+constexpr auto test_emplace_exists_imp(long) -> bool {
+  return false;
+}
+
+template <class Var, size_t I, class... Args> constexpr bool emplace_exists() {
+  return test_emplace_exists_imp<Var, I, Args...>(0);
+}
+
+void test_emplace_sfinae() {
+  {
+    using V = std::variant<int, void *, const void *, TestTypes::NoCtors>;
+    static_assert(emplace_exists<V, 0>(), "");
+    static_assert(emplace_exists<V, 0, int>(), "");
+    static_assert(!emplace_exists<V, 0, decltype(nullptr)>(),
+                  "cannot construct");
+    static_assert(emplace_exists<V, 1, decltype(nullptr)>(), "");
+    static_assert(emplace_exists<V, 1, int *>(), "");
+    static_assert(!emplace_exists<V, 1, const int *>(), "");
+    static_assert(!emplace_exists<V, 1, int>(), "cannot construct");
+    static_assert(emplace_exists<V, 2, const int *>(), "");
+    static_assert(emplace_exists<V, 2, int *>(), "");
+    static_assert(!emplace_exists<V, 3>(), "cannot construct");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, int &, int const &, int &&, TestTypes::NoCtors>;
+    static_assert(emplace_exists<V, 0>(), "");
+    static_assert(emplace_exists<V, 0, int>(), "");
+    static_assert(emplace_exists<V, 0, long long>(), "");
+    static_assert(!emplace_exists<V, 0, int, int>(), "too many args");
+    static_assert(emplace_exists<V, 1, int &>(), "");
+    static_assert(!emplace_exists<V, 1>(), "cannot default construct ref");
+    static_assert(!emplace_exists<V, 1, int const &>(), "cannot bind ref");
+    static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref");
+    static_assert(emplace_exists<V, 2, int &>(), "");
+    static_assert(emplace_exists<V, 2, const int &>(), "");
+    static_assert(emplace_exists<V, 2, int &&>(), "");
+    static_assert(!emplace_exists<V, 2, void *>(),
+                  "not constructible from void*");
+    static_assert(emplace_exists<V, 3, int>(), "");
+    static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref");
+    static_assert(!emplace_exists<V, 3, int const &>(), "cannot bind ref");
+    static_assert(!emplace_exists<V, 3, int const &&>(), "cannot bind ref");
+    static_assert(!emplace_exists<V, 4>(), "no ctors");
+  }
+#endif
+}
+
+void test_basic() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    v.emplace<0>();
+    assert(std::get<0>(v) == 0);
+    v.emplace<0>(42);
+    assert(std::get<0>(v) == 42);
+  }
+  {
+    using V =
+        std::variant<int, long, const void *, TestTypes::NoCtors, std::string>;
+    const int x = 100;
+    V v(std::in_place_index<0>, -1);
+    // default emplace a value
+    v.emplace<1>();
+    assert(std::get<1>(v) == 0);
+    v.emplace<2>(&x);
+    assert(std::get<2>(v) == &x);
+    // emplace with multiple args
+    v.emplace<4>(3, 'a');
+    assert(std::get<4>(v) == "aaa");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, long, int const &, int &&, TestTypes::NoCtors,
+                           std::string>;
+    const int x = 100;
+    int y = 42;
+    int z = 43;
+    V v(std::in_place_index<0>, -1);
+    // default emplace a value
+    v.emplace<1>();
+    assert(std::get<1>(v) == 0);
+    // emplace a reference
+    v.emplace<2>(x);
+    assert(&std::get<2>(v) == &x);
+    // emplace an rvalue reference
+    v.emplace<3>(std::move(y));
+    assert(&std::get<3>(v) == &y);
+    // re-emplace a new reference over the active member
+    v.emplace<3>(std::move(z));
+    assert(&std::get<3>(v) == &z);
+    // emplace with multiple args
+    v.emplace<5>(3, 'a');
+    assert(std::get<5>(v) == "aaa");
+  }
+#endif
+}
+
+int main() {
+  test_basic();
+  test_emplace_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_init_list_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <size_t I, class U, class ...Args>
+// void emplace(initializer_list<U> il,Args&&... args);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+struct InitList {
+  std::size_t size;
+  constexpr InitList(std::initializer_list<int> il) : size(il.size()) {}
+};
+
+struct InitListArg {
+  std::size_t size;
+  int value;
+  constexpr InitListArg(std::initializer_list<int> il, int v)
+      : size(il.size()), value(v) {}
+};
+
+template <class Var, size_t I, class... Args>
+constexpr auto test_emplace_exists_imp(int) -> decltype(
+    std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) {
+  return true;
+}
+
+template <class, size_t, class...>
+constexpr auto test_emplace_exists_imp(long) -> bool {
+  return false;
+}
+
+template <class Var, size_t I, class... Args> constexpr bool emplace_exists() {
+  return test_emplace_exists_imp<Var, I, Args...>(0);
+}
+
+void test_emplace_sfinae() {
+  using V =
+      std::variant<int, TestTypes::NoCtors, InitList, InitListArg, long, long>;
+  using IL = std::initializer_list<int>;
+  static_assert(!emplace_exists<V, 1, IL>(), "no such constructor");
+  static_assert(emplace_exists<V, 2, IL>(), "");
+  static_assert(!emplace_exists<V, 2, int>(), "args don't match");
+  static_assert(!emplace_exists<V, 2, IL, int>(), "too many args");
+  static_assert(emplace_exists<V, 3, IL, int>(), "");
+  static_assert(!emplace_exists<V, 3, int>(), "args don't match");
+  static_assert(!emplace_exists<V, 3, IL>(), "too few args");
+  static_assert(!emplace_exists<V, 3, IL, int, int>(), "too many args");
+}
+
+void test_basic() {
+  using V = std::variant<int, InitList, InitListArg, TestTypes::NoCtors>;
+  V v;
+  v.emplace<1>({1, 2, 3});
+  assert(std::get<1>(v).size == 3);
+  v.emplace<2>({1, 2, 3, 4}, 42);
+  assert(std::get<2>(v).size == 4);
+  assert(std::get<2>(v).value == 42);
+  v.emplace<1>({1});
+  assert(std::get<1>(v).size == 1);
+}
+
+int main() {
+  test_basic();
+  test_emplace_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,138 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class T, class ...Args> void emplace(Args&&... args);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_convertible.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+template <class Var, class T, class... Args>
+constexpr auto test_emplace_exists_imp(int) -> decltype(
+    std::declval<Var>().template emplace<T>(std::declval<Args>()...), true) {
+  return true;
+}
+
+template <class, class, class...>
+constexpr auto test_emplace_exists_imp(long) -> bool {
+  return false;
+}
+
+template <class... Args> constexpr bool emplace_exists() {
+  return test_emplace_exists_imp<Args...>(0);
+}
+
+void test_emplace_sfinae() {
+  {
+    using V = std::variant<int, void *, const void *, TestTypes::NoCtors>;
+    static_assert(emplace_exists<V, int>(), "");
+    static_assert(emplace_exists<V, int, int>(), "");
+    static_assert(!emplace_exists<V, int, decltype(nullptr)>(),
+                  "cannot construct");
+    static_assert(emplace_exists<V, void *, decltype(nullptr)>(), "");
+    static_assert(!emplace_exists<V, void *, int>(), "cannot construct");
+    static_assert(emplace_exists<V, void *, int *>(), "");
+    static_assert(!emplace_exists<V, void *, const int *>(), "");
+    static_assert(emplace_exists<V, void const *, const int *>(), "");
+    static_assert(emplace_exists<V, void const *, int *>(), "");
+    static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  using V = std::variant<int, int &, int const &, int &&, long, long,
+                         TestTypes::NoCtors>;
+  static_assert(emplace_exists<V, int>(), "");
+  static_assert(emplace_exists<V, int, int>(), "");
+  static_assert(emplace_exists<V, int, long long>(), "");
+  static_assert(!emplace_exists<V, int, int, int>(), "too many args");
+  static_assert(emplace_exists<V, int &, int &>(), "");
+  static_assert(!emplace_exists<V, int &>(), "cannot default construct ref");
+  static_assert(!emplace_exists<V, int &, int const &>(), "cannot bind ref");
+  static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref");
+  static_assert(emplace_exists<V, int const &, int &>(), "");
+  static_assert(emplace_exists<V, int const &, const int &>(), "");
+  static_assert(emplace_exists<V, int const &, int &&>(), "");
+  static_assert(!emplace_exists<V, int const &, void *>(),
+                "not constructible from void*");
+  static_assert(emplace_exists<V, int &&, int>(), "");
+  static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref");
+  static_assert(!emplace_exists<V, int &&, int const &>(), "cannot bind ref");
+  static_assert(!emplace_exists<V, int &&, int const &&>(), "cannot bind ref");
+  static_assert(!emplace_exists<V, long, long>(), "ambiguous");
+  static_assert(!emplace_exists<V, TestTypes::NoCtors>(),
+                "cannot construct void");
+#endif
+}
+
+void test_basic() {
+  {
+    using V = std::variant<int>;
+    V v(42);
+    v.emplace<int>();
+    assert(std::get<0>(v) == 0);
+    v.emplace<int>(42);
+    assert(std::get<0>(v) == 42);
+  }
+  {
+    using V =
+        std::variant<int, long, const void *, TestTypes::NoCtors, std::string>;
+    const int x = 100;
+    V v(std::in_place_type<int>, -1);
+    // default emplace a value
+    v.emplace<long>();
+    assert(std::get<1>(v) == 0);
+    v.emplace<const void *>(&x);
+    assert(std::get<2>(v) == &x);
+    // emplace with multiple args
+    v.emplace<std::string>(3, 'a');
+    assert(std::get<4>(v) == "aaa");
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  {
+    using V = std::variant<int, long, int const &, int &&, TestTypes::NoCtors,
+                           std::string>;
+    const int x = 100;
+    int y = 42;
+    int z = 43;
+    V v(std::in_place_index<0>, -1);
+    // default emplace a value
+    v.emplace<long>();
+    assert(std::get<long>(v) == 0);
+    // emplace a reference
+    v.emplace<int const &>(x);
+    assert(&std::get<int const &>(v) == &x);
+    // emplace an rvalue reference
+    v.emplace<int &&>(std::move(y));
+    assert(&std::get<int &&>(v) == &y);
+    // re-emplace a new reference over the active member
+    v.emplace<int &&>(std::move(z));
+    assert(&std::get<int &&>(v) == &z);
+    // emplace with multiple args
+    v.emplace<std::string>(3, 'a');
+    assert(std::get<std::string>(v) == "aaa");
+  }
+#endif
+}
+
+int main() {
+  test_basic();
+  test_emplace_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_init_list_args.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// template <class T, class U, class ...Args>
+// void emplace(initializer_list<U> il,Args&&... args);
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_convertible.hpp"
+#include "test_macros.h"
+
+struct InitList {
+  std::size_t size;
+  constexpr InitList(std::initializer_list<int> il) : size(il.size()) {}
+};
+
+struct InitListArg {
+  std::size_t size;
+  int value;
+  constexpr InitListArg(std::initializer_list<int> il, int v)
+      : size(il.size()), value(v) {}
+};
+
+template <class Var, class T, class... Args>
+constexpr auto test_emplace_exists_imp(int) -> decltype(
+    std::declval<Var>().template emplace<T>(std::declval<Args>()...), true) {
+  return true;
+}
+
+template <class, class, class...>
+constexpr auto test_emplace_exists_imp(long) -> bool {
+  return false;
+}
+
+template <class... Args> constexpr bool emplace_exists() {
+  return test_emplace_exists_imp<Args...>(0);
+}
+
+void test_emplace_sfinae() {
+  using V =
+      std::variant<int, TestTypes::NoCtors, InitList, InitListArg, long, long>;
+  using IL = std::initializer_list<int>;
+  static_assert(emplace_exists<V, InitList, IL>(), "");
+  static_assert(!emplace_exists<V, InitList, int>(), "args don't match");
+  static_assert(!emplace_exists<V, InitList, IL, int>(), "too many args");
+  static_assert(emplace_exists<V, InitListArg, IL, int>(), "");
+  static_assert(!emplace_exists<V, InitListArg, int>(), "args don't match");
+  static_assert(!emplace_exists<V, InitListArg, IL>(), "too few args");
+  static_assert(!emplace_exists<V, InitListArg, IL, int, int>(),
+                "too many args");
+}
+
+void test_basic() {
+  using V = std::variant<int, InitList, InitListArg, TestTypes::NoCtors>;
+  V v;
+  v.emplace<InitList>({1, 2, 3});
+  assert(std::get<InitList>(v).size == 3);
+  v.emplace<InitListArg>({1, 2, 3, 4}, 42);
+  assert(std::get<InitListArg>(v).size == 4);
+  assert(std::get<InitListArg>(v).value == 42);
+  v.emplace<InitList>({1});
+  assert(std::get<InitList>(v).size == 1);
+}
+
+int main() {
+  test_basic();
+  test_emplace_sfinae();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/index.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// constexpr size_t index() const noexcept;
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+int main() {
+  {
+    using V = std::variant<int, ConstexprTestTypes::NoCtors>;
+    constexpr V v;
+    static_assert(v.index() == 0, "");
+  }
+  {
+    using V = std::variant<int, long>;
+    constexpr V v(std::in_place_index<1>);
+    static_assert(v.index() == 1, "");
+  }
+  {
+    using V = std::variant<int, std::string>;
+    V v("abc");
+    assert(v.index() == 1);
+    v = 42;
+    assert(v.index() == 0);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v;
+    assert(v.index() == 0);
+    makeEmpty(v);
+    assert(v.index() == std::variant_npos);
+  }
+#endif
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.status/valueless_by_exception.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// constexpr bool valueless_by_exception() const noexcept;
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "archetypes.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+int main() {
+  {
+    using V = std::variant<int, ConstexprTestTypes::NoCtors>;
+    constexpr V v;
+    static_assert(!v.valueless_by_exception(), "");
+  }
+  {
+    using V = std::variant<int, long, std::string>;
+    const V v("abc");
+    assert(!v.valueless_by_exception());
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v;
+    assert(!v.valueless_by_exception());
+    makeEmpty(v);
+    assert(v.valueless_by_exception());
+  }
+#endif
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.swap/swap.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,591 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// void swap(variant& rhs) noexcept(see below)
+
+#include <cassert>
+#include <string>
+#include <type_traits>
+#include <variant>
+
+#include "test_convertible.hpp"
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+struct NotSwappable {};
+void swap(NotSwappable &, NotSwappable &) = delete;
+
+struct NotCopyable {
+  NotCopyable() = default;
+  NotCopyable(NotCopyable const &) = delete;
+  NotCopyable &operator=(NotCopyable const &) = delete;
+};
+
+struct NotCopyableWithSwap {
+  NotCopyableWithSwap() = default;
+  NotCopyableWithSwap(NotCopyableWithSwap const &) = delete;
+  NotCopyableWithSwap &operator=(NotCopyableWithSwap const &) = delete;
+};
+void swap(NotCopyableWithSwap &, NotCopyableWithSwap) {}
+
+struct NotMoveAssignable {
+  NotMoveAssignable() = default;
+  NotMoveAssignable(NotMoveAssignable &&) = default;
+  NotMoveAssignable &operator=(NotMoveAssignable &&) = delete;
+};
+
+struct NotMoveAssignableWithSwap {
+  NotMoveAssignableWithSwap() = default;
+  NotMoveAssignableWithSwap(NotMoveAssignableWithSwap &&) = default;
+  NotMoveAssignableWithSwap &operator=(NotMoveAssignableWithSwap &&) = delete;
+};
+void swap(NotMoveAssignableWithSwap &, NotMoveAssignableWithSwap &) noexcept {}
+
+template <bool Throws> void do_throw() {}
+
+template <> void do_throw<true>() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  throw 42;
+#else
+  std::abort();
+#endif
+}
+
+template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign,
+          bool NT_Swap, bool EnableSwap = true>
+struct NothrowTypeImp {
+  static int move_called;
+  static int move_assign_called;
+  static int swap_called;
+  static void reset() { move_called = move_assign_called = swap_called = 0; }
+  NothrowTypeImp() = default;
+  explicit NothrowTypeImp(int v) : value(v) {}
+  NothrowTypeImp(NothrowTypeImp const &o) noexcept(NT_Copy) : value(o.value) {
+    assert(false);
+  } // never called by test
+  NothrowTypeImp(NothrowTypeImp &&o) noexcept(NT_Move) : value(o.value) {
+    ++move_called;
+    do_throw<!NT_Move>();
+    o.value = -1;
+  }
+  NothrowTypeImp &operator=(NothrowTypeImp const &) noexcept(NT_CopyAssign) {
+    assert(false);
+    return *this;
+  } // never called by the tests
+  NothrowTypeImp &operator=(NothrowTypeImp &&o) noexcept(NT_MoveAssign) {
+    ++move_assign_called;
+    do_throw<!NT_MoveAssign>();
+    value = o.value;
+    o.value = -1;
+    return *this;
+  }
+  int value;
+};
+template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign,
+          bool NT_Swap, bool EnableSwap>
+int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap,
+                   EnableSwap>::move_called = 0;
+template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign,
+          bool NT_Swap, bool EnableSwap>
+int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap,
+                   EnableSwap>::move_assign_called = 0;
+template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign,
+          bool NT_Swap, bool EnableSwap>
+int NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign, NT_Swap,
+                   EnableSwap>::swap_called = 0;
+
+template <bool NT_Copy, bool NT_Move, bool NT_CopyAssign, bool NT_MoveAssign,
+          bool NT_Swap>
+void swap(NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign,
+                         NT_Swap, true> &lhs,
+          NothrowTypeImp<NT_Copy, NT_Move, NT_CopyAssign, NT_MoveAssign,
+                         NT_Swap, true> &rhs) noexcept(NT_Swap) {
+  lhs.swap_called++;
+  do_throw<!NT_Swap>();
+  int tmp = lhs.value;
+  lhs.value = rhs.value;
+  rhs.value = tmp;
+}
+
+// throwing copy, nothrow move ctor/assign, no swap provided
+using NothrowMoveable = NothrowTypeImp<false, true, false, true, false, false>;
+// throwing copy and move assign, nothrow move ctor, no swap provided
+using NothrowMoveCtor = NothrowTypeImp<false, true, false, false, false, false>;
+// nothrow move ctor, throwing move assignment, swap provided
+using NothrowMoveCtorWithThrowingSwap =
+    NothrowTypeImp<false, true, false, false, false, true>;
+// throwing move ctor, nothrow move assignment, no swap provided
+using ThrowingMoveCtor =
+    NothrowTypeImp<false, false, false, true, false, false>;
+// throwing special members, nothrowing swap
+using ThrowingTypeWithNothrowSwap =
+    NothrowTypeImp<false, false, false, false, true, true>;
+using NothrowTypeWithThrowingSwap =
+    NothrowTypeImp<true, true, true, true, false, true>;
+// throwing move assign with nothrow move and nothrow swap
+using ThrowingMoveAssignNothrowMoveCtorWithSwap =
+    NothrowTypeImp<false, true, false, false, true, true>;
+// throwing move assign with nothrow move but no swap.
+using ThrowingMoveAssignNothrowMoveCtor =
+    NothrowTypeImp<false, true, false, false, false, false>;
+
+struct NonThrowingNonNoexceptType {
+  static int move_called;
+  static void reset() { move_called = 0; }
+  NonThrowingNonNoexceptType() = default;
+  NonThrowingNonNoexceptType(int v) : value(v) {}
+  NonThrowingNonNoexceptType(NonThrowingNonNoexceptType &&o) noexcept(false)
+      : value(o.value) {
+    ++move_called;
+    o.value = -1;
+  }
+  NonThrowingNonNoexceptType &
+  operator=(NonThrowingNonNoexceptType &&) noexcept(false) {
+    assert(false); // never called by the tests.
+    return *this;
+  }
+  int value;
+};
+int NonThrowingNonNoexceptType::move_called = 0;
+
+struct ThrowsOnSecondMove {
+  int value;
+  int move_count;
+  ThrowsOnSecondMove(int v) : value(v), move_count(0) {}
+  ThrowsOnSecondMove(ThrowsOnSecondMove &&o) noexcept(false)
+      : value(o.value), move_count(o.move_count + 1) {
+    if (move_count == 2)
+      do_throw<true>();
+    o.value = -1;
+  }
+  ThrowsOnSecondMove &operator=(ThrowsOnSecondMove &&) {
+    assert(false); // not called by test
+    return *this;
+  }
+};
+
+void test_swap_valueless_by_exception() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using V = std::variant<int, MakeEmptyT>;
+  { // both empty
+    V v1;
+    makeEmpty(v1);
+    V v2;
+    makeEmpty(v2);
+    assert(MakeEmptyT::alive == 0);
+    { // member swap
+      v1.swap(v2);
+      assert(v1.valueless_by_exception());
+      assert(v2.valueless_by_exception());
+      assert(MakeEmptyT::alive == 0);
+    }
+    { // non-member swap
+      swap(v1, v2);
+      assert(v1.valueless_by_exception());
+      assert(v2.valueless_by_exception());
+      assert(MakeEmptyT::alive == 0);
+    }
+  }
+  { // only one empty
+    V v1(42);
+    V v2;
+    makeEmpty(v2);
+    { // member swap
+      v1.swap(v2);
+      assert(v1.valueless_by_exception());
+      assert(std::get<0>(v2) == 42);
+      // swap again
+      v2.swap(v1);
+      assert(v2.valueless_by_exception());
+      assert(std::get<0>(v1) == 42);
+    }
+    { // non-member swap
+      swap(v1, v2);
+      assert(v1.valueless_by_exception());
+      assert(std::get<0>(v2) == 42);
+      // swap again
+      swap(v1, v2);
+      assert(v2.valueless_by_exception());
+      assert(std::get<0>(v1) == 42);
+    }
+  }
+#endif
+}
+
+void test_swap_same_alternative() {
+  {
+    using T = ThrowingTypeWithNothrowSwap;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>, 100);
+    v1.swap(v2);
+    assert(T::swap_called == 1);
+    assert(std::get<0>(v1).value == 100);
+    assert(std::get<0>(v2).value == 42);
+    swap(v1, v2);
+    assert(T::swap_called == 2);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<0>(v2).value == 100);
+  }
+  {
+    using T = NothrowMoveable;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>, 100);
+    v1.swap(v2);
+    assert(T::swap_called == 0);
+    assert(T::move_called == 1);
+    assert(T::move_assign_called == 2);
+    assert(std::get<0>(v1).value == 100);
+    assert(std::get<0>(v2).value == 42);
+    T::reset();
+    swap(v1, v2);
+    assert(T::swap_called == 0);
+    assert(T::move_called == 1);
+    assert(T::move_assign_called == 2);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<0>(v2).value == 100);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using T = NothrowTypeWithThrowingSwap;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T::swap_called == 1);
+    assert(T::move_called == 0);
+    assert(T::move_assign_called == 0);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<0>(v2).value == 100);
+  }
+  {
+    using T = ThrowingMoveCtor;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T::move_called == 1); // call threw
+    assert(T::move_assign_called == 0);
+    assert(std::get<0>(v1).value ==
+           42); // throw happened before v1 was moved from
+    assert(std::get<0>(v2).value == 100);
+  }
+  {
+    using T = ThrowingMoveAssignNothrowMoveCtor;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<0>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T::move_called == 1);
+    assert(T::move_assign_called == 1);  // call threw and didn't complete
+    assert(std::get<0>(v1).value == -1); // v1 was moved from
+    assert(std::get<0>(v2).value == 100);
+  }
+#endif
+}
+
+void test_swap_different_alternatives() {
+  {
+    using T = NothrowMoveCtorWithThrowingSwap;
+    using V = std::variant<T, int>;
+    T::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    v1.swap(v2);
+    assert(T::swap_called == 0);
+    // The libc++ implementation double copies the argument, and not
+    // the variant swap is called on.
+    LIBCPP_ASSERT(T::move_called == 1);
+    assert(T::move_called <= 2);
+    assert(T::move_assign_called == 0);
+    assert(std::get<1>(v1) == 100);
+    assert(std::get<0>(v2).value == 42);
+    T::reset();
+    swap(v1, v2);
+    assert(T::swap_called == 0);
+    LIBCPP_ASSERT(T::move_called == 2);
+    assert(T::move_called <= 2);
+    assert(T::move_assign_called == 0);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<1>(v2) == 100);
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using T1 = ThrowingTypeWithNothrowSwap;
+    using T2 = NonThrowingNonNoexceptType;
+    using V = std::variant<T1, T2>;
+    T1::reset();
+    T2::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T1::swap_called == 0);
+    assert(T1::move_called == 1); // throws
+    assert(T1::move_assign_called == 0);
+    // FIXME: libc++ shouldn't move from T2 here.
+    LIBCPP_ASSERT(T2::move_called == 1);
+    assert(T2::move_called <= 1);
+    assert(std::get<0>(v1).value == 42);
+    if (T2::move_called != 0)
+      assert(v2.valueless_by_exception());
+    else
+      assert(std::get<1>(v2).value == 100);
+  }
+  {
+    using T1 = NonThrowingNonNoexceptType;
+    using T2 = ThrowingTypeWithNothrowSwap;
+    using V = std::variant<T1, T2>;
+    T1::reset();
+    T2::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    LIBCPP_ASSERT(T1::move_called == 0);
+    assert(T1::move_called <= 1);
+    assert(T2::swap_called == 0);
+    assert(T2::move_called == 1); // throws
+    assert(T2::move_assign_called == 0);
+    if (T1::move_called != 0)
+      assert(v1.valueless_by_exception());
+    else
+      assert(std::get<0>(v1).value == 42);
+    assert(std::get<1>(v2).value == 100);
+  }
+// FIXME: The tests below are just very libc++ specific
+#ifdef _LIBCPP_VERSION
+  {
+    using T1 = ThrowsOnSecondMove;
+    using T2 = NonThrowingNonNoexceptType;
+    using V = std::variant<T1, T2>;
+    T2::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    v1.swap(v2);
+    assert(T2::move_called == 2);
+    assert(std::get<1>(v1).value == 100);
+    assert(std::get<0>(v2).value == 42);
+    assert(std::get<0>(v2).move_count == 1);
+  }
+  {
+    using T1 = NonThrowingNonNoexceptType;
+    using T2 = ThrowsOnSecondMove;
+    using V = std::variant<T1, T2>;
+    T1::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T1::move_called == 1);
+    assert(v1.valueless_by_exception());
+    assert(std::get<0>(v2).value == 42);
+  }
+#endif
+// testing libc++ extension. If either variant stores a nothrow move
+// constructible type v1.swap(v2) provides the strong exception safety
+// guarantee.
+#ifdef _LIBCPP_VERSION
+  {
+
+    using T1 = ThrowingTypeWithNothrowSwap;
+    using T2 = NothrowMoveable;
+    using V = std::variant<T1, T2>;
+    T1::reset();
+    T2::reset();
+    V v1(std::in_place_index<0>, 42);
+    V v2(std::in_place_index<1>, 100);
+    try {
+      v1.swap(v2);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T1::swap_called == 0);
+    assert(T1::move_called == 1);
+    assert(T1::move_assign_called == 0);
+    assert(T2::swap_called == 0);
+    assert(T2::move_called == 2);
+    assert(T2::move_assign_called == 0);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<1>(v2).value == 100);
+    // swap again, but call v2's swap.
+    T1::reset();
+    T2::reset();
+    try {
+      v2.swap(v1);
+      assert(false);
+    } catch (int) {
+    }
+    assert(T1::swap_called == 0);
+    assert(T1::move_called == 1);
+    assert(T1::move_assign_called == 0);
+    assert(T2::swap_called == 0);
+    assert(T2::move_called == 2);
+    assert(T2::move_assign_called == 0);
+    assert(std::get<0>(v1).value == 42);
+    assert(std::get<1>(v2).value == 100);
+  }
+#endif // _LIBCPP_VERSION
+#endif
+}
+
+template <class Var>
+constexpr auto has_swap_member_imp(int)
+    -> decltype(std::declval<Var &>().swap(std::declval<Var &>()), true) {
+  return true;
+}
+
+template <class Var> constexpr auto has_swap_member_imp(long) -> bool {
+  return false;
+}
+
+template <class Var> constexpr bool has_swap_member() {
+  return has_swap_member_imp<Var>(0);
+}
+
+void test_swap_sfinae() {
+  {
+    // This variant type does not provide either a member or non-member swap
+    // but is still swappable via the generic swap algorithm, since the
+    // variant is move constructible and move assignable.
+    using V = std::variant<int, NotSwappable>;
+    LIBCPP_STATIC_ASSERT(!has_swap_member<V>());
+    static_assert(std::is_swappable_v<V>, "");
+  }
+  {
+    using V = std::variant<int, NotCopyable>;
+    LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), "");
+    static_assert(!std::is_swappable_v<V>, "");
+  }
+  {
+    using V = std::variant<int, NotCopyableWithSwap>;
+    LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), "");
+    static_assert(!std::is_swappable_v<V>, "");
+  }
+  {
+    using V = std::variant<int, NotMoveAssignable>;
+    LIBCPP_STATIC_ASSERT(!has_swap_member<V>(), "");
+    static_assert(!std::is_swappable_v<V>, "");
+  }
+}
+
+void test_swap_noexcept() {
+  {
+    using V = std::variant<int, NothrowMoveable>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    using V = std::variant<int, NothrowMoveCtor>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(!std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    using V = std::variant<int, ThrowingTypeWithNothrowSwap>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(!std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    using V = std::variant<int, ThrowingMoveAssignNothrowMoveCtor>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(!std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    using V = std::variant<int, ThrowingMoveAssignNothrowMoveCtorWithSwap>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    using V = std::variant<int, NotMoveAssignableWithSwap>;
+    static_assert(std::is_swappable_v<V> && has_swap_member<V>(), "");
+    static_assert(std::is_nothrow_swappable_v<V>, "");
+    // instantiate swap
+    V v1, v2;
+    v1.swap(v2);
+    swap(v1, v2);
+  }
+  {
+    // This variant type does not provide either a member or non-member swap
+    // but is still swappable via the generic swap algorithm, since the
+    // variant is move constructible and move assignable.
+    using V = std::variant<int, NotSwappable>;
+    LIBCPP_STATIC_ASSERT(!has_swap_member<V>());
+    static_assert(std::is_swappable_v<V>, "");
+    static_assert(std::is_nothrow_swappable_v<V>, "");
+    V v1, v2;
+    swap(v1, v2);
+  }
+}
+
+
+// This is why variant should SFINAE member swap. :-)
+LIBCPP_ONLY(template class std::variant<int, NotSwappable>;)
+
+
+int main() {
+  test_swap_valueless_by_exception();
+  test_swap_same_alternative();
+  test_swap_different_alternatives();
+  test_swap_sfinae();
+  test_swap_noexcept();
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant_array.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant_array.fail.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant_array.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant_array.fail.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+
+#include <variant>
+#include <type_traits>
+#include <string>
+#include <cassert>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include "test_convertible.hpp"
+
+int main()
+{
+    // expected-error at variant:* 3 {{static_assert failed}}
+    std::variant<int, int[]> v; // expected-note {{requested here}}
+    std::variant<int, int[42]> v2; // expected-note {{requested here}}
+    std::variant<int, int[][42]> v3; // expected-note {{requested here}}
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant_empty.fail.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+int main()
+{
+    // expected-error at variant:* 1 {{static_assert failed}}
+    std::variant<> v; // expected-note {{requested here}}
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant_reference.fail.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+#include <variant>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+
+int main()
+{
+    // expected-error at variant:* 3 {{static_assert failed}}
+    std::variant<int, int&> v; // expected-note {{requested here}}
+    std::variant<int, int const&> v2; // expected-note {{requested here}}
+    std::variant<int, int&&> v3; // expected-note {{requested here}}
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.variant/variant_void.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant_void.fail.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant_void.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant_void.fail.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+
+#include <variant>
+#include <type_traits>
+#include <string>
+#include <cassert>
+
+#include "test_macros.h"
+#include "variant_test_helpers.hpp"
+#include "test_convertible.hpp"
+
+int main()
+{
+    // expected-error at variant:* 3 {{static_assert failed}}
+    std::variant<int, void> v; // expected-note {{requested here}}
+    std::variant<int, const void> v2; // expected-note {{requested here}}
+    std::variant<const volatile void, int> v3; // expected-note {{requested here}}
+}

Added: libcxx/trunk/test/std/utilities/variant/variant.visit/visit.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.visit/visit.pass.cpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.visit/visit.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/variant/variant.visit/visit.pass.cpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,291 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <variant>
+// template <class Visitor, class... Variants>
+// constexpr see below visit(Visitor&& vis, Variants&&... vars);
+
+#include <cassert>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+#include "test_macros.h"
+#include "type_id.h"
+#include "variant_test_helpers.hpp"
+
+enum CallType : unsigned {
+  CT_None,
+  CT_NonConst = 1,
+  CT_Const = 2,
+  CT_LValue = 4,
+  CT_RValue = 8
+};
+
+inline constexpr CallType operator|(CallType LHS, CallType RHS) {
+  return static_cast<CallType>(static_cast<unsigned>(LHS) |
+                               static_cast<unsigned>(RHS));
+}
+
+struct ForwardingCallObject {
+
+  template <class... Args> bool operator()(Args &&...) & {
+    set_call<Args &&...>(CT_NonConst | CT_LValue);
+    return true;
+  }
+
+  template <class... Args> bool operator()(Args &&...) const & {
+    set_call<Args &&...>(CT_Const | CT_LValue);
+    return true;
+  }
+
+  // Don't allow the call operator to be invoked as an rvalue.
+  template <class... Args> bool operator()(Args &&...) && {
+    set_call<Args &&...>(CT_NonConst | CT_RValue);
+    return true;
+  }
+
+  template <class... Args> bool operator()(Args &&...) const && {
+    set_call<Args &&...>(CT_Const | CT_RValue);
+    return true;
+  }
+
+  template <class... Args> static void set_call(CallType type) {
+    assert(last_call_type == CT_None);
+    assert(last_call_args == nullptr);
+    last_call_type = type;
+    last_call_args = std::addressof(makeArgumentID<Args...>());
+  }
+
+  template <class... Args> static bool check_call(CallType type) {
+    bool result = last_call_type == type && last_call_args &&
+                  *last_call_args == makeArgumentID<Args...>();
+    last_call_type = CT_None;
+    last_call_args = nullptr;
+    return result;
+  }
+
+  static CallType last_call_type;
+  static TypeID const *last_call_args;
+};
+
+CallType ForwardingCallObject::last_call_type = CT_None;
+TypeID const *ForwardingCallObject::last_call_args = nullptr;
+
+void test_call_operator_forwarding() {
+  using Fn = ForwardingCallObject;
+  Fn obj{};
+  Fn const &cobj = obj;
+  { // test call operator forwarding - single variant, single arg
+    using V = std::variant<int>;
+    V v(42);
+    std::visit(obj, v);
+    assert(Fn::check_call<int &>(CT_NonConst | CT_LValue));
+    std::visit(cobj, v);
+    assert(Fn::check_call<int &>(CT_Const | CT_LValue));
+    std::visit(std::move(obj), v);
+    assert(Fn::check_call<int &>(CT_NonConst | CT_RValue));
+    std::visit(std::move(cobj), v);
+    assert(Fn::check_call<int &>(CT_Const | CT_RValue));
+  }
+  { // test call operator forwarding - single variant, multi arg
+    using V = std::variant<int, long, double>;
+    V v(42l);
+    std::visit(obj, v);
+    assert(Fn::check_call<long &>(CT_NonConst | CT_LValue));
+    std::visit(cobj, v);
+    assert(Fn::check_call<long &>(CT_Const | CT_LValue));
+    std::visit(std::move(obj), v);
+    assert(Fn::check_call<long &>(CT_NonConst | CT_RValue));
+    std::visit(std::move(cobj), v);
+    assert(Fn::check_call<long &>(CT_Const | CT_RValue));
+  }
+  { // test call operator forwarding - multi variant, multi arg
+    using V = std::variant<int, long, double>;
+    using V2 = std::variant<int *, std::string>;
+    V v(42l);
+    V2 v2("hello");
+    std::visit(obj, v, v2);
+    assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_LValue)));
+    std::visit(cobj, v, v2);
+    assert((Fn::check_call<long &, std::string &>(CT_Const | CT_LValue)));
+    std::visit(std::move(obj), v, v2);
+    assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_RValue)));
+    std::visit(std::move(cobj), v, v2);
+    assert((Fn::check_call<long &, std::string &>(CT_Const | CT_RValue)));
+  }
+}
+
+void test_argument_forwarding() {
+  using Fn = ForwardingCallObject;
+  Fn obj{};
+  const auto Val = CT_LValue | CT_NonConst;
+  { // single argument - value type
+    using V = std::variant<int>;
+    V v(42);
+    V const &cv = v;
+    std::visit(obj, v);
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, cv);
+    assert(Fn::check_call<int const &>(Val));
+    std::visit(obj, std::move(v));
+    assert(Fn::check_call<int &&>(Val));
+    std::visit(obj, std::move(cv));
+    assert(Fn::check_call<const int &&>(Val));
+  }
+#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
+  { // single argument - lvalue reference
+    using V = std::variant<int &>;
+    int x = 42;
+    V v(x);
+    V const &cv = v;
+    std::visit(obj, v);
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, cv);
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, std::move(v));
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, std::move(cv));
+    assert(Fn::check_call<int &>(Val));
+  }
+  { // single argument - rvalue reference
+    using V = std::variant<int &&>;
+    int x = 42;
+    V v(std::move(x));
+    V const &cv = v;
+    std::visit(obj, v);
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, cv);
+    assert(Fn::check_call<int &>(Val));
+    std::visit(obj, std::move(v));
+    assert(Fn::check_call<int &&>(Val));
+    std::visit(obj, std::move(cv));
+    assert(Fn::check_call<int &&>(Val));
+  }
+  { // multi argument - multi variant
+    using S = std::string const &;
+    using V = std::variant<int, S, long &&>;
+    std::string const str = "hello";
+    long l = 43;
+    V v1(42);
+    V const &cv1 = v1;
+    V v2(str);
+    V const &cv2 = v2;
+    V v3(std::move(l));
+    V const &cv3 = v3;
+    std::visit(obj, v1, v2, v3);
+    assert((Fn::check_call<int &, S, long &>(Val)));
+    std::visit(obj, cv1, cv2, std::move(v3));
+    assert((Fn::check_call<const int &, S, long &&>(Val)));
+  }
+#endif
+}
+
+struct ReturnFirst {
+  template <class... Args> constexpr int operator()(int f, Args &&...) const {
+    return f;
+  }
+};
+
+struct ReturnArity {
+  template <class... Args> constexpr int operator()(Args &&...) const {
+    return sizeof...(Args);
+  }
+};
+
+void test_constexpr() {
+  constexpr ReturnFirst obj{};
+  constexpr ReturnArity aobj{};
+  {
+    using V = std::variant<int>;
+    constexpr V v(42);
+    static_assert(std::visit(obj, v) == 42, "");
+  }
+  {
+    using V = std::variant<short, long, char>;
+    constexpr V v(42l);
+    static_assert(std::visit(obj, v) == 42, "");
+  }
+  {
+    using V1 = std::variant<int>;
+    using V2 = std::variant<int, char *, long long>;
+    using V3 = std::variant<bool, int, int>;
+    constexpr V1 v1;
+    constexpr V2 v2(nullptr);
+    constexpr V3 v3;
+    static_assert(std::visit(aobj, v1, v2, v3) == 3, "");
+  }
+  {
+    using V1 = std::variant<int>;
+    using V2 = std::variant<int, char *, long long>;
+    using V3 = std::variant<void *, int, int>;
+    constexpr V1 v1;
+    constexpr V2 v2(nullptr);
+    constexpr V3 v3;
+    static_assert(std::visit(aobj, v1, v2, v3) == 3, "");
+  }
+}
+
+void test_exceptions() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  ReturnArity obj{};
+  auto test = [&](auto &&... args) {
+    try {
+      std::visit(obj, args...);
+    } catch (std::bad_variant_access const &) {
+      return true;
+    } catch (...) {
+    }
+    return false;
+  };
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    V v;
+    makeEmpty(v);
+    assert(test(v));
+  }
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    using V2 = std::variant<long, std::string, void *>;
+    V v;
+    makeEmpty(v);
+    V2 v2("hello");
+    assert(test(v, v2));
+  }
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    using V2 = std::variant<long, std::string, void *>;
+    V v;
+    makeEmpty(v);
+    V2 v2("hello");
+    assert(test(v2, v));
+  }
+  {
+    using V = std::variant<int, MakeEmptyT>;
+    using V2 = std::variant<long, std::string, void *, MakeEmptyT>;
+    V v;
+    makeEmpty(v);
+    V2 v2;
+    makeEmpty(v2);
+    assert(test(v, v2));
+  }
+#endif
+}
+
+int main() {
+  test_call_operator_forwarding();
+  test_argument_forwarding();
+  test_constexpr();
+  test_exceptions();
+}

Modified: libcxx/trunk/test/support/archetypes.ipp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/archetypes.ipp?rev=287728&r1=287727&r2=287728&view=diff
==============================================================================
--- libcxx/trunk/test/support/archetypes.ipp (original)
+++ libcxx/trunk/test/support/archetypes.ipp Tue Nov 22 19:02:51 2016
@@ -42,7 +42,6 @@ struct AllCtors : DEFINE_BASE(AllCtors)
 
 struct NoCtors : DEFINE_BASE(NoCtors) {
   using Base = DEFINE_BASE(NoCtors);
-  using Base::Base;
   DEFINE_EXPLICIT NoCtors() = delete;
   DEFINE_EXPLICIT NoCtors(NoCtors const&) = delete;
   NoCtors& operator=(NoCtors const&) = delete;

Added: libcxx/trunk/test/support/variant_test_helpers.hpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/variant_test_helpers.hpp?rev=287728&view=auto
==============================================================================
--- libcxx/trunk/test/support/variant_test_helpers.hpp (added)
+++ libcxx/trunk/test/support/variant_test_helpers.hpp Tue Nov 22 19:02:51 2016
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SUPPORT_VARIANT_TEST_HELPERS_HPP
+#define SUPPORT_VARIANT_TEST_HELPERS_HPP
+
+#include <type_traits>
+#include <utility>
+#include <cassert>
+
+#include "test_macros.h"
+
+#if TEST_STD_VER <= 14
+#error This file requires C++17
+#endif
+
+// FIXME: Currently the variant<T&> tests are disabled using this macro.
+#define TEST_VARIANT_HAS_NO_REFERENCES
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct CopyThrows {
+  CopyThrows() = default;
+  CopyThrows(CopyThrows const&) { throw 42; }
+  CopyThrows& operator=(CopyThrows const&) { throw 42; }
+};
+
+struct MoveThrows {
+  static int alive;
+  MoveThrows() { ++alive; }
+  MoveThrows(MoveThrows const&) {++alive;}
+  MoveThrows(MoveThrows&&) {  throw 42; }
+  MoveThrows& operator=(MoveThrows const&) { return *this; }
+  MoveThrows& operator=(MoveThrows&&) { throw 42; }
+  ~MoveThrows() { --alive; }
+};
+
+int MoveThrows::alive = 0;
+
+struct MakeEmptyT {
+  static int alive;
+  MakeEmptyT() { ++alive; }
+  MakeEmptyT(MakeEmptyT const&) {
+      ++alive;
+      // Don't throw from the copy constructor since variant's assignment
+      // operator performs a copy before committing to the assignment.
+  }
+  MakeEmptyT(MakeEmptyT &&) {
+      throw 42;
+  }
+  MakeEmptyT& operator=(MakeEmptyT const&) {
+      throw 42;
+  }
+  MakeEmptyT& operator=(MakeEmptyT&&) {
+      throw 42;
+  }
+   ~MakeEmptyT() { --alive; }
+};
+static_assert(std::is_swappable_v<MakeEmptyT>, ""); // required for test
+
+int MakeEmptyT::alive = 0;
+
+template <class Variant>
+void makeEmpty(Variant& v) {
+    Variant v2(std::in_place_type<MakeEmptyT>);
+    try {
+        v = v2;
+        assert(false);
+    }  catch (...) {
+        assert(v.valueless_by_exception());
+    }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+
+#endif // SUPPORT_VARIANT_TEST_HELPERS_HPP




More information about the cfe-commits mailing list