diff options
author | Louis Dionne <ldionne@apple.com> | 2019-01-10 20:06:11 +0000 |
---|---|---|
committer | Louis Dionne <ldionne@apple.com> | 2019-01-10 20:06:11 +0000 |
commit | 1d5f6a81f577d62688946e3ffbcf2643f03fa507 (patch) | |
tree | 4327bda2860847a2b716545a10d533709f4730e1 /libcxx/test/std/utilities/optional | |
parent | 7d1085cbb020f68014ba938314e9136bb9e811a1 (diff) | |
download | bcm5719-llvm-1d5f6a81f577d62688946e3ffbcf2643f03fa507.tar.gz bcm5719-llvm-1d5f6a81f577d62688946e3ffbcf2643f03fa507.zip |
[libcxx] Reorganize tests since the application of P0602R4
Summary:
P0602R4 makes the special member functions of optional and variant
conditionally trivial based on the types in the optional/variant.
We already implemented that, but the tests were organized as if this
were a non-standard extension. This patch reorganizes the tests in a
way that makes more sense since this is not an extension anymore.
Reviewers: EricWF, mpark, mclow.lists
Subscribers: christof, jkorous, dexonsmith, libcxx-commits
Differential Revision: https://reviews.llvm.org/D54772
llvm-svn: 350884
Diffstat (limited to 'libcxx/test/std/utilities/optional')
6 files changed, 201 insertions, 141 deletions
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp index 98c90aa1d4f..bec0f09a3e9 100644 --- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 // <optional> -// optional<T>& operator=(const optional<T>& rhs); +// optional<T>& operator=(const optional<T>& rhs); // constexpr in C++20 #include <optional> #include <type_traits> @@ -53,15 +53,19 @@ int main() { { using O = optional<int>; +#if TEST_STD_VER > 17 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif assert(assign_empty(O{42})); assert(assign_value(O{42})); } { using O = optional<TrivialTestTypes::TestType>; +#if TEST_STD_VER > 17 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif assert(assign_empty(O{42})); assert(assign_value(O{42})); } diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp index ed8b433da69..c41674f13cf 100644 --- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -12,11 +12,12 @@ // optional<T>& operator=(optional<T>&& rhs) // noexcept(is_nothrow_move_assignable<T>::value && -// is_nothrow_move_constructible<T>::value); +// is_nothrow_move_constructible<T>::value); // constexpr in C++20 #include <optional> -#include <type_traits> #include <cassert> +#include <type_traits> +#include <utility> #include "test_macros.h" #include "archetypes.hpp" @@ -51,6 +52,21 @@ struct Y {}; bool X::throw_now = false; int X::alive = 0; + +template <class Tp> +constexpr bool assign_empty(optional<Tp>&& lhs) { + optional<Tp> rhs; + lhs = std::move(rhs); + return !lhs.has_value() && !rhs.has_value(); +} + +template <class Tp> +constexpr bool assign_value(optional<Tp>&& lhs) { + optional<Tp> rhs(101); + lhs = std::move(rhs); + return lhs.has_value() && rhs.has_value() && *lhs == Tp{101}; +} + int main() { { @@ -97,6 +113,24 @@ int main() assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); assert(*opt == *opt2); } + { + using O = optional<int>; +#if TEST_STD_VER > 17 + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TrivialTestTypes::TestType>; +#if TEST_STD_VER > 17 + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); +#endif + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } #ifndef TEST_HAS_NO_EXCEPTIONS { static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp deleted file mode 100644 index 5933683487a..00000000000 --- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.fail.cpp +++ /dev/null @@ -1,36 +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, c++11, c++14 -// <optional> - -// constexpr optional(const optional<T>& rhs); -// If is_trivially_copy_constructible_v<T> is true, -// this constructor shall be a constexpr constructor. - -#include <optional> -#include <type_traits> -#include <cassert> - -#include "test_macros.h" - -struct S { - constexpr S() : v_(0) {} - S(int v) : v_(v) {} - S(const S &rhs) : v_(rhs.v_) {} // make it not trivially copyable - int v_; -}; - - -int main() -{ - static_assert (!std::is_trivially_copy_constructible_v<S>, "" ); - constexpr std::optional<S> o1; - constexpr std::optional<S> o2 = o1; // not constexpr -} diff --git a/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp deleted file mode 100644 index 0b9b6e717c3..00000000000 --- a/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp +++ /dev/null @@ -1,102 +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, c++11, c++14 -// <optional> - - -#include <optional> -#include <type_traits> -#include <cassert> - -#include "archetypes.hpp" - -template <class T> -struct SpecialMemberTest { - using O = std::optional<T>; - - static_assert(std::is_default_constructible_v<O>, - "optional is always default constructible."); - static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, - "optional<T> is copy constructible if and only if T is copy constructible."); - static_assert(std::is_move_constructible_v<O> == - (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), - "optional<T> is move constructible if and only if T is copy or move constructible."); - static_assert(std::is_copy_assignable_v<O> == - (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), - "optional<T> is copy assignable if and only if T is both copy " - "constructible and copy assignable."); - static_assert(std::is_move_assignable_v<O> == - ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) || - (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)), - "optional<T> is move assignable if and only if T is both move constructible and " - "move assignable, or both copy constructible and copy assignable."); - - // The following tests are for not-yet-standardized behavior (P0602): - static_assert(std::is_trivially_destructible_v<O> == - std::is_trivially_destructible_v<T>, - "optional<T> is trivially destructible if and only if T is."); - static_assert(std::is_trivially_copy_constructible_v<O> == - std::is_trivially_copy_constructible_v<T>, - "optional<T> is trivially copy constructible if and only if T is."); - static_assert(std::is_trivially_move_constructible_v<O> == - std::is_trivially_move_constructible_v<T> || - (!std::is_move_constructible_v<T> && std::is_trivially_copy_constructible_v<T>), - "optional<T> is trivially move constructible if T is trivially move constructible, " - "or if T is trivially copy constructible and is not move constructible."); - static_assert(std::is_trivially_copy_assignable_v<O> == - (std::is_trivially_destructible_v<T> && - std::is_trivially_copy_constructible_v<T> && - std::is_trivially_copy_assignable_v<T>), - "optional<T> is trivially copy assignable if and only if T is trivially destructible, " - "trivially copy constructible, and trivially copy assignable."); - static_assert(std::is_trivially_move_assignable_v<O> == - (std::is_trivially_destructible_v<T> && - ((std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>) || - ((!std::is_move_constructible_v<T> || !std::is_move_assignable_v<T>) && - std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>))), - "optional<T> is trivially move assignable if T is trivially destructible, and either " - "(1) trivially move constructible and trivially move assignable, or " - "(2) not move constructible or not move assignable, and " - "trivially copy constructible and trivially copy assignable."); -}; - -template <class ...Args> static void sink(Args&&...) {} - -template <class ...TestTypes> -struct DoTestsMetafunction { - DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } -}; - -struct TrivialMoveNonTrivialCopy { - TrivialMoveNonTrivialCopy() = default; - TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} - TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; - TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } - TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; -}; - -struct TrivialCopyNonTrivialMove { - TrivialCopyNonTrivialMove() = default; - TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; - TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} - TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; - TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } -}; - -int main() -{ - sink( - ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, - ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, - NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, - NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, - DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} - ); -} diff --git a/libcxx/test/std/utilities/optional/optional.object/special_members.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/special_members.pass.cpp new file mode 100644 index 00000000000..3bc561cfea3 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/special_members.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <optional> + +// Make sure we properly generate special member functions for optional<T> +// based on the properties of T itself. + +#include <optional> +#include <type_traits> + +#include "archetypes.hpp" + + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(std::is_default_constructible_v<O>, + "optional is always default constructible."); + + static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, + "optional<T> is copy constructible if and only if T is copy constructible."); + + static_assert(std::is_move_constructible_v<O> == + (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), + "optional<T> is move constructible if and only if T is copy or move constructible."); + + static_assert(std::is_copy_assignable_v<O> == + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), + "optional<T> is copy assignable if and only if T is both copy " + "constructible and copy assignable."); + + static_assert(std::is_move_assignable_v<O> == + ((std::is_move_constructible_v<T> && std::is_move_assignable_v<T>) || + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)), + "optional<T> is move assignable if and only if T is both move constructible and " + "move assignable, or both copy constructible and copy assignable."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +int main() { + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{} + ); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp new file mode 100644 index 00000000000..c21c85aad96 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/triviality.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <optional> + +// The following special member functions should propagate the triviality of +// the element held in the optional (see P0602R4): +// +// constexpr optional(const optional& rhs); +// constexpr optional(optional&& rhs) noexcept(see below); +// constexpr optional<T>& operator=(const optional& rhs); +// constexpr optional<T>& operator=(optional&& rhs) noexcept(see below); + + +#include <optional> +#include <type_traits> + +#include "archetypes.hpp" + + +constexpr bool implies(bool p, bool q) { + return !p || q; +} + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(implies(std::is_trivially_copy_constructible_v<T>, + std::is_trivially_copy_constructible_v<O>), + "optional<T> is trivially copy constructible if T is trivially copy constructible."); + + static_assert(implies(std::is_trivially_move_constructible_v<T>, + std::is_trivially_move_constructible_v<O>), + "optional<T> is trivially move constructible if T is trivially move constructible"); + + static_assert(implies(std::is_trivially_copy_constructible_v<T> && + std::is_trivially_copy_assignable_v<T> && + std::is_trivially_destructible_v<T>, + + std::is_trivially_copy_assignable_v<O>), + "optional<T> is trivially copy assignable if T is " + "trivially copy constructible, " + "trivially copy assignable, and " + "trivially destructible"); + + static_assert(implies(std::is_trivially_move_constructible_v<T> && + std::is_trivially_move_assignable_v<T> && + std::is_trivially_destructible_v<T>, + + std::is_trivially_move_assignable_v<O>), + "optional<T> is trivially move assignable if T is " + "trivially move constructible, " + "trivially move assignable, and" + "trivially destructible."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() { + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} |