[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