diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:41 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:41 +0000 |
commit | 74c4bc8d0eddcb4786594f1c6b598094fac43859 (patch) | |
tree | b52af5df113676d27ce94f2a11b1b73f28e1e0a1 | |
parent | 7c5c4ef25000522f341d2edb21344a2fe2b881ad (diff) |
Notes
30 files changed, 1288 insertions, 832 deletions
diff --git a/include/__mutex_base b/include/__mutex_base index 159acd626618..3b2453f1ba1a 100644 --- a/include/__mutex_base +++ b/include/__mutex_base @@ -48,7 +48,7 @@ class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mut public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_CXX03_LANG - constexpr mutex() _NOEXCEPT = default; + constexpr mutex() = default; #else mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;} #endif @@ -67,6 +67,9 @@ public: _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; +static_assert(is_nothrow_default_constructible<mutex>::value, + "the default constructor for std::mutex must be nothrow"); + struct _LIBCPP_TYPE_VIS defer_lock_t {}; struct _LIBCPP_TYPE_VIS try_to_lock_t {}; struct _LIBCPP_TYPE_VIS adopt_lock_t {}; diff --git a/include/mutex b/include/mutex index 55380882044d..1557ed8770d7 100644 --- a/include/mutex +++ b/include/mutex @@ -502,7 +502,6 @@ public: _LIBCPP_INLINE_VISIBILITY explicit scoped_lock(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} - scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; diff --git a/include/numeric b/include/numeric index 0e53ba33c3c7..a84fb862b667 100644 --- a/include/numeric +++ b/include/numeric @@ -42,6 +42,23 @@ template <class InputIterator, class OutputIterator, class BinaryOperation> OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); +template<class InputIterator, class OutputIterator, class T> + OutputIterator + exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init); // C++17 + +template<class InputIterator, class OutputIterator, class T, class BinaryOperation> + OutputIterator + exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init, BinaryOperation binary_op); // C++17 + +template<class InputIterator, class OutputIterator, class T, + class BinaryOperation, class UnaryOperation> + OutputIterator + transform_exclusive_scan(InputIterator first, InputIterator last, + OutputIterator result, T init, + BinaryOperation binary_op, UnaryOperation unary_op); // C++17 + template <class InputIterator, class OutputIterator> OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result); @@ -66,6 +83,7 @@ template <class M, class N> #include <__config> #include <iterator> #include <limits> // for numeric_limits +#include <functional> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -154,6 +172,59 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res return __result; } +#if _LIBCPP_STD_VER > 14 +template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp> +inline _LIBCPP_INLINE_VISIBILITY +_OutputIterator +exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, _BinaryOp __b) +{ + if (__first != __last) + { + _Tp __saved = __init; + do + { + __init = __b(__init, *__first); + *__result = __saved; + __saved = __init; + ++__result; + } while (++__first != __last); + } + return __result; +} + +template <class _InputIterator, class _OutputIterator, class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +_OutputIterator +exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init) +{ + return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>()); +} + +template <class _InputIterator, class _OutputIterator, class _Tp, + class _BinaryOp, class _UnaryOp> +inline _LIBCPP_INLINE_VISIBILITY +_OutputIterator +transform_exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOp __b, _UnaryOp __u) +{ + if (__first != __last) + { + _Tp __saved = __init; + do + { + __init = __b(__init, __u(*__first)); + *__result = __saved; + __saved = __init; + ++__result; + } while (++__first != __last); + } + return __result; +} +#endif + template <class _InputIterator, class _OutputIterator> inline _LIBCPP_INLINE_VISIBILITY _OutputIterator diff --git a/include/optional b/include/optional index 8c8ee76b1411..c0fd0e7bc49f 100644 --- a/include/optional +++ b/include/optional @@ -897,7 +897,7 @@ public: template <class _Up> _LIBCPP_INLINE_VISIBILITY - value_type value_or(_Up&& __v) && + constexpr value_type value_or(_Up&& __v) && { static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible"); diff --git a/include/tuple b/include/tuple index aa4713faf06f..a52b934aaca7 100644 --- a/include/tuple +++ b/include/tuple @@ -929,6 +929,16 @@ public: void swap(tuple&) _NOEXCEPT {} }; +#ifdef __cpp_deduction_guides +// NOTE: These are not yet standardized, but are required to simulate the +// implicit deduction guide that should be generated had libc++ declared the +// tuple-like constructors "correctly" +template <class _Alloc, class ..._Args> +tuple(allocator_arg_t, const _Alloc&, tuple<_Args...> const&) -> tuple<_Args...>; +template <class _Alloc, class ..._Args> +tuple(allocator_arg_t, const _Alloc&, tuple<_Args...>&&) -> tuple<_Args...>; +#endif + template <class ..._Tp> inline _LIBCPP_INLINE_VISIBILITY typename enable_if diff --git a/include/variant b/include/variant index ba15ed8c4a14..8505f3262a18 100644 --- a/include/variant +++ b/include/variant @@ -358,7 +358,6 @@ struct __traits { static constexpr _Trait __copy_assignable_trait = __common_trait( {__copy_constructible_trait, - __move_constructible_trait, __trait<_Types, is_trivially_copy_assignable, is_copy_assignable>...}); static constexpr _Trait __move_assignable_trait = __common_trait( @@ -877,25 +876,24 @@ public: } protected: - template <bool _CopyAssign, size_t _Ip, class _Tp, class _Arg> + template <size_t _Ip, class _Tp, class _Arg> inline _LIBCPP_INLINE_VISIBILITY - void __assign_alt(__alt<_Ip, _Tp>& __a, - _Arg&& __arg, - bool_constant<_CopyAssign> __tag) { + void __assign_alt(__alt<_Ip, _Tp>& __a, _Arg&& __arg) { if (this->index() == _Ip) { __a.__value = _VSTD::forward<_Arg>(__arg); } else { struct { void operator()(true_type) const { - __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg))); + __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg)); } void operator()(false_type) const { - __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg)); + __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg))); } __assignment* __this; _Arg&& __arg; } __impl{this, _VSTD::forward<_Arg>(__arg)}; - __impl(__tag); + __impl(bool_constant<is_nothrow_constructible_v<_Tp, _Arg> || + !is_nothrow_move_constructible_v<_Tp>>{}); } } @@ -912,8 +910,7 @@ protected: [this](auto& __this_alt, auto&& __that_alt) { this->__assign_alt( __this_alt, - _VSTD::forward<decltype(__that_alt)>(__that_alt).__value, - is_lvalue_reference<_That>{}); + _VSTD::forward<decltype(__that_alt)>(__that_alt).__value); }, *this, _VSTD::forward<_That>(__that)); } @@ -1013,8 +1010,7 @@ public: inline _LIBCPP_INLINE_VISIBILITY void __assign(_Arg&& __arg) { this->__assign_alt(__access::__base::__get_alt<_Ip>(*this), - _VSTD::forward<_Arg>(__arg), - false_type{}); + _VSTD::forward<_Arg>(__arg)); } inline _LIBCPP_INLINE_VISIBILITY @@ -1088,7 +1084,6 @@ class _LIBCPP_TEMPLATE_VIS variant __all<is_move_constructible_v<_Types>...>::value>, private __sfinae_assign_base< __all<(is_copy_constructible_v<_Types> && - is_move_constructible_v<_Types> && is_copy_assignable_v<_Types>)...>::value, __all<(is_move_constructible_v<_Types> && is_move_assignable_v<_Types>)...>::value> { diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp deleted file mode 100644 index 26556c6eb047..000000000000 --- a/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// -*- 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 - -// The following compilers don't generate constexpr special members correctly. -// XFAIL: clang-3.5, clang-3.6, clang-3.7, clang-3.8 -// XFAIL: apple-clang-6, apple-clang-7, apple-clang-8.0 - -// <variant> - -// template <class ...Types> class variant; - -// variant& operator=(variant const&); - -#include <type_traits> -#include <variant> - -#include "test_macros.h" - -struct NTCopyAssign { - constexpr NTCopyAssign(int v) : value(v) {} - NTCopyAssign(const NTCopyAssign &) = default; - NTCopyAssign(NTCopyAssign &&) = default; - NTCopyAssign &operator=(const NTCopyAssign &that) { - value = that.value; - return *this; - }; - NTCopyAssign &operator=(NTCopyAssign &&) = delete; - int value; -}; - -static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, ""); -static_assert(std::is_copy_assignable<NTCopyAssign>::value, ""); - -struct TCopyAssign { - constexpr TCopyAssign(int v) : value(v) {} - TCopyAssign(const TCopyAssign &) = default; - TCopyAssign(TCopyAssign &&) = default; - TCopyAssign &operator=(const TCopyAssign &) = default; - TCopyAssign &operator=(TCopyAssign &&) = delete; - int value; -}; - -static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, ""); - -struct TCopyAssignNTMoveAssign { - constexpr TCopyAssignNTMoveAssign(int v) : value(v) {} - TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default; - TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default; - TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default; - TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) { - value = that.value; - that.value = -1; - return *this; - } - int value; -}; - -static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>, ""); - -void test_copy_assignment_sfinae() { - { - using V = std::variant<int, long>; - static_assert(std::is_trivially_copy_assignable<V>::value, ""); - } - { - using V = std::variant<int, NTCopyAssign>; - static_assert(!std::is_trivially_copy_assignable<V>::value, ""); - static_assert(std::is_copy_assignable<V>::value, ""); - } - { - using V = std::variant<int, TCopyAssign>; - static_assert(std::is_trivially_copy_assignable<V>::value, ""); - } - { - using V = std::variant<int, TCopyAssignNTMoveAssign>; - static_assert(std::is_trivially_copy_assignable<V>::value, ""); - } -} - -template <typename T> struct Result { size_t index; T value; }; - -void test_copy_assignment_same_index() { - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int>; - V v(43); - V v2(42); - v = v2; - return {v.index(), std::get<0>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 0, ""); - static_assert(result.value == 42, ""); - } - { - struct { - constexpr Result<long> operator()() const { - using V = std::variant<int, long, unsigned>; - V v(43l); - V v2(42l); - v = v2; - return {v.index(), std::get<1>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42l, ""); - } - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int, TCopyAssign, unsigned>; - V v(std::in_place_type<TCopyAssign>, 43); - V v2(std::in_place_type<TCopyAssign>, 42); - v = v2; - return {v.index(), std::get<1>(v).value}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>; - V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43); - V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42); - v = v2; - return {v.index(), std::get<1>(v).value}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } -} - -void test_copy_assignment_different_index() { - { - struct { - constexpr Result<long> operator()() const { - using V = std::variant<int, long, unsigned>; - V v(43); - V v2(42l); - v = v2; - return {v.index(), std::get<1>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42l, ""); - } - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int, TCopyAssign, unsigned>; - V v(std::in_place_type<unsigned>, 43); - V v2(std::in_place_type<TCopyAssign>, 42); - v = v2; - return {v.index(), std::get<1>(v).value}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } -} - -template <size_t NewIdx, class ValueType> -constexpr bool test_constexpr_assign_extension_imp( - std::variant<long, void*, int>&& v, ValueType&& new_value) -{ - const std::variant<long, void*, int> cp( - std::forward<ValueType>(new_value)); - v = cp; - return v.index() == NewIdx && - std::get<NewIdx>(v) == std::get<NewIdx>(cp); -} - -void test_constexpr_copy_assignment_extension() { -#ifdef _LIBCPP_VERSION - using V = std::variant<long, void*, int>; - static_assert(std::is_trivially_copyable<V>::value, ""); - static_assert(std::is_trivially_copy_assignable<V>::value, ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); - static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); -#endif -} - -int main() { - test_copy_assignment_same_index(); - test_copy_assignment_different_index(); - test_copy_assignment_sfinae(); - test_constexpr_copy_assignment_extension(); -} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp deleted file mode 100644 index fb6907dc5627..000000000000 --- a/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -*- 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 - -// The following compilers don't generate constexpr special members correctly. -// XFAIL: clang-3.5, clang-3.6, clang-3.7, clang-3.8 -// XFAIL: apple-clang-6, apple-clang-7, apple-clang-8.0 - -// <variant> - -// template <class ...Types> class variant; - -// variant& operator=(variant&&) noexcept(see below); - -#include <type_traits> -#include <variant> - -#include "test_macros.h" - -struct NTMoveAssign { - constexpr NTMoveAssign(int v) : value(v) {} - NTMoveAssign(const NTMoveAssign &) = default; - NTMoveAssign(NTMoveAssign &&) = default; - NTMoveAssign &operator=(const NTMoveAssign &that) = default; - NTMoveAssign &operator=(NTMoveAssign &&that) { - value = that.value; - that.value = -1; - return *this; - }; - int value; -}; - -static_assert(!std::is_trivially_move_assignable<NTMoveAssign>::value, ""); -static_assert(std::is_move_assignable<NTMoveAssign>::value, ""); - -struct TMoveAssign { - constexpr TMoveAssign(int v) : value(v) {} - TMoveAssign(const TMoveAssign &) = delete; - TMoveAssign(TMoveAssign &&) = default; - TMoveAssign &operator=(const TMoveAssign &) = delete; - TMoveAssign &operator=(TMoveAssign &&) = default; - int value; -}; - -static_assert(std::is_trivially_move_assignable<TMoveAssign>::value, ""); - -struct TMoveAssignNTCopyAssign { - constexpr TMoveAssignNTCopyAssign(int v) : value(v) {} - TMoveAssignNTCopyAssign(const TMoveAssignNTCopyAssign &) = default; - TMoveAssignNTCopyAssign(TMoveAssignNTCopyAssign &&) = default; - TMoveAssignNTCopyAssign &operator=(const TMoveAssignNTCopyAssign &that) { - value = that.value; - return *this; - } - TMoveAssignNTCopyAssign &operator=(TMoveAssignNTCopyAssign &&) = default; - int value; -}; - -static_assert(std::is_trivially_move_assignable_v<TMoveAssignNTCopyAssign>, ""); - -void test_move_assignment_sfinae() { - { - using V = std::variant<int, long>; - static_assert(std::is_trivially_move_assignable<V>::value, ""); - } - { - using V = std::variant<int, NTMoveAssign>; - static_assert(!std::is_trivially_move_assignable<V>::value, ""); - static_assert(std::is_move_assignable<V>::value, ""); - } - { - using V = std::variant<int, TMoveAssign>; - static_assert(std::is_trivially_move_assignable<V>::value, ""); - } - { - using V = std::variant<int, TMoveAssignNTCopyAssign>; - static_assert(std::is_trivially_move_assignable<V>::value, ""); - } -} - -template <typename T> struct Result { size_t index; T value; }; - -void test_move_assignment_same_index() { - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int>; - V v(43); - V v2(42); - v = std::move(v2); - return {v.index(), std::get<0>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 0, ""); - static_assert(result.value == 42, ""); - } - { - struct { - constexpr Result<long> operator()() const { - using V = std::variant<int, long, unsigned>; - V v(43l); - V v2(42l); - v = std::move(v2); - return {v.index(), std::get<1>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42l, ""); - } - { - struct { - constexpr Result<int> operator()() const { - using V = std::variant<int, TMoveAssign, unsigned>; - V v(std::in_place_type<TMoveAssign>, 43); - V v2(std::in_place_type<TMoveAssign>, 42); - v = std::move(v2); - return {v.index(), std::get<1>(v).value}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } -} - -void test_move_assignment_different_index() { - { - struct { - constexpr Result<long> operator()() const { - using V = std::variant<int, long, unsigned>; - V v(43); - V v2(42l); - v = std::move(v2); - return {v.index(), std::get<1>(v)}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42l, ""); - } - { - struct { - constexpr Result<long> operator()() const { - using V = std::variant<int, TMoveAssign, unsigned>; - V v(std::in_place_type<unsigned>, 43); - V v2(std::in_place_type<TMoveAssign>, 42); - v = std::move(v2); - return {v.index(), std::get<1>(v).value}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } -} - - -template <size_t NewIdx, class ValueType> -constexpr bool test_constexpr_assign_extension_imp( - std::variant<long, void*, int>&& v, ValueType&& new_value) -{ - std::variant<long, void*, int> v2( - std::forward<ValueType>(new_value)); - const auto cp = v2; - v = std::move(v2); - return v.index() == NewIdx && - std::get<NewIdx>(v) == std::get<NewIdx>(cp); -} - -void test_constexpr_move_assignment_extension() { -#ifdef _LIBCPP_VERSION - using V = std::variant<long, void*, int>; - static_assert(std::is_trivially_copyable<V>::value, ""); - static_assert(std::is_trivially_move_assignable<V>::value, ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); - static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); - static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); -#endif -} - -int main() { - test_move_assignment_same_index(); - test_move_assignment_different_index(); - test_move_assignment_sfinae(); - test_constexpr_move_assignment_extension(); -} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp deleted file mode 100644 index 0d30a78a48ac..000000000000 --- a/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -*- 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 <type_traits> -#include <variant> - -#include "test_macros.h" - -struct NTCopy { - constexpr NTCopy(int v) : value(v) {} - NTCopy(const NTCopy &that) : value(that.value) {} - NTCopy(NTCopy &&) = delete; - int value; -}; - -static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, ""); -static_assert(std::is_copy_constructible<NTCopy>::value, ""); - -struct TCopy { - constexpr TCopy(int v) : value(v) {} - TCopy(TCopy const &) = default; - TCopy(TCopy &&) = delete; - int value; -}; - -static_assert(std::is_trivially_copy_constructible<TCopy>::value, ""); - -struct TCopyNTMove { - constexpr TCopyNTMove(int v) : value(v) {} - TCopyNTMove(const TCopyNTMove&) = default; - TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; } - int value; -}; - -static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, ""); - -void test_copy_ctor_sfinae() { - { - using V = std::variant<int, long>; - static_assert(std::is_trivially_copy_constructible<V>::value, ""); - } - { - using V = std::variant<int, NTCopy>; - static_assert(!std::is_trivially_copy_constructible<V>::value, ""); - static_assert(std::is_copy_constructible<V>::value, ""); - } - { - using V = std::variant<int, TCopy>; - static_assert(std::is_trivially_copy_constructible<V>::value, ""); - } - { - using V = std::variant<int, TCopyNTMove>; - static_assert(std::is_trivially_copy_constructible<V>::value, ""); - } -} - -void test_copy_ctor_basic() { - { - constexpr std::variant<int> v(std::in_place_index<0>, 42); - static_assert(v.index() == 0, ""); - constexpr std::variant<int> v2 = v; - static_assert(v2.index() == 0, ""); - static_assert(std::get<0>(v2) == 42, ""); - } - { - constexpr std::variant<int, long> v(std::in_place_index<1>, 42); - static_assert(v.index() == 1, ""); - constexpr std::variant<int, long> v2 = v; - static_assert(v2.index() == 1, ""); - static_assert(std::get<1>(v2) == 42, ""); - } - { - constexpr std::variant<TCopy> v(std::in_place_index<0>, 42); - static_assert(v.index() == 0, ""); - constexpr std::variant<TCopy> v2(v); - static_assert(v2.index() == 0, ""); - static_assert(std::get<0>(v2).value == 42, ""); - } - { - constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42); - static_assert(v.index() == 1, ""); - constexpr std::variant<int, TCopy> v2(v); - static_assert(v2.index() == 1, ""); - static_assert(std::get<1>(v2).value == 42, ""); - } - { - constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42); - static_assert(v.index() == 0, ""); - constexpr std::variant<TCopyNTMove> v2(v); - static_assert(v2.index() == 0, ""); - static_assert(std::get<0>(v2).value == 42, ""); - } - { - constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42); - static_assert(v.index() == 1, ""); - constexpr std::variant<int, TCopyNTMove> v2(v); - static_assert(v2.index() == 1, ""); - static_assert(std::get<1>(v2).value == 42, ""); - } -} - -int main() { - test_copy_ctor_basic(); - test_copy_ctor_sfinae(); -} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp deleted file mode 100644 index 91e8c194d144..000000000000 --- a/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -*- 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 <type_traits> -#include <variant> - -#include "test_macros.h" - -struct NTMove { - constexpr NTMove(int v) : value(v) {} - NTMove(const NTMove &) = delete; - NTMove(NTMove &&that) : value(that.value) { that.value = -1; } - int value; -}; - -static_assert(!std::is_trivially_move_constructible<NTMove>::value, ""); -static_assert(std::is_move_constructible<NTMove>::value, ""); - -struct TMove { - constexpr TMove(int v) : value(v) {} - TMove(const TMove &) = delete; - TMove(TMove &&) = default; - int value; -}; - -static_assert(std::is_trivially_move_constructible<TMove>::value, ""); - -struct TMoveNTCopy { - constexpr TMoveNTCopy(int v) : value(v) {} - TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {} - TMoveNTCopy(TMoveNTCopy&&) = default; - int value; -}; - -static_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, ""); - -void test_move_ctor_sfinae() { - { - using V = std::variant<int, long>; - static_assert(std::is_trivially_move_constructible<V>::value, ""); - } - { - using V = std::variant<int, NTMove>; - static_assert(!std::is_trivially_move_constructible<V>::value, ""); - static_assert(std::is_move_constructible<V>::value, ""); - } - { - using V = std::variant<int, TMove>; - static_assert(std::is_trivially_move_constructible<V>::value, ""); - } - { - using V = std::variant<int, TMoveNTCopy>; - static_assert(std::is_trivially_move_constructible<V>::value, ""); - } -} - -template <typename T> -struct Result { size_t index; T value; }; - -void test_move_ctor_basic() { - { - struct { - constexpr Result<int> operator()() const { - std::variant<int> v(std::in_place_index<0>, 42); - std::variant<int> v2 = std::move(v); - return {v2.index(), std::get<0>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 0, ""); - static_assert(result.value == 42, ""); - } - { - struct { - constexpr Result<long> operator()() const { - std::variant<int, long> v(std::in_place_index<1>, 42); - std::variant<int, long> v2 = std::move(v); - return {v2.index(), std::get<1>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value == 42, ""); - } - { - struct { - constexpr Result<TMove> operator()() const { - std::variant<TMove> v(std::in_place_index<0>, 42); - std::variant<TMove> v2(std::move(v)); - return {v2.index(), std::get<0>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 0, ""); - static_assert(result.value.value == 42, ""); - } - { - struct { - constexpr Result<TMove> operator()() const { - std::variant<int, TMove> v(std::in_place_index<1>, 42); - std::variant<int, TMove> v2(std::move(v)); - return {v2.index(), std::get<1>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value.value == 42, ""); - } - { - struct { - constexpr Result<TMoveNTCopy> operator()() const { - std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42); - std::variant<TMoveNTCopy> v2(std::move(v)); - return {v2.index(), std::get<0>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 0, ""); - static_assert(result.value.value == 42, ""); - } - { - struct { - constexpr Result<TMoveNTCopy> operator()() const { - std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42); - std::variant<int, TMoveNTCopy> v2(std::move(v)); - return {v2.index(), std::get<1>(std::move(v2))}; - } - } test; - constexpr auto result = test(); - static_assert(result.index == 1, ""); - static_assert(result.value.value == 42, ""); - } -} - -int main() { - test_move_ctor_basic(); - test_move_ctor_sfinae(); -} diff --git a/test/std/localization/locale.categories/category.ctype/locale.codecvt.byname/ctor_char.pass.cpp b/test/std/localization/locale.categories/category.ctype/locale.codecvt.byname/ctor_char.pass.cpp index 349577835ec6..24c2f23f0db7 100644 --- a/test/std/localization/locale.categories/category.ctype/locale.codecvt.byname/ctor_char.pass.cpp +++ b/test/std/localization/locale.categories/category.ctype/locale.codecvt.byname/ctor_char.pass.cpp @@ -17,6 +17,8 @@ #include <locale> #include <cassert> +#include "platform_support.h" + typedef std::codecvt_byname<char, char, std::mbstate_t> F; class my_facet @@ -38,12 +40,12 @@ int my_facet::count = 0; int main() { { - std::locale l(std::locale::classic(), new my_facet("en_US")); + std::locale l(std::locale::classic(), new my_facet(LOCALE_en_US)); assert(my_facet::count == 1); } assert(my_facet::count == 0); { - my_facet f("en_US", 1); + my_facet f(LOCALE_en_US, 1); assert(my_facet::count == 1); { std::locale l(std::locale::classic(), &f); @@ -53,12 +55,12 @@ int main() } assert(my_facet::count == 0); { - std::locale l(std::locale::classic(), new my_facet(std::string("en_US"))); + std::locale l(std::locale::classic(), new my_facet(std::string(LOCALE_en_US))); assert(my_facet::count == 1); } assert(my_facet::count == 0); { - my_facet f(std::string("en_US"), 1); + my_facet f(std::string(LOCALE_en_US), 1); assert(my_facet::count == 1); { std::locale l(std::locale::classic(), &f); diff --git a/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter.pass.cpp b/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter.pass.cpp new file mode 100644 index 000000000000..6fdd288e2d6a --- /dev/null +++ b/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter.pass.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <numeric> +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// template<class InputIterator, class OutputIterator, class T> +// OutputIterator exclusive_scan(InputIterator first, InputIterator last, +// OutputIterator result, T init); +// + +#include <numeric> +#include <vector> +#include <cassert> + +#include "test_iterators.h" + +template <class Iter1, class T, class Iter2> +void +test(Iter1 first, Iter1 last, T init, Iter2 rFirst, Iter2 rLast) +{ + std::vector<typename std::iterator_traits<Iter1>::value_type> v; + +// Not in place + std::exclusive_scan(first, last, std::back_inserter(v), init); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); + +// In place + v.clear(); + v.assign(first, last); + std::exclusive_scan(v.begin(), v.end(), v.begin(), init); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); +} + + +template <class Iter> +void +test() +{ + int ia[] = {1, 3, 5, 7, 9}; + const int pRes[] = {0, 1, 4, 9, 16}; + const unsigned sa = sizeof(ia) / sizeof(ia[0]); + static_assert(sa == sizeof(pRes) / sizeof(pRes[0])); // just to be sure + + for (unsigned int i = 0; i < sa; ++i ) + test(Iter(ia), Iter(ia + i), 0, pRes, pRes + i); +} + +int triangle(int n) { return n*(n+1)/2; } + +// Basic sanity +void basic_tests() +{ + { + std::vector<int> v(10); + std::fill(v.begin(), v.end(), 3); + std::exclusive_scan(v.begin(), v.end(), v.begin(), 50); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 50 + (int) i * 3); + } + + { + std::vector<int> v(10); + std::iota(v.begin(), v.end(), 0); + std::exclusive_scan(v.begin(), v.end(), v.begin(), 30); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 30 + triangle(i-1)); + } + + { + std::vector<int> v(10); + std::iota(v.begin(), v.end(), 1); + std::exclusive_scan(v.begin(), v.end(), v.begin(), 40); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 40 + triangle(i)); + } + +} + +int main() +{ + basic_tests(); + +// All the iterator categories + test<input_iterator <const int*> >(); + test<forward_iterator <const int*> >(); + test<bidirectional_iterator<const int*> >(); + test<random_access_iterator<const int*> >(); + test<const int*>(); + test< int*>(); +} diff --git a/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter_init_op.pass.cpp b/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter_init_op.pass.cpp new file mode 100644 index 000000000000..ba1673fe467f --- /dev/null +++ b/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_iter_iter_iter_init_op.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <numeric> +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// template<class InputIterator, class OutputIterator, class T, class BinaryOperation> +// OutputIterator +// exclusive_scan(InputIterator first, InputIterator last, +// OutputIterator result, +// T init, BinaryOperation binary_op); // C++17 + +#include <numeric> +#include <vector> +#include <cassert> + +#include "test_iterators.h" + +template <class Iter1, class T, class Op, class Iter2> +void +test(Iter1 first, Iter1 last, T init, Op op, Iter2 rFirst, Iter2 rLast) +{ + std::vector<typename std::iterator_traits<Iter1>::value_type> v; + +// Not in place + std::exclusive_scan(first, last, std::back_inserter(v), init, op); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); + +// In place + v.clear(); + v.assign(first, last); + std::exclusive_scan(v.begin(), v.end(), v.begin(), init, op); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); +} + + +template <class Iter> +void +test() +{ + int ia[] = {1, 3, 5, 7, 9}; + const int pRes[] = {0, 1, 4, 9, 16}; + const int mRes[] = {1, 1, 3, 15, 105}; + const unsigned sa = sizeof(ia) / sizeof(ia[0]); + static_assert(sa == sizeof(pRes) / sizeof(pRes[0])); // just to be sure + static_assert(sa == sizeof(mRes) / sizeof(mRes[0])); // just to be sure + + for (unsigned int i = 0; i < sa; ++i ) { + test(Iter(ia), Iter(ia + i), 0, std::plus<>(), pRes, pRes + i); + test(Iter(ia), Iter(ia + i), 1, std::multiplies<>(), mRes, mRes + i); + } +} + +int main() +{ +// All the iterator categories + test<input_iterator <const int*> >(); + test<forward_iterator <const int*> >(); + test<bidirectional_iterator<const int*> >(); + test<random_access_iterator<const int*> >(); + test<const int*>(); + test< int*>(); + +// Make sure that the calculations are done using the init typedef + { + std::vector<unsigned char> v(10); + std::iota(v.begin(), v.end(), 1); + std::vector<int> res; + std::exclusive_scan(v.begin(), v.end(), std::back_inserter(res), 1, std::multiplies<>()); + + assert(res.size() == 10); + int j = 1; + assert(res[0] == 1); + for (size_t i = 1; i < v.size(); ++i) + { + j *= i; + assert(res[i] == j); + } + } +} +
\ No newline at end of file diff --git a/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_iter_iter_iter_init_bop_uop.pass.cpp b/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_iter_iter_iter_init_bop_uop.pass.cpp new file mode 100644 index 000000000000..3bfb336a03f9 --- /dev/null +++ b/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_iter_iter_iter_init_bop_uop.pass.cpp @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <numeric> +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// template<class InputIterator, class OutputIterator, class T, +// class BinaryOperation, class UnaryOperation> +// OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last, +// OutputIterator result, T init, +// BinaryOperation binary_op, +// UnaryOperation unary_op); + + +#include <numeric> +#include <vector> +#include <cassert> +#include <iostream> + +#include "test_iterators.h" + +template <class _Tp = void> +struct identity : std::unary_function<_Tp, _Tp> +{ + constexpr const _Tp& operator()(const _Tp& __x) const { return __x;} +}; + +template <> +struct identity<void> +{ + template <class _Tp> + constexpr auto operator()(_Tp&& __x) const + _NOEXCEPT_(noexcept(_VSTD::forward<_Tp>(__x))) + -> decltype (_VSTD::forward<_Tp>(__x)) + { return _VSTD::forward<_Tp>(__x); } +}; + +template <class Iter1, class BOp, class UOp, class T, class Iter2> +void +test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast) +{ + std::vector<typename std::iterator_traits<Iter1>::value_type> v; +// Test not in-place + std::transform_exclusive_scan(first, last, std::back_inserter(v), init, bop, uop); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); + +// Test in-place + v.clear(); + v.assign(first, last); + std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), init, bop, uop); + assert(std::equal(v.begin(), v.end(), rFirst, rLast)); +} + + +template <class Iter> +void +test() +{ + int ia[] = { 1, 3, 5, 7, 9}; + const int pResI0[] = { 0, 1, 4, 9, 16}; // with identity + const int mResI0[] = { 0, 0, 0, 0, 0}; + const int pResN0[] = { 0, -1, -4, -9, -16}; // with negate + const int mResN0[] = { 0, 0, 0, 0, 0}; + const int pResI2[] = { 2, 3, 6, 11, 18}; // with identity + const int mResI2[] = { 2, 2, 6, 30, 210}; + const int pResN2[] = { 2, 1, -2, -7, -14}; // with negate + const int mResN2[] = { 2, -2, 6, -30, 210}; + const unsigned sa = sizeof(ia) / sizeof(ia[0]); + static_assert(sa == sizeof(pResI0) / sizeof(pResI0[0])); // just to be sure + static_assert(sa == sizeof(mResI0) / sizeof(mResI0[0])); // just to be sure + static_assert(sa == sizeof(pResN0) / sizeof(pResN0[0])); // just to be sure + static_assert(sa == sizeof(mResN0) / sizeof(mResN0[0])); // just to be sure + static_assert(sa == sizeof(pResI2) / sizeof(pResI2[0])); // just to be sure + static_assert(sa == sizeof(mResI2) / sizeof(mResI2[0])); // just to be sure + static_assert(sa == sizeof(pResN2) / sizeof(pResN2[0])); // just to be sure + static_assert(sa == sizeof(mResN2) / sizeof(mResN2[0])); // just to be sure + + for (unsigned int i = 0; i < sa; ++i ) { + test(Iter(ia), Iter(ia + i), std::plus<>(), identity<>(), 0, pResI0, pResI0 + i); + test(Iter(ia), Iter(ia + i), std::multiplies<>(), identity<>(), 0, mResI0, mResI0 + i); + test(Iter(ia), Iter(ia + i), std::plus<>(), std::negate<>(), 0, pResN0, pResN0 + i); + test(Iter(ia), Iter(ia + i), std::multiplies<>(), std::negate<>(), 0, mResN0, mResN0 + i); + test(Iter(ia), Iter(ia + i), std::plus<>(), identity<>(), 2, pResI2, pResI2 + i); + test(Iter(ia), Iter(ia + i), std::multiplies<>(), identity<>(), 2, mResI2, mResI2 + i); + test(Iter(ia), Iter(ia + i), std::plus<>(), std::negate<>(), 2, pResN2, pResN2 + i); + test(Iter(ia), Iter(ia + i), std::multiplies<>(), std::negate<>(), 2, mResN2, mResN2 + i); + } +} + +int triangle(int n) { return n*(n+1)/2; } + +// Basic sanity +void basic_tests() +{ + { + std::vector<int> v(10); + std::fill(v.begin(), v.end(), 3); + std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 50, std::plus<>(), identity<>()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 50 + (int) i * 3); + } + + { + std::vector<int> v(10); + std::iota(v.begin(), v.end(), 0); + std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 30, std::plus<>(), identity<>()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 30 + triangle(i-1)); + } + + { + std::vector<int> v(10); + std::iota(v.begin(), v.end(), 1); + std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), 40, std::plus<>(), identity<>()); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == 40 + triangle(i)); + } + +// Make sure that the calculations are done using the init typedef + { + std::vector<unsigned char> v(10); + std::iota(v.begin(), v.end(), 1); + std::vector<int> res; + std::transform_exclusive_scan(v.begin(), v.end(), std::back_inserter(res), 1, std::multiplies<>(), identity<>()); + + assert(res.size() == 10); + int j = 1; + assert(res[0] == 1); + for (size_t i = 1; i < res.size(); ++i) + { + j *= i; + assert(res[i] == j); + } + } +} + +int main() +{ + basic_tests(); + +// All the iterator categories + test<input_iterator <const int*> >(); + test<forward_iterator <const int*> >(); + test<bidirectional_iterator<const int*> >(); + test<random_access_iterator<const int*> >(); + test<const int*>(); + test< int*>(); +} diff --git a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp index 4de42fbd0243..48c3a73a06cc 100644 --- a/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp +++ b/test/std/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/default.pass.cpp @@ -16,8 +16,10 @@ // mutex(); #include <mutex> +#include <type_traits> int main() { + static_assert(std::is_nothrow_default_constructible<std::mutex>::value, ""); std::mutex m; } diff --git a/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp index cee73da849b6..8fcd1860843d 100644 --- a/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp +++ b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp @@ -48,7 +48,6 @@ int main() assert(X::dtor_called == false); assert(static_cast<bool>(opt) == false); } - assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 { optional<X> opt(X{}); X::dtor_called = false; @@ -57,5 +56,4 @@ int main() assert(static_cast<bool>(opt) == false); X::dtor_called = false; } - assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 } diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp index c219e9704716..f94dcabde513 100644 --- a/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp +++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 // <optional> -// template <class U> T optional<T>::value_or(U&& v) &&; +// template <class U> constexpr T optional<T>::value_or(U&& v) &&; #include <optional> #include <type_traits> @@ -26,22 +26,22 @@ struct Y { int i_; - Y(int i) : i_(i) {} + constexpr Y(int i) : i_(i) {} }; struct X { int i_; - X(int i) : i_(i) {} - X(X&& x) : i_(x.i_) {x.i_ = 0;} - X(const Y& y) : i_(y.i_) {} - X(Y&& y) : i_(y.i_+1) {} + constexpr X(int i) : i_(i) {} + constexpr X(X&& x) : i_(x.i_) {x.i_ = 0;} + constexpr X(const Y& y) : i_(y.i_) {} + constexpr X(Y&& y) : i_(y.i_+1) {} friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} }; -int main() +constexpr int test() { { optional<X> opt(in_place, 2); @@ -65,4 +65,10 @@ int main() assert(std::move(opt).value_or(Y(3)) == 4); assert(!opt); } + return 0; +} + +int main() +{ + static_assert(test() == 0); } diff --git a/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp new file mode 100644 index 000000000000..7b9c061b3ae8 --- /dev/null +++ b/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-deduction-guides + +// GCC's implementation of class template deduction is still immature and runs +// into issues with libc++. However GCC accepts this code when compiling +// against libstdc++. +// XFAIL: gcc + +// <string> + +// Test that the constructors offered by std::basic_string are formulated +// so they're compatible with implicit deduction guides. + +#include <tuple> +#include <memory> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + + +// Overloads +// using A = Allocator +// using AT = std::allocator_arg_t +// --------------- +// (1) tuple(const Types&...) -> tuple<Types...> +// (2) explicit tuple(const Types&...) -> tuple<Types...> +// (3) tuple(AT, A const&, Types const&...) -> tuple<Types...> +// (4) explicit tuple(AT, A const&, Types const&...) -> tuple<Types...> +// (5) tuple(tuple const& t) -> decltype(t) +// (6) tuple(tuple&& t) -> decltype(t) +// (7) tuple(AT, A const&, tuple const& t) -> decltype(t) +// (8) tuple(AT, A const&, tuple&& t) -> decltype(t) +void test_primary_template() +{ + const std::allocator<int> A; + const auto AT = std::allocator_arg; + { // Testing (1) + int x = 101; + std::tuple t1(42); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>); + std::tuple t2(x, 0.0, nullptr); + ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, decltype(nullptr)>); + } + { // Testing (2) + using T = ExplicitTestTypes::TestType; + static_assert(!std::is_convertible<T const&, T>::value, ""); + + std::tuple t1(T{}); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>); + + const T v{}; + std::tuple t2(T{}, 101l, v); + ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>); + } + { // Testing (3) + int x = 101; + std::tuple t1(AT, A, 42); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>); + + std::tuple t2(AT, A, 42, 0.0, x); + ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, int>); + } + { // Testing (4) + using T = ExplicitTestTypes::TestType; + static_assert(!std::is_convertible<T const&, T>::value, ""); + + std::tuple t1(AT, A, T{}); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<T>); + + const T v{}; + std::tuple t2(AT, A, T{}, 101l, v); + ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>); + } + { // Testing (5) + using Tup = std::tuple<int, decltype(nullptr)>; + const Tup t(42, nullptr); + + std::tuple t1(t); + ASSERT_SAME_TYPE(decltype(t1), Tup); + } + { // Testing (6) + using Tup = std::tuple<void*, unsigned, char>; + std::tuple t1(Tup(nullptr, 42, 'a')); + ASSERT_SAME_TYPE(decltype(t1), Tup); + } + { // Testing (7) + using Tup = std::tuple<int, decltype(nullptr)>; + const Tup t(42, nullptr); + + std::tuple t1(AT, A, t); + ASSERT_SAME_TYPE(decltype(t1), Tup); + } + { // Testing (8) + using Tup = std::tuple<void*, unsigned, char>; + std::tuple t1(AT, A, Tup(nullptr, 42, 'a')); + ASSERT_SAME_TYPE(decltype(t1), Tup); + } +} + +// Overloads +// using A = Allocator +// using AT = std::allocator_arg_t +// --------------- +// (1) tuple() -> tuple<> +// (2) tuple(AT, A const&) -> tuple<> +// (3) tuple(tuple const&) -> tuple<> +// (4) tuple(tuple&&) -> tuple<> +// (5) tuple(AT, A const&, tuple const&) -> tuple<> +// (6) tuple(AT, A const&, tuple&&) -> tuple<> +void test_empty_specialization() +{ + std::allocator<int> A; + const auto AT = std::allocator_arg; + { // Testing (1) + std::tuple t1{}; + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } + { // Testing (2) + std::tuple t1{AT, A}; + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } + { // Testing (3) + const std::tuple<> t{}; + std::tuple t1(t); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } + { // Testing (4) + std::tuple t1(std::tuple<>{}); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } + { // Testing (5) + const std::tuple<> t{}; + std::tuple t1(AT, A, t); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } + { // Testing (6) + std::tuple t1(AT, A, std::tuple<>{}); + ASSERT_SAME_TYPE(decltype(t1), std::tuple<>); + } +} + +int main() { + test_primary_template(); + test_empty_specialization(); +} diff --git a/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp index dd5880ea6635..29228e562d69 100644 --- a/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -68,6 +68,28 @@ struct ThrowsCtorT { } }; +struct MoveCrashes { + int value; + MoveCrashes(int v = 0) noexcept : value{v} {} + MoveCrashes(MoveCrashes &&) noexcept { assert(false); } + MoveCrashes &operator=(MoveCrashes &&) noexcept { assert(false); return *this; } + MoveCrashes &operator=(int v) noexcept { + value = v; + return *this; + } +}; + +struct ThrowsCtorTandMove { + int value; + ThrowsCtorTandMove() : value(0) {} + ThrowsCtorTandMove(int) noexcept(false) { throw 42; } + ThrowsCtorTandMove(ThrowsCtorTandMove &&) noexcept(false) { assert(false); } + ThrowsCtorTandMove &operator=(int v) noexcept { + value = v; + return *this; + } +}; + struct ThrowsAssignT { int value; ThrowsAssignT() : value(0) {} @@ -126,7 +148,7 @@ void test_T_assignment_sfinae() { using V = std::variant<int, const int &>; static_assert(!std::is_assignable<V, int>::value, "ambiguous"); } -#endif +#endif // TEST_VARIANT_HAS_NO_REFERENCES } void test_T_assignment_basic() { @@ -163,7 +185,7 @@ void test_T_assignment_basic() { assert(v.index() == 2); assert(std::get<2>(v) == 42); } -#endif +#endif // TEST_VARIANT_HAS_NO_REFERENCES } void test_T_assignment_performs_construction() { @@ -174,9 +196,11 @@ void test_T_assignment_performs_construction() { V v(std::in_place_type<std::string>, "hello"); try { v = 42; + assert(false); } catch (...) { /* ... */ } - assert(v.valueless_by_exception()); + assert(v.index() == 0); + assert(std::get<0>(v) == "hello"); } { using V = std::variant<ThrowsAssignT, std::string>; @@ -185,7 +209,7 @@ void test_T_assignment_performs_construction() { assert(v.index() == 0); assert(std::get<0>(v).value == 42); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } void test_T_assignment_performs_assignment() { @@ -227,7 +251,7 @@ void test_T_assignment_performs_assignment() { assert(v.index() == 1); assert(std::get<1>(v).value == 100); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } int main() { diff --git a/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp index 4f0009d9d620..068b9a201566 100644 --- a/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -10,6 +10,10 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 +// The following compilers don't generate constexpr special members correctly. +// XFAIL: clang-3.5, clang-3.6, clang-3.7, clang-3.8 +// XFAIL: apple-clang-6, apple-clang-7, apple-clang-8.0 + // XFAIL: with_system_cxx_lib=macosx10.12 // XFAIL: with_system_cxx_lib=macosx10.11 // XFAIL: with_system_cxx_lib=macosx10.10 @@ -35,11 +39,6 @@ struct NoCopy { NoCopy &operator=(const NoCopy &) = default; }; -struct NothrowCopy { - NothrowCopy(const NothrowCopy &) noexcept = default; - NothrowCopy &operator=(const NothrowCopy &) noexcept = default; -}; - struct CopyOnly { CopyOnly(const CopyOnly &) = default; CopyOnly(CopyOnly &&) = delete; @@ -73,7 +72,7 @@ struct CopyAssign { ++alive; ++copy_construct; } - CopyAssign(CopyAssign &&o) : value(o.value) { + CopyAssign(CopyAssign &&o) noexcept : value(o.value) { o.value = -1; ++alive; ++move_construct; @@ -83,7 +82,7 @@ struct CopyAssign { ++copy_assign; return *this; } - CopyAssign &operator=(CopyAssign &&o) { + CopyAssign &operator=(CopyAssign &&o) noexcept { value = o.value; o.value = -1; ++move_assign; @@ -108,6 +107,48 @@ struct CopyDoesThrow { CopyDoesThrow &operator=(const CopyDoesThrow &) noexcept(false); }; + +struct NTCopyAssign { + constexpr NTCopyAssign(int v) : value(v) {} + NTCopyAssign(const NTCopyAssign &) = default; + NTCopyAssign(NTCopyAssign &&) = default; + NTCopyAssign &operator=(const NTCopyAssign &that) { + value = that.value; + return *this; + }; + NTCopyAssign &operator=(NTCopyAssign &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, ""); +static_assert(std::is_copy_assignable<NTCopyAssign>::value, ""); + +struct TCopyAssign { + constexpr TCopyAssign(int v) : value(v) {} + TCopyAssign(const TCopyAssign &) = default; + TCopyAssign(TCopyAssign &&) = default; + TCopyAssign &operator=(const TCopyAssign &) = default; + TCopyAssign &operator=(TCopyAssign &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, ""); + +struct TCopyAssignNTMoveAssign { + constexpr TCopyAssignNTMoveAssign(int v) : value(v) {} + TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default; + TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + } + int value; +}; + +static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>, ""); + #ifndef TEST_HAS_NO_EXCEPTIONS struct CopyThrows { CopyThrows() = default; @@ -115,6 +156,17 @@ struct CopyThrows { CopyThrows &operator=(const CopyThrows &) { throw 42; } }; +struct CopyCannotThrow { + static int alive; + CopyCannotThrow() { ++alive; } + CopyCannotThrow(const CopyCannotThrow &) noexcept { ++alive; } + CopyCannotThrow(CopyCannotThrow &&) noexcept { assert(false); } + CopyCannotThrow &operator=(const CopyCannotThrow &) noexcept = default; + CopyCannotThrow &operator=(CopyCannotThrow &&) noexcept { assert(false); return *this; } +}; + +int CopyCannotThrow::alive = 0; + struct MoveThrows { static int alive; MoveThrows() { ++alive; } @@ -146,7 +198,7 @@ int MakeEmptyT::alive = 0; template <class Variant> void makeEmpty(Variant &v) { Variant v2(std::in_place_type<MakeEmptyT>); try { - v = v2; + v = std::move(v2); assert(false); } catch (...) { assert(v.valueless_by_exception()); @@ -171,10 +223,8 @@ void test_copy_assignment_sfinae() { static_assert(std::is_copy_assignable<V>::value, ""); } { - // variant only provides copy assignment when both the copy and move - // constructors are well formed using V = std::variant<int, CopyOnly>; - static_assert(!std::is_copy_assignable<V>::value, ""); + static_assert(std::is_copy_assignable<V>::value, ""); } { using V = std::variant<int, NoCopy>; @@ -188,6 +238,29 @@ void test_copy_assignment_sfinae() { using V = std::variant<int, MoveOnlyNT>; static_assert(!std::is_copy_assignable<V>::value, ""); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTCopyAssign>; + static_assert(!std::is_trivially_copy_assignable<V>::value, ""); + static_assert(std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssignNTMoveAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, CopyOnly>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } } void test_copy_assignment_empty_empty() { @@ -204,7 +277,7 @@ void test_copy_assignment_empty_empty() { assert(v1.valueless_by_exception()); assert(v1.index() == std::variant_npos); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } void test_copy_assignment_non_empty_empty() { @@ -230,7 +303,7 @@ void test_copy_assignment_non_empty_empty() { assert(v1.valueless_by_exception()); assert(v1.index() == std::variant_npos); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } void test_copy_assignment_empty_non_empty() { @@ -256,9 +329,11 @@ void test_copy_assignment_empty_non_empty() { assert(v1.index() == 2); assert(std::get<2>(v1) == "hello"); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } +template <typename T> struct Result { size_t index; T value; }; + void test_copy_assignment_same_index() { { using V = std::variant<int>; @@ -306,7 +381,65 @@ void test_copy_assignment_same_index() { assert(v1.index() == 1); assert(&std::get<1>(v1) == &mref); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS + + // The following tests are for not-yet-standardized behavior (P0602): + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = v2; + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0, ""); + static_assert(result.value == 42, ""); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42l, ""); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<TCopyAssign>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>; + V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43); + V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } } void test_copy_assignment_different_index() { @@ -338,8 +471,6 @@ void test_copy_assignment_different_index() { } #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>); @@ -348,24 +479,31 @@ void test_copy_assignment_different_index() { assert(false); } catch (...) { /* ... */ } - assert(v1.index() == 2); - assert(std::get<2>(v1) == "hello"); + // Test that copy construction is used directly if move construction may throw, + // resulting in a valueless variant if copy throws. + assert(v1.valueless_by_exception()); } { - // 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()); + // Test that copy construction is used directly if move construction may throw. + v1 = v2; + assert(v1.index() == 1); assert(v2.index() == 1); - assert(MoveThrows::alive == 1); + assert(MoveThrows::alive == 2); + } + { + // Test that direct copy construction is preferred when it cannot throw. + using V = std::variant<int, CopyCannotThrow, std::string>; + V v1(std::in_place_type<std::string>, "hello"); + V v2(std::in_place_type<CopyCannotThrow>); + assert(CopyCannotThrow::alive == 1); + v1 = v2; + assert(v1.index() == 1); + assert(v2.index() == 1); + assert(CopyCannotThrow::alive == 2); } { using V = std::variant<int, CopyThrows, std::string>; @@ -389,9 +527,60 @@ void test_copy_assignment_different_index() { assert(v2.index() == 2); assert(std::get<2>(v2) == "hello"); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS + + // The following tests are for not-yet-standardized behavior (P0602): + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42l, ""); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } +} + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + const std::variant<long, void*, int> cp( + std::forward<ValueType>(new_value)); + v = cp; + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); } +void test_constexpr_copy_assignment_extension() { + // The following tests are for not-yet-standardized behavior (P0602): + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); +} int main() { test_copy_assignment_empty_empty(); @@ -401,4 +590,5 @@ int main() { test_copy_assignment_different_index(); test_copy_assignment_sfinae(); test_copy_assignment_not_noexcept(); + test_constexpr_copy_assignment_extension(); } diff --git a/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp index c1ba87be76d1..c410b4b8f3ef 100644 --- a/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -10,6 +10,10 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 +// The following compilers don't generate constexpr special members correctly. +// XFAIL: clang-3.5, clang-3.6, clang-3.7, clang-3.8 +// XFAIL: apple-clang-6, apple-clang-7, apple-clang-8.0 + // XFAIL: with_system_cxx_lib=macosx10.12 // XFAIL: with_system_cxx_lib=macosx10.11 // XFAIL: with_system_cxx_lib=macosx10.10 @@ -91,6 +95,60 @@ struct MoveAssign { int MoveAssign::move_construct = 0; int MoveAssign::move_assign = 0; +struct NTMoveAssign { + constexpr NTMoveAssign(int v) : value(v) {} + NTMoveAssign(const NTMoveAssign &) = default; + NTMoveAssign(NTMoveAssign &&) = default; + NTMoveAssign &operator=(const NTMoveAssign &that) = default; + NTMoveAssign &operator=(NTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + }; + int value; +}; + +static_assert(!std::is_trivially_move_assignable<NTMoveAssign>::value, ""); +static_assert(std::is_move_assignable<NTMoveAssign>::value, ""); + +struct TMoveAssign { + constexpr TMoveAssign(int v) : value(v) {} + TMoveAssign(const TMoveAssign &) = delete; + TMoveAssign(TMoveAssign &&) = default; + TMoveAssign &operator=(const TMoveAssign &) = delete; + TMoveAssign &operator=(TMoveAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable<TMoveAssign>::value, ""); + +struct TMoveAssignNTCopyAssign { + constexpr TMoveAssignNTCopyAssign(int v) : value(v) {} + TMoveAssignNTCopyAssign(const TMoveAssignNTCopyAssign &) = default; + TMoveAssignNTCopyAssign(TMoveAssignNTCopyAssign &&) = default; + TMoveAssignNTCopyAssign &operator=(const TMoveAssignNTCopyAssign &that) { + value = that.value; + return *this; + } + TMoveAssignNTCopyAssign &operator=(TMoveAssignNTCopyAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable_v<TMoveAssignNTCopyAssign>, ""); + +struct TrivialCopyNontrivialMove { + TrivialCopyNontrivialMove(TrivialCopyNontrivialMove const&) = default; + TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) noexcept {} + TrivialCopyNontrivialMove& operator=(TrivialCopyNontrivialMove const&) = default; + TrivialCopyNontrivialMove& operator=(TrivialCopyNontrivialMove&&) noexcept { + return *this; + } +}; + +static_assert(std::is_trivially_copy_assignable_v<TrivialCopyNontrivialMove>, ""); +static_assert(!std::is_trivially_move_assignable_v<TrivialCopyNontrivialMove>, ""); + + void test_move_assignment_noexcept() { { using V = std::variant<int>; @@ -124,10 +182,8 @@ void test_move_assignment_sfinae() { 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, ""); + static_assert(std::is_move_assignable<V>::value, ""); } { using V = std::variant<int, NoCopy>; @@ -147,6 +203,33 @@ void test_move_assignment_sfinae() { using V = std::variant<int, MoveAssignOnly>; static_assert(!std::is_move_assignable<V>::value, ""); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTMoveAssign>; + static_assert(!std::is_trivially_move_assignable<V>::value, ""); + static_assert(std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssignNTCopyAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TrivialCopyNontrivialMove>; + static_assert(!std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, CopyOnly>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } } void test_move_assignment_empty_empty() { @@ -163,7 +246,7 @@ void test_move_assignment_empty_empty() { assert(v1.valueless_by_exception()); assert(v1.index() == std::variant_npos); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } void test_move_assignment_non_empty_empty() { @@ -189,7 +272,7 @@ void test_move_assignment_non_empty_empty() { assert(v1.valueless_by_exception()); assert(v1.index() == std::variant_npos); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } void test_move_assignment_empty_non_empty() { @@ -215,9 +298,11 @@ void test_move_assignment_empty_non_empty() { assert(v1.index() == 2); assert(std::get<2>(v1) == "hello"); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } +template <typename T> struct Result { size_t index; T value; }; + void test_move_assignment_same_index() { { using V = std::variant<int>; @@ -264,7 +349,51 @@ void test_move_assignment_same_index() { assert(v1.index() == 1); assert(&std::get<1>(v1) == &mref); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS + + // The following tests are for not-yet-standardized behavior (P0602): + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = std::move(v2); + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0, ""); + static_assert(result.value == 42, ""); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42l, ""); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<TMoveAssign>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } } void test_move_assignment_different_index() { @@ -312,7 +441,60 @@ void test_move_assignment_different_index() { assert(v1.index() == 2); assert(std::get<2>(v1) == "hello"); } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS + + // The following tests are for not-yet-standardized behavior (P0602): + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42l, ""); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } +} + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + std::variant<long, void*, int> v2( + std::forward<ValueType>(new_value)); + const auto cp = v2; + v = std::move(v2); + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); +} + +void test_constexpr_move_assignment_extension() { + // The following tests are for not-yet-standardized behavior (P0602): + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_move_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); } int main() { @@ -323,4 +505,5 @@ int main() { test_move_assignment_different_index(); test_move_assignment_sfinae(); test_move_assignment_noexcept(); + test_constexpr_move_assignment_extension(); } diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp index 3b20c369c638..f3113435f3ce 100644 --- a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -51,6 +51,34 @@ struct MoveOnlyNT { MoveOnlyNT(MoveOnlyNT &&) {} }; +struct NTCopy { + constexpr NTCopy(int v) : value(v) {} + NTCopy(const NTCopy &that) : value(that.value) {} + NTCopy(NTCopy &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, ""); +static_assert(std::is_copy_constructible<NTCopy>::value, ""); + +struct TCopy { + constexpr TCopy(int v) : value(v) {} + TCopy(TCopy const &) = default; + TCopy(TCopy &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopy>::value, ""); + +struct TCopyNTMove { + constexpr TCopyNTMove(int v) : value(v) {} + TCopyNTMove(const TCopyNTMove&) = default; + TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, ""); + #ifndef TEST_HAS_NO_EXCEPTIONS struct MakeEmptyT { static int alive; @@ -71,7 +99,7 @@ int MakeEmptyT::alive = 0; template <class Variant> void makeEmpty(Variant &v) { Variant v2(std::in_place_type<MakeEmptyT>); try { - v = v2; + v = std::move(v2); assert(false); } catch (...) { assert(v.valueless_by_exception()); @@ -96,6 +124,25 @@ void test_copy_ctor_sfinae() { using V = std::variant<int, MoveOnlyNT>; static_assert(!std::is_copy_constructible<V>::value, ""); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTCopy>; + static_assert(!std::is_trivially_copy_constructible<V>::value, ""); + static_assert(std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopy>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopyNTMove>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } } void test_copy_ctor_basic() { @@ -125,6 +172,50 @@ void test_copy_ctor_basic() { assert(v2.index() == 1); assert(std::get<1>(v2).value == 42); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + constexpr std::variant<int> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0, ""); + constexpr std::variant<int> v2 = v; + static_assert(v2.index() == 0, ""); + static_assert(std::get<0>(v2) == 42, ""); + } + { + constexpr std::variant<int, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + constexpr std::variant<int, long> v2 = v; + static_assert(v2.index() == 1, ""); + static_assert(std::get<1>(v2) == 42, ""); + } + { + constexpr std::variant<TCopy> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0, ""); + constexpr std::variant<TCopy> v2(v); + static_assert(v2.index() == 0, ""); + static_assert(std::get<0>(v2).value == 42, ""); + } + { + constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + constexpr std::variant<int, TCopy> v2(v); + static_assert(v2.index() == 1, ""); + static_assert(std::get<1>(v2).value == 42, ""); + } + { + constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0, ""); + constexpr std::variant<TCopyNTMove> v2(v); + static_assert(v2.index() == 0, ""); + static_assert(std::get<0>(v2).value == 42, ""); + } + { + constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + constexpr std::variant<int, TCopyNTMove> v2(v); + static_assert(v2.index() == 1, ""); + static_assert(std::get<1>(v2).value == 42, ""); + } } void test_copy_ctor_valueless_by_exception() { @@ -135,7 +226,7 @@ void test_copy_ctor_valueless_by_exception() { const V &cv1 = v1; V v(cv1); assert(v.valueless_by_exception()); -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } template <size_t Idx> @@ -149,7 +240,7 @@ constexpr bool test_constexpr_copy_ctor_extension_imp( } void test_constexpr_copy_ctor_extension() { - // NOTE: This test is for not yet standardized behavior. + // NOTE: This test is for not yet standardized behavior. (P0602) using V = std::variant<long, void*, const int>; #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_destructible<V>::value, ""); @@ -157,9 +248,9 @@ void test_constexpr_copy_ctor_extension() { static_assert(std::is_trivially_move_constructible<V>::value, ""); static_assert(!std::is_copy_assignable<V>::value, ""); static_assert(!std::is_move_assignable<V>::value, ""); -#else +#else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_copyable<V>::value, ""); -#endif +#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), ""); static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), ""); static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), ""); diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp index a5de1f77334e..6b392068d5a9 100644 --- a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp +++ b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -53,6 +53,34 @@ struct MoveOnlyNT { MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; } }; +struct NTMove { + constexpr NTMove(int v) : value(v) {} + NTMove(const NTMove &) = delete; + NTMove(NTMove &&that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(!std::is_trivially_move_constructible<NTMove>::value, ""); +static_assert(std::is_move_constructible<NTMove>::value, ""); + +struct TMove { + constexpr TMove(int v) : value(v) {} + TMove(const TMove &) = delete; + TMove(TMove &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMove>::value, ""); + +struct TMoveNTCopy { + constexpr TMoveNTCopy(int v) : value(v) {} + TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {} + TMoveNTCopy(TMoveNTCopy&&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, ""); + #ifndef TEST_HAS_NO_EXCEPTIONS struct MakeEmptyT { static int alive; @@ -73,7 +101,7 @@ int MakeEmptyT::alive = 0; template <class Variant> void makeEmpty(Variant &v) { Variant v2(std::in_place_type<MakeEmptyT>); try { - v = v2; + v = std::move(v2); assert(false); } catch (...) { assert(v.valueless_by_exception()); @@ -117,8 +145,30 @@ void test_move_ctor_sfinae() { using V = std::variant<int, NoCopy>; static_assert(!std::is_move_constructible<V>::value, ""); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTMove>; + static_assert(!std::is_trivially_move_constructible<V>::value, ""); + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMove>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMoveNTCopy>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } } +template <typename T> +struct Result { size_t index; T value; }; + void test_move_ctor_basic() { { std::variant<int> v(std::in_place_index<0>, 42); @@ -162,6 +212,80 @@ void test_move_ctor_basic() { assert(std::get<1>(v).value == -1); assert(std::get<1>(v2).value == 42); } + + // The following tests are for not-yet-standardized behavior (P0602): + { + struct { + constexpr Result<int> operator()() const { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = std::move(v); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0, ""); + static_assert(result.value == 42, ""); + } + { + struct { + constexpr Result<long> operator()() const { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = std::move(v); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value == 42, ""); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<TMove> v(std::in_place_index<0>, 42); + std::variant<TMove> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0, ""); + static_assert(result.value.value == 42, ""); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<int, TMove> v(std::in_place_index<1>, 42); + std::variant<int, TMove> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value.value == 42, ""); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42); + std::variant<TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0, ""); + static_assert(result.value.value == 42, ""); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42); + std::variant<int, TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1, ""); + static_assert(result.value.value == 42, ""); + } } void test_move_ctor_valueless_by_exception() { @@ -171,7 +295,7 @@ void test_move_ctor_valueless_by_exception() { makeEmpty(v1); V v(std::move(v1)); assert(v.valueless_by_exception()); -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } template <size_t Idx> @@ -186,7 +310,7 @@ constexpr bool test_constexpr_ctor_extension_imp( } void test_constexpr_move_ctor_extension() { - // NOTE: This test is for not yet standardized behavior. + // NOTE: This test is for not yet standardized behavior. (P0602) using V = std::variant<long, void*, const int>; #ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_destructible<V>::value, ""); @@ -194,9 +318,9 @@ void test_constexpr_move_ctor_extension() { static_assert(std::is_trivially_move_constructible<V>::value, ""); static_assert(!std::is_copy_assignable<V>::value, ""); static_assert(!std::is_move_assignable<V>::value, ""); -#else +#else // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_copyable<V>::value, ""); -#endif +#endif // TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE static_assert(std::is_trivially_move_constructible<V>::value, ""); static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), ""); static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), ""); diff --git a/test/support/msvc_stdlib_force_include.hpp b/test/support/msvc_stdlib_force_include.hpp index 6bcc97952199..954cf513ef2d 100644 --- a/test/support/msvc_stdlib_force_include.hpp +++ b/test/support/msvc_stdlib_force_include.hpp @@ -28,11 +28,6 @@ #error This header may not be used when targeting libc++ #endif -// Indicates that we are using the MSVC standard library. -#ifndef _MSVC_STL_VER - #define _MSVC_STL_VER 42 -#endif - #ifndef _LIBCXX_IN_DEVCRT struct AssertionDialogAvoider { AssertionDialogAvoider() { @@ -81,6 +76,9 @@ const AssertionDialogAvoider assertion_dialog_avoider{}; // Silence warnings about raw pointers and other unchecked iterators. #define _SCL_SECURE_NO_WARNINGS + + // Silence warnings about features that are deprecated in C++17. + #define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS #endif // _LIBCXX_IN_DEVCRT #include <ciso646> diff --git a/test/support/platform_support.h b/test/support/platform_support.h index 737e5d7a01ce..a9b5b98a3668 100644 --- a/test/support/platform_support.h +++ b/test/support/platform_support.h @@ -19,16 +19,18 @@ #ifdef _WIN32 // WARNING: Windows does not support UTF-8 codepages. // Locales are "converted" using http://docs.moodle.org/dev/Table_of_locales -#define LOCALE_en_US_UTF_8 "English_United States.1252" -#define LOCALE_cs_CZ_ISO8859_2 "Czech_Czech Republic.1250" -#define LOCALE_fr_FR_UTF_8 "French_France.1252" -#define LOCALE_fr_CA_ISO8859_1 "French_Canada.1252" -#define LOCALE_ru_RU_UTF_8 "Russian_Russia.1251" -#define LOCALE_zh_CN_UTF_8 "Chinese_China.936" +#define LOCALE_en_US "en-US" +#define LOCALE_en_US_UTF_8 "en-US" +#define LOCALE_cs_CZ_ISO8859_2 "cs-CZ" +#define LOCALE_fr_FR_UTF_8 "fr-FR" +#define LOCALE_fr_CA_ISO8859_1 "fr-CA" +#define LOCALE_ru_RU_UTF_8 "ru-RU" +#define LOCALE_zh_CN_UTF_8 "zh-CN" #elif defined(__CloudABI__) // Timezones are integrated into locales through LC_TIMEZONE_MASK on // CloudABI. LC_ALL_MASK can only be used if a timezone has also been // provided. UTC should be all right. +#define LOCALE_en_US "en_US" #define LOCALE_en_US_UTF_8 "en_US.UTF-8@UTC" #define LOCALE_fr_FR_UTF_8 "fr_FR.UTF-8@UTC" #define LOCALE_fr_CA_ISO8859_1 "fr_CA.ISO-8859-1@UTC" @@ -36,6 +38,7 @@ #define LOCALE_ru_RU_UTF_8 "ru_RU.UTF-8@UTC" #define LOCALE_zh_CN_UTF_8 "zh_CN.UTF-8@UTC" #else +#define LOCALE_en_US "en_US" #define LOCALE_en_US_UTF_8 "en_US.UTF-8" #define LOCALE_fr_FR_UTF_8 "fr_FR.UTF-8" #ifdef __linux__ diff --git a/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp b/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp deleted file mode 100644 index f25a9c9984cc..000000000000 --- a/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 - -// Verify TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION. - -#include <type_traits> - -#include "test_workarounds.h" - -template<class T> -struct identity { - using type = T; -}; - -template<class...> struct list {}; - -// C1XX believes this function template is not viable when LArgs is an empty -// parameter pack. -template <class ...LArgs> -int f2(typename identity<LArgs>::type..., int i) { - return i; -} - -#ifdef TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION -// C1XX believes this function template *is* viable when LArgs is an empty -// parameter pack. Conforming compilers believe the two overloads are -// ambiguous when LArgs is an empty pack. -template <class ...LArgs> -int f2(int i) { - return i; -} -#endif - -template <class ...LArgs, class ...Args> -int f1(list<LArgs...>, Args&&... args) { - return f2<LArgs const&...>(args...); -} - -int main() { - f1(list<>{}, 42); -} diff --git a/test/support/test_workarounds.h b/test/support/test_workarounds.h index ae123d7e41d0..e88a14957d31 100644 --- a/test/support/test_workarounds.h +++ b/test/support/test_workarounds.h @@ -19,7 +19,6 @@ #if defined(TEST_COMPILER_C1XX) # define TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE // VSO#117743 -# define TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION // VSO#109062 # ifndef _MSC_EXTENSIONS # define TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK // VSO#119998 # endif diff --git a/test/support/uses_alloc_types.hpp b/test/support/uses_alloc_types.hpp index 7f92f0fd19c7..426d2583ef80 100644 --- a/test/support/uses_alloc_types.hpp +++ b/test/support/uses_alloc_types.hpp @@ -257,13 +257,6 @@ private: return alloc; } -#ifdef TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION - template <class ...LArgs> - static CtorAlloc getAllocatorFromPackImp(CtorAlloc const& alloc) { - return alloc; - } -#endif - bool has_alloc() const { return alloc_store.get_allocator() != nullptr; } const CtorAlloc *get_alloc() const { return alloc_store.get_allocator(); } public: diff --git a/test/support/variant_test_helpers.hpp b/test/support/variant_test_helpers.hpp index 277167233714..75981546467b 100644 --- a/test/support/variant_test_helpers.hpp +++ b/test/support/variant_test_helpers.hpp @@ -69,9 +69,9 @@ template <class Variant> void makeEmpty(Variant& v) { Variant v2(std::in_place_type<MakeEmptyT>); try { - v = v2; + v = std::move(v2); assert(false); - } catch (...) { + } catch (...) { assert(v.valueless_by_exception()); } } diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index 80b53021c1f0..bd33b6e3c574 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -46,7 +46,7 @@ <li>SG1 - Study group #1 (Concurrency working group)</li> </ul> </p> - + <h3>Paper Status</h3> <table id="papers" border="1"> <tr><th>Paper #</th><th>Group</th><th>Paper Name</th><th>Meeting</th><th>Status</th><th>First released version</th></tr> @@ -477,7 +477,7 @@ <tr><td><a href="http://wg21.link/LWG2890">2890</a></td><td>The definition of 'object state' applies only to class types</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://wg21.link/LWG2903">2903</a></td><td>The form of initialization for the emplace-constructors is not specified</td><td>Kona</td><td></td></tr> - <tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td></td></tr> + <tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://wg21.link/LWG2908">2908</a></td><td>The less-than operator for shared pointers could do more</td><td>Kona</td><td></td></tr> <tr><td><a href="http://wg21.link/LWG2911">2911</a></td><td>An is_aggregate type trait is needed</td><td>Kona</td><td>Complete</td></tr> |