diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-10-12 07:46:20 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-10-12 07:46:20 +0000 |
commit | a9e659619f592c49b352af16253ec0b79c207956 (patch) | |
tree | afba7c02efb5a36d4fb797262d8b0db50da64c49 /libcxx/test | |
parent | 90d990e034f05f4d9e0354f54205fd3b471f6507 (diff) | |
download | bcm5719-llvm-a9e659619f592c49b352af16253ec0b79c207956.tar.gz bcm5719-llvm-a9e659619f592c49b352af16253ec0b79c207956.zip |
Implement N4606 optional
Summary:
Adapt implementation of Library Fundamentals TS optional into an implementation of N4606 optional.
- Update relational operators per http://wg21.link/P0307
- Update to requirements of http://wg21.link/P0032
- Extension: Implement trivial copy/move construction/assignment for `optional<T>` when `T` is trivially copyable.
Audit P/Rs for optional LWG issues:
- 2756 "C++ WP optional<T> should 'forward' T's implicit conversions" Implemented, which also resolves 2753 "Optional's constructors and assignments need constraints" (modulo my refusal to explicitly delete the move operations, which is a design error that I'm working on correcting in the 2756 P/R).
- 2736 "nullopt_t insufficiently constrained" Already conforming. I've added a test ensuring that `nullopt_t` is not copy-initializable from an empty braced-init-list, which I believe is the root intent of the issue, to avoid regression.
- 2740 "constexpr optional<T>::operator->" Already conforming.
- 2746 "Inconsistency between requirements for emplace between optional and variant" No P/R, but note that the author's '"suggested resolution" is already implemented.
- 2748 "swappable traits for optionals" Already conforming.
- 2753 "Optional's constructors and assignments need constraints" Implemented.
Most of the work for this patch was done by Casey Carter @ Microsoft. Thank you Casey!
Reviewers: mclow.lists, CaseyCarter, EricWF
Differential Revision: https://reviews.llvm.org/D22741
llvm-svn: 283980
Diffstat (limited to 'libcxx/test')
81 files changed, 7141 insertions, 44 deletions
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp new file mode 100644 index 00000000000..e4de92fbd01 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(const Y&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1(const Z1&) = default; + Z1& operator=(Z1&&) = default; + Z1& operator=(const Z1&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = default; + Z2(const Z2&) = delete; + Z2& operator=(Z2&&) = default; + Z2& operator=(const Z2&) = default; +}; + +#if __cplusplus >= 201402 +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = opt2; + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + static_assert(!(std::is_trivially_copy_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_copy_assignable<optional<Z2>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp new file mode 100644 index 00000000000..e2eaa8ce6a0 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional<T>& operator=(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(Y&&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1& operator=(Z1&&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = delete; + Z2& operator=(Z2&&) = default; +}; + +#if __cplusplus >= 201402 +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = std::move(opt2); + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + static_assert(!(std::is_trivially_move_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_move_assignable<optional<Z2>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 00000000000..75e763507b2 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(const Y&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + static_assert(!(std::is_trivially_copy_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_constructible<optional<Z>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 00000000000..e6d9bb8421c --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(Y&&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + static_assert(!(std::is_trivially_move_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_constructible<optional<Z>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp new file mode 100644 index 00000000000..9493d6bb766 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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>; + + template <template <class> class TestMF> + static constexpr bool check_same() { + return TestMF<O>::value == TestMF<T>::value; + } + + // Test that optional inherits the correct trivial/non-trivial members + static_assert(check_same<std::is_trivially_destructible>(), ""); + static_assert(check_same<std::is_trivially_copyable>(), ""); +}; + +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/libcxx/utilities/optional/version.pass.cpp b/libcxx/test/libcxx/utilities/optional/version.pass.cpp new file mode 100644 index 00000000000..e7581b5431b --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <optional> + +#include <optional> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp index 408231f6057..b23a5e45f28 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp @@ -59,7 +59,7 @@ int main() !std::is_nothrow_swappable_with<A&, A&>::value, ""); } { - // test that hetrogenius swap is allowed only if both 'swap(A, B)' and + // test that heterogeneous swap is allowed only if both 'swap(A, B)' and // 'swap(B, A)' are valid. static_assert(std::is_nothrow_swappable_with<A&, B&>::value, ""); static_assert(!std::is_nothrow_swappable_with<A&, C&>::value && diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp new file mode 100644 index 00000000000..e3c7bb5ad27 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// class bad_optional_access is default constructible + +#include <optional> +#include <type_traits> + +int main() +{ + using std::bad_optional_access; + bad_optional_access ex; +} diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp new file mode 100644 index 00000000000..85e36d2c107 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// class bad_optional_access : public logic_error + +#include <optional> +#include <type_traits> + +int main() +{ + using std::bad_optional_access; + + static_assert(std::is_base_of<std::logic_error, bad_optional_access>::value, ""); + static_assert(std::is_convertible<bad_optional_access*, std::logic_error*>::value, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp new file mode 100644 index 00000000000..b54a08f5575 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator==(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator==(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 == T(1)), "" ); + static_assert ( (o2 == T(1)), "" ); + static_assert ( !(o3 == T(1)), "" ); + static_assert ( (o3 == T(2)), "" ); + static_assert ( (o3 == val), "" ); + + static_assert ( !(T(1) == o1), "" ); + static_assert ( (T(1) == o2), "" ); + static_assert ( !(T(1) == o3), "" ); + static_assert ( (T(2) == o3), "" ); + static_assert ( (val == o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp new file mode 100644 index 00000000000..064114fb9db --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator>(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 > T(1)), "" ); + static_assert ( !(o2 > T(1)), "" ); // equal + static_assert ( (o3 > T(1)), "" ); + static_assert ( !(o2 > val), "" ); + static_assert ( !(o3 > val), "" ); // equal + static_assert ( !(o3 > T(3)), "" ); + + static_assert ( (T(1) > o1), "" ); + static_assert ( !(T(1) > o2), "" ); // equal + static_assert ( !(T(1) > o3), "" ); + static_assert ( (val > o2), "" ); + static_assert ( !(val > o3), "" ); // equal + static_assert ( (T(3) > o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp new file mode 100644 index 00000000000..663686cdf34 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator>=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 >= T(1)), "" ); + static_assert ( (o2 >= T(1)), "" ); // equal + static_assert ( (o3 >= T(1)), "" ); + static_assert ( !(o2 >= val), "" ); + static_assert ( (o3 >= val), "" ); // equal + static_assert ( !(o3 >= T(3)), "" ); + + static_assert ( (T(1) >= o1), "" ); + static_assert ( (T(1) >= o2), "" ); // equal + static_assert ( !(T(1) >= o3), "" ); + static_assert ( (val >= o2), "" ); + static_assert ( (val >= o3), "" ); // equal + static_assert ( (T(3) >= o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp new file mode 100644 index 00000000000..05ac5eb12b4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator<=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 <= T(1)), "" ); + static_assert ( (o2 <= T(1)), "" ); // equal + static_assert ( !(o3 <= T(1)), "" ); + static_assert ( (o2 <= val), "" ); + static_assert ( (o3 <= val), "" ); // equal + static_assert ( (o3 <= T(3)), "" ); + + static_assert ( !(T(1) <= o1), "" ); + static_assert ( (T(1) <= o2), "" ); // equal + static_assert ( (T(1) <= o3), "" ); + static_assert ( !(val <= o2), "" ); + static_assert ( (val <= o3), "" ); // equal + static_assert ( !(T(3) <= o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp new file mode 100644 index 00000000000..d1891a286d7 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator<(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 < T(1)), "" ); + static_assert ( !(o2 < T(1)), "" ); // equal + static_assert ( !(o3 < T(1)), "" ); + static_assert ( (o2 < val), "" ); + static_assert ( !(o3 < val), "" ); // equal + static_assert ( (o3 < T(3)), "" ); + + static_assert ( !(T(1) < o1), "" ); + static_assert ( !(T(1) < o2), "" ); // equal + static_assert ( (T(1) < o3), "" ); + static_assert ( !(val < o2), "" ); + static_assert ( !(val < o3), "" ); // equal + static_assert ( !(T(3) < o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp new file mode 100644 index 00000000000..ae2ff808fb2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator!=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 != T(1)), "" ); + static_assert ( !(o2 != T(1)), "" ); + static_assert ( (o3 != T(1)), "" ); + static_assert ( !(o3 != T(2)), "" ); + static_assert ( !(o3 != val), "" ); + + static_assert ( (T(1) != o1), "" ); + static_assert ( !(T(1) != o2), "" ); + static_assert ( (T(1) != o3), "" ); + static_assert ( !(T(2) != o3), "" ); + static_assert ( !(val != o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp b/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp new file mode 100644 index 00000000000..dfdd07ddf45 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> struct hash<optional<T>>; + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + + +int main() +{ + using std::optional; + const std::size_t nullopt_hash = + std::hash<optional<double>>{}(optional<double>{}); + + { + typedef int T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = 2; + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::string T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::string("123"); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::unique_ptr<int> T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::unique_ptr<int>(new int(3)); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp new file mode 100644 index 00000000000..a87a87f877f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt == o1), "" ); + static_assert ( !(nullopt == o2), "" ); + static_assert ( (o1 == nullopt), "" ); + static_assert ( !(o2 == nullopt), "" ); + + static_assert (noexcept(nullopt == o1), ""); + static_assert (noexcept(o1 == nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp new file mode 100644 index 00000000000..3986a0a9265 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt > o1), "" ); + static_assert ( !(nullopt > o2), "" ); + static_assert ( !(o1 > nullopt), "" ); + static_assert ( (o2 > nullopt), "" ); + + static_assert (noexcept(nullopt > o1), ""); + static_assert (noexcept(o1 > nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp new file mode 100644 index 00000000000..9f242727347 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt >= o1), "" ); + static_assert ( !(nullopt >= o2), "" ); + static_assert ( (o1 >= nullopt), "" ); + static_assert ( (o2 >= nullopt), "" ); + + static_assert (noexcept(nullopt >= o1), ""); + static_assert (noexcept(o1 >= nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp new file mode 100644 index 00000000000..8e73247b9d6 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt <= o1), "" ); + static_assert ( (nullopt <= o2), "" ); + static_assert ( (o1 <= nullopt), "" ); + static_assert ( !(o2 <= nullopt), "" ); + + static_assert (noexcept(nullopt <= o1), ""); + static_assert (noexcept(o1 <= nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp new file mode 100644 index 00000000000..39a8e4a3936 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt < o1), "" ); + static_assert ( (nullopt < o2), "" ); + static_assert ( !(o1 < nullopt), "" ); + static_assert ( !(o2 < nullopt), "" ); + + static_assert (noexcept(nullopt < o1), ""); + static_assert (noexcept(o1 < nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp new file mode 100644 index 00000000000..1c96dd42e80 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt != o1), "" ); + static_assert ( (nullopt != o2), "" ); + static_assert ( !(o1 != nullopt), "" ); + static_assert ( (o2 != nullopt), "" ); + + static_assert (noexcept(nullopt != o1), ""); + static_assert (noexcept(o1 != nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp new file mode 100644 index 00000000000..86da5054a70 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// struct nullopt_t{see below}; + +#include <optional> + +using std::optional; +using std::nullopt_t; + +int main() +{ + // I roughly interpret LWG2736 as "it shall not be possible to copy-list-initialize nullopt_t with an + // empty braced-init-list." + nullopt_t foo = {}; +} diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp new file mode 100644 index 00000000000..84bb29fabac --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// struct nullopt_t{see below}; +// constexpr nullopt_t nullopt(unspecified); + +#include <optional> +#include <type_traits> + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +constexpr +int +test(const nullopt_t&) +{ + return 3; +} + +int main() +{ + static_assert((std::is_class<nullopt_t>::value), ""); + static_assert((std::is_empty<nullopt_t>::value), ""); + static_assert((std::is_literal_type<nullopt_t>::value), ""); + static_assert((!std::is_default_constructible<nullopt_t>::value), ""); + + static_assert(test(nullopt) == 3, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp new file mode 100644 index 00000000000..6abdd0db63c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp @@ -0,0 +1,261 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> optional<T>& operator=(U&& v); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct ThrowAssign { + static int dtor_called; + ThrowAssign() = default; + ThrowAssign(int) { TEST_THROW(42); } + ThrowAssign& operator=(int) { + TEST_THROW(42); + } + ~ThrowAssign() { ++dtor_called; } +}; +int ThrowAssign::dtor_called = 0; + +template <class T, class Arg = T, bool Expect = true> +void assert_assignable() { + static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, ""); + static_assert(!std::is_assignable<const optional<T>&, Arg>::value, ""); +} + +struct MismatchType { + explicit MismatchType(int) {} + explicit MismatchType(char*) {} + explicit MismatchType(int*) = delete; + MismatchType& operator=(int) { return *this; } + MismatchType& operator=(int*) { return *this; } + MismatchType& operator=(char*) = delete; +}; + +void test_sfinae() { + using I = TestTypes::TestType; + using E = ExplicitTestTypes::TestType; + assert_assignable<int>(); + assert_assignable<int, int&>(); + assert_assignable<int, int const&>(); + // Implicit test type + assert_assignable<I, I const&>(); + assert_assignable<I, I&&>(); + assert_assignable<I, int>(); + assert_assignable<I, void*, false>(); + // Explicit test type + assert_assignable<E, E const&>(); + assert_assignable<E, E &&>(); + assert_assignable<E, int>(); + assert_assignable<E, void*, false>(); + // Mismatch type + assert_assignable<MismatchType, int>(); + assert_assignable<MismatchType, int*, false>(); + assert_assignable<MismatchType, char*, false>(); +} + +void test_with_test_type() +{ + using T = TestTypes::TestType; + T::reset(); + { // to empty + optional<T> opt; + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(42); + T::reset_constructors(); + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 1); + assert(T::move_assigned == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {}; + assert(static_cast<bool>(opt) == false); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + } +} + +template <class T, class Value = int> +void test_with_type() { + { // to empty + optional<T> opt; + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(Value(42)); + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test const + optional<T> opt(Value(42)); + const T t(Value(3)); + opt = t; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + opt = {Value(1)}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(Value(42)); + opt = {}; + assert(static_cast<bool>(opt) == false); + } +} + +template <class T> +void test_with_type_multi() { + test_with_type<T>(); + { // test default argument + optional<T> opt; + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } +} + +void test_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using T = ThrowAssign; + { + using T = ThrowAssign; + optional<T> opt; + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == false); + } + assert(T::dtor_called == 0); + { + T::dtor_called = 0; + optional<T> opt(std::in_place); + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == true); + assert(T::dtor_called == 0); + } + assert(T::dtor_called == 1); +#endif +} + +enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; + +using Fn = void(*)(); + +int main() +{ + test_sfinae(); + // Test with instrumented type + test_with_test_type(); + // Test with various scalar types + test_with_type<int>(); + test_with_type<MyEnum, MyEnum>(); + test_with_type<int, MyEnum>(); + test_with_type<Fn, Fn>(); + // Test types with multi argument constructors + test_with_type_multi<ConstexprTestTypes::TestType>(); + test_with_type_multi<TrivialTestTypes::TestType>(); + // Test move only types + { + optional<std::unique_ptr<int>> opt; + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + { + optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + test_throws(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp new file mode 100644 index 00000000000..d471c053c90 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// From LWG2451: +// template<class U> +// optional<T>& operator=(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + const optional<int> other(42); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + const optional<int> other(42); + T::reset_constructors(); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt const&>; + const OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = a; + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = std::move(a); + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + } + { + using T = AssignableFrom<OptInt&>; + OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable_v<Opt&, OptInt const&>, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} 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 new file mode 100644 index 00000000000..98c90aa1d4f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(const X&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +template <class Tp> +constexpr bool assign_empty(optional<Tp>&& lhs) { + const optional<Tp> rhs; + lhs = rhs; + return !lhs.has_value() && !rhs.has_value(); +} + +template <class Tp> +constexpr bool assign_value(optional<Tp>&& lhs) { + const optional<Tp> rhs(101); + lhs = rhs; + return lhs.has_value() && rhs.has_value() && *lhs == *rhs; +} + +int main() +{ + { + using O = optional<int>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TrivialTestTypes::TestType>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TestTypes::TestType>; + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + const optional<T> opt2; + assert(T::alive == 1); + opt = opt2; + assert(T::alive == 0); + assert(!opt2.has_value()); + assert(!opt.has_value()); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<X> opt2(X{}); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp new file mode 100644 index 00000000000..be17aa6fc51 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class... Args> void optional<T>::emplace(Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ +public: + static bool dtor_called; + Y() = default; + Y(int) { TEST_THROW(6);} + ~Y() {dtor_called = true;} +}; + +bool Y::dtor_called = false; + +template <class T> +void test_one_arg() { + using Opt = std::optional<T>; + { + Opt opt; + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt; + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { + Opt opt(2); + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt(2); + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } +} + + +template <class T> +void test_multi_arg() +{ + test_one_arg<T>(); + using Opt = std::optional<T>; + Opt opt; + { + opt.emplace(101, 41); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101, 41)); + } + { + Opt opt; + opt.emplace({1, 2, 3, 4}); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // T sets its value to the size of the init list + } + { + Opt opt; + opt.emplace({1, 2, 3, 4, 5}, 6); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(5)); // T sets its value to the size of the init list + } +} + +template <class T> +void test_on_test_type() { + + T::reset(); + optional<T> opt; + assert(T::alive == 0); + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(101); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}, 42); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } +} + + + +int main() +{ + { + test_on_test_type<TestTypes::TestType>(); + test_on_test_type<ExplicitTestTypes::TestType>(); + } + { + using T = int; + test_one_arg<T>(); + test_one_arg<const T>(); + } + { + using T = ConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = TrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitTrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + optional<const int> opt; + opt.emplace(42); + assert(*opt == 42); + opt.emplace(); + assert(*opt == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + Y::dtor_called = false; + { + Y y; + optional<Y> opt(y); + try + { + assert(static_cast<bool>(opt) == true); + assert(Y::dtor_called == false); + opt.emplace(1); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Y::dtor_called == true); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp new file mode 100644 index 00000000000..1c3c69a7030 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U, class... Args> +// void optional<T>::emplace(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <vector> + +#include "test_macros.h" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + constexpr X() : i_(0) {} + constexpr X(int i) : i_(i) {} + constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + ~X() {dtor_called = true;} + + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool X::dtor_called = false; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + { TEST_THROW(6);} + ~Z() {dtor_called = true;} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool Z::dtor_called = false; + +int main() +{ + { + X x; + optional<X> opt(x); + assert(X::dtor_called == false); + opt.emplace({1, 2}); + assert(X::dtor_called == true); + assert(*opt == X({1, 2})); + } + { + optional<std::vector<int>> opt; + opt.emplace({1, 2, 3}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert(*opt == std::vector<int>({1, 2, 3})); + } + { + optional<Y> opt; + opt.emplace({1, 2}); + assert(static_cast<bool>(opt) == true); + assert(*opt == Y({1, 2})); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + Z z; + optional<Z> opt(z); + try + { + assert(static_cast<bool>(opt) == true); + assert(Z::dtor_called == false); + opt.emplace({1, 2}); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Z::dtor_called == true); + } + } +#endif +} 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 new file mode 100644 index 00000000000..3ba261b5246 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// optional<T>& operator=(optional<T>&& rhs) +// noexcept(is_nothrow_move_assignable<T>::value && +// is_nothrow_move_constructible<T>::value); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + static int alive; + + X() { ++alive; } + X(X&&) + { + if (throw_now) + TEST_THROW(6); + ++alive; + } + + X& operator=(X&&) + { + if (throw_now) + TEST_THROW(42); + return *this; + } + + ~X() { assert(alive > 0); --alive; } +}; + +struct Y {}; + +bool X::throw_now = false; +int X::alive = 0; + +int main() +{ + { + static_assert(std::is_nothrow_move_assignable<optional<int>>::value, ""); + optional<int> opt; + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + optional<T> opt2; + assert(T::alive == 1); + opt = std::move(opt2); + assert(T::alive == 0); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::alive = 0; + X::throw_now = false; + optional<X> opt; + optional<X> opt2(X{}); + assert(X::alive == 1); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + assert(X::alive == 1); + } + assert(X::alive == 0); + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::throw_now = false; + optional<X> opt(X{}); + optional<X> opt2(X{}); + assert(X::alive == 2); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 42); + assert(static_cast<bool>(opt) == true); + } + assert(X::alive == 2); + } + assert(X::alive == 0); +#endif // TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, ""); + } + { + struct ThrowsMove { + ThrowsMove() noexcept {} + ThrowsMove(ThrowsMove const&) noexcept {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; } + ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, ""); + struct ThrowsMoveAssign { + ThrowsMoveAssign() noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {} + ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; } + ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept {} + NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; } + NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; } + }; + static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp new file mode 100644 index 00000000000..991f4334304 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// optional<T>& operator=(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + using TT = TestTypes::TestType; + TT::reset(); + { + optional<TT> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + assert(TT::destroyed == 0); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 0); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 0); + TT::reset(); + { + optional<TT> opt(42); + assert(TT::destroyed == 0); + TT::reset_constructors(); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 1); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 1); + TT::reset(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp new file mode 100644 index 00000000000..db7fc19bfb1 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// From LWG2451: +// template <class U> +// optional<T>& operator=(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int &&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +class B {}; +class D : public B {}; + + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + optional<int> other(42); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + optional<int> other(42); + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt&&>; + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } + { + using T = AssignableFrom<OptInt const&&>; + T::reset(); + { + const OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(std::is_assignable<Opt&, OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<std::unique_ptr<B>> opt; + optional<std::unique_ptr<D>> other(new D()); + opt = std::move(other); + assert(static_cast<bool>(opt) == true); + assert(static_cast<bool>(other) == true); + assert(opt->get() != nullptr); + assert(other->get() == nullptr); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp new file mode 100644 index 00000000000..18efd10a30b --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> +// constexpr EXPLICIT optional(U&& u); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" +#include "test_convertible.hpp" + + +using std::optional; + +struct ImplicitThrow +{ + constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + +struct ExplicitThrow +{ + constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + + +template <class To, class From> +constexpr bool implicit_conversion(optional<To>&& opt, const From& v) +{ + using O = optional<To>; + static_assert(test_convertible<O, From>(), ""); + static_assert(!test_convertible<O, void*>(), ""); + static_assert(!test_convertible<O, From, int>(), ""); + return opt && *opt == static_cast<To>(v); +} + +template <class To, class Input, class Expect> +constexpr bool explicit_conversion(Input&& in, const Expect& v) +{ + using O = optional<To>; + static_assert(std::is_constructible<O, Input>::value, ""); + static_assert(!std::is_convertible<Input, O>::value, ""); + static_assert(!std::is_constructible<O, void*>::value, ""); + static_assert(!std::is_constructible<O, Input, int>::value, ""); + optional<To> opt(std::forward<Input>(in)); + return opt && *opt == static_cast<To>(v); +} + +void test_implicit() +{ + { + using T = long long; + static_assert(implicit_conversion<long long>(42, 42), ""); + } + { + using T = long double; + static_assert(implicit_conversion<long double>(3.14, 3.14), ""); + } + { + using T = TrivialTestTypes::TestType; + static_assert(implicit_conversion<T>(42, 42), ""); + } + { + using T = TestTypes::TestType; + assert(implicit_conversion<T>(3, T(3))); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ImplicitThrow; + optional<T> t = 42; + assert(false); + } catch (int) { + } + } +#endif +} + +void test_explicit() { + { + using T = ExplicitTrivialTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + } + { + using T = ExplicitConstexprTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + static_assert(!std::is_convertible<int, T>::value, ""); + } + { + using T = ExplicitTestTypes::TestType; + using O = optional<T>; + T::reset(); + { + assert(explicit_conversion<T>(42, 42)); + assert(T::alive == 0); + } + T::reset(); + { + optional<T> t(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + assert(T::copy_constructed == 0); + assert(t.value().value == 42); + } + assert(T::alive == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ExplicitThrow; + optional<T> t(42); + assert(false); + } catch (int) { + } + } +#endif +} + +int main() { + test_implicit(); + test_explicit(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp new file mode 100644 index 00000000000..3f98d907890 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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 T& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +int main() +{ + { + typedef int T; + constexpr T t(5); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + typedef double T; + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + typedef TestTypes::TestType T; + T::reset(); + const T t(3); + optional<T> opt = t; + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T const&, optional<T>>::value, ""); + T::reset(); + const T t(3); + optional<T> opt(t); + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr T t(3); + constexpr optional<T> opt = {t}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<const T&, optional<T>>::value, ""); + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(const Z&) {throw 6;} + }; + typedef Z T; + try + { + const T t(3); + optional<T> opt(t); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp new file mode 100644 index 00000000000..e12f6cb28f5 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> +// optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = rhs; + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef short U; + typedef int T; + optional<U> rhs; + test<T>(rhs); + } + { + typedef short U; + typedef int T; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs, true); + } + + static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 00000000000..d2b704c95f2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z const& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + const Z z; + const optional<Z> rhs(z); + try + { + optional<Z> lhs(rhs); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + +int main() +{ + test<int>(); + test<int>(3); + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value()); + assert(T::copy_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + test_reference_extension(); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp new file mode 100644 index 00000000000..62795b91f9f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt; + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt; + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt; + assert(static_cast<bool>(opt) == false); + } + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); + // EXTENSIONS +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + test_constexpr<optional<int&>>(); + test_constexpr<optional<const int&>>(); + test_constexpr<optional<int&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&&>>(); +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp new file mode 100644 index 00000000000..64ac05316c2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> +// explicit optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + explicit Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + explicit Z(int i) : i_(i) { TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs, true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp new file mode 100644 index 00000000000..2c6757a9582 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> +// explicit optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(std::move(rhs)); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(std::move(rhs)); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ +public: + explicit Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp new file mode 100644 index 00000000000..9b59b02593b --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class... Args> +// constexpr explicit optional(in_place_t, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(int i, int j) : i_(i), j_(j) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ +public: + Z(int i) {TEST_THROW(6);} +}; + + +int main() +{ + { + constexpr optional<int> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<int> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<int>(in_place, i) {} + }; + + } + { + const optional<X> opt(in_place); + assert(static_cast<bool>(opt) == true); + assert(*opt == X()); + } + { + const optional<X> opt(in_place, 5); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5)); + } + { + const optional<X> opt(in_place, 5, 4); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5, 4)); + } + { + constexpr optional<Y> opt(in_place); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t) + : optional<Y>(in_place) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<Y>(in_place, i) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5, 4); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5, 4), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i, int j) + : optional<Y>(in_place, i, j) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try + { + const optional<Z> opt(in_place, 1); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp new file mode 100644 index 00000000000..6d9f45a97d4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U, class... Args> +// constexpr +// explicit optional(in_place_t, initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <vector> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + {TEST_THROW(6);} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +int main() +{ + { + static_assert(!std::is_constructible<X, std::initializer_list<int>&>::value, ""); + static_assert(!std::is_constructible<optional<X>, std::initializer_list<int>&>::value, ""); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + static_assert(std::is_constructible<optional<Y>, std::initializer_list<int>&>::value, ""); + constexpr optional<Y> opt(in_place, {3, 1}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y{3, 1}, ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, std::initializer_list<int> i) + : optional<Y>(in_place, i) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_constructible<optional<Z>, std::initializer_list<int>&>::value, ""); + try + { + optional<Z> opt(in_place, {3, 1}); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 00000000000..5a4929c5373 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +1,196 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> orig(std::forward<InitArgs>(args)...); + optional<T> rhs(orig); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *orig); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z&& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + Z z; + optional<Z> rhs(std::move(z)); + try + { + optional<Z> lhs(std::move(rhs)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + T::reset_constructors(); + test_ref<T&&>(); + test_ref<T&&>(std::move(t)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&&>(); + test_ref<T const&&>(std::move(t)); + test_ref<T const&&>(std::move(ct)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + + +int main() +{ + test<int>(); + test<int>(3); + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value() == false); + assert(rhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value()); + assert(rhs.has_value()); + assert(lhs.value().value == 42); + assert(rhs.value().value == -1); + assert(T::move_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + struct ThrowsMove { + ThrowsMove() noexcept(false) {} + ThrowsMove(ThrowsMove const&) noexcept(false) {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + }; + static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept(true) {} + }; + static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); + } + { + test_reference_extension(); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp new file mode 100644 index 00000000000..468a00346fc --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt(nullopt); + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp new file mode 100644 index 00000000000..0e180c14ec6 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> +// optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = std::move(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +struct Z +{ + Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<short> rhs; + test<int>(std::move(rhs)); + } + { + optional<short> rhs(short{3}); + test<int>(std::move(rhs)); + } + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } + + static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp new file mode 100644 index 00000000000..496661d922a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp @@ -0,0 +1,148 @@ +//===----------------------------------------------------------------------===// +// +// 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(T&& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + + +using std::optional; + + +class Z +{ +public: + Z(int) {} + Z(Z&&) {TEST_THROW(6);} +}; + + +int main() +{ + { + typedef int T; + constexpr optional<T> opt(T(5)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + typedef double T; + constexpr optional<T> opt(T(3)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = T{3}; + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + T::reset(); + optional<T> opt(T{3}); + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = {3}; + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + assert(T::move_constructed == 0); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {T(3)}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {3}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + constexpr optional<T> opt(T{3}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(Z&&) {throw 6;} + }; + typedef Z T; + try + { + T t(3); + optional<T> opt(std::move(t)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp new file mode 100644 index 00000000000..5132c9a73d0 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// ~optional(); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct PODType { + int value; + int value2; +}; + +class X +{ +public: + static bool dtor_called; + X() = default; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + typedef int T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef double T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef PODType T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef X T; + static_assert(!std::is_trivially_destructible<T>::value, ""); + static_assert(!std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(!std::is_literal_type<optional<T>>::value, ""); + { + X x; + optional<X> opt{x}; + assert(X::dtor_called == false); + } + assert(X::dtor_called == true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp new file mode 100644 index 00000000000..cee73da849b --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void reset() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + static bool dtor_called; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt.reset()) == true, ""); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<X> opt; + static_assert(noexcept(opt.reset()) == true, ""); + assert(X::dtor_called == false); + opt.reset(); + 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; + opt.reset(); + assert(X::dtor_called == true); + assert(static_cast<bool>(opt) == false); + X::dtor_called = false; + } + assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp new file mode 100644 index 00000000000..9820d50f632 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 explicit optional<T>::operator bool() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(bool(opt)); + static_assert(!std::is_convertible<optional<int>, bool>::value, ""); + } + { + constexpr optional<int> opt; + static_assert(!opt, ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp new file mode 100644 index 00000000000..4087cfdf104 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 T& optional<T>::operator*() &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*opt).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*opt).test() == 4); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp new file mode 100644 index 00000000000..0779c9047c9 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 const T& optional<T>::operator*() const &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X const&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*opt).test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*opt).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp new file mode 100644 index 00000000000..78fd992952c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 T&& optional<T>::operator*() const &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const && {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X const &&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*std::move(opt)).test() == 5, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*std::move(opt)).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 5); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp new file mode 100644 index 00000000000..2924123234a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 T&& optional<T>::operator*() &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*std::move(opt)).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X&&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*std::move(opt)).test() == 6); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp new file mode 100644 index 00000000000..5df295d01e2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 bool optional<T>::has_value() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(opt.has_value()); + ASSERT_SAME_TYPE(decltype(opt.has_value()), bool); + } + { + constexpr optional<int> opt; + static_assert(!opt.has_value(), ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt.has_value(), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp new file mode 100644 index 00000000000..2f1648c48c8 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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 T* optional<T>::operator->(); + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + int test() noexcept {return 3;} +}; + +struct Y +{ + constexpr int test() {return 3;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt->test(); +} + +int main() +{ + { + std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert(opt->test() == 3); + } + { + static_assert(test() == 3, ""); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp new file mode 100644 index 00000000000..887edc7114e --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 const T* optional<T>::operator->() const; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} +}; + +struct Y +{ + int test() const noexcept {return 2;} +}; + +struct Z +{ + const Z* operator&() const; + constexpr int test() const {return 1;} +}; + +int main() +{ + { + const std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X const*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert(opt->test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert(opt->test() == 2); + } + { + constexpr optional<Z> opt(Z{}); + static_assert(opt->test() == 1, ""); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp new file mode 100644 index 00000000000..516a79db5f6 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 T& optional<T>::value() &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() & {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt.value().test(); +} + + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X&); + } + { + optional<X> opt; + opt.emplace(); + assert(opt.value().test() == 4); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp new file mode 100644 index 00000000000..6076c509fa4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} + int test() {return 4;} +}; + +int main() +{ + { + constexpr optional<X> opt; + static_assert(opt.value().test() == 3, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp new file mode 100644 index 00000000000..d4038e4efa6 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X const&); + } + { + constexpr optional<X> opt(in_place); + static_assert(opt.value().test() == 3, ""); + } + { + const optional<X> opt(in_place); + assert(opt.value().test() == 3); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp new file mode 100644 index 00000000000..e189d3af688 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 const T& optional<T>::value() const &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X const&&); + } + { + constexpr optional<X> opt(in_place); + static_assert(std::move(opt).value().test() == 5, ""); + } + { + const optional<X> opt(in_place); + assert(std::move(opt).value().test() == 5); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp new file mode 100644 index 00000000000..c219e970471 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> T optional<T>::value_or(U&& v) &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +struct Y +{ + int i_; + + 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) {} + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_;} +}; + +int main() +{ + { + optional<X> opt(in_place, 2); + Y y(3); + assert(std::move(opt).value_or(y) == 2); + assert(*opt == 0); + } + { + optional<X> opt(in_place, 2); + assert(std::move(opt).value_or(Y(3)) == 2); + assert(*opt == 0); + } + { + optional<X> opt; + Y y(3); + assert(std::move(opt).value_or(y) == 3); + assert(!opt); + } + { + optional<X> opt; + assert(std::move(opt).value_or(Y(3)) == 4); + assert(!opt); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp new file mode 100644 index 00000000000..36a85811ba4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> constexpr T optional<T>::value_or(U&& v) const&; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct Y +{ + int i_; + + constexpr Y(int i) : i_(i) {} +}; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} + 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 optional<X> opt(2); + constexpr Y y(3); + static_assert(opt.value_or(y) == 2, ""); + } + { + constexpr optional<X> opt(2); + static_assert(opt.value_or(Y(3)) == 2, ""); + } + { + constexpr optional<X> opt; + constexpr Y y(3); + static_assert(opt.value_or(y) == 3, ""); + } + { + constexpr optional<X> opt; + static_assert(opt.value_or(Y(3)) == 4, ""); + } + { + const optional<X> opt(2); + const Y y(3); + assert(opt.value_or(y) == 2); + } + { + const optional<X> opt(2); + assert(opt.value_or(Y(3)) == 2); + } + { + const optional<X> opt; + const Y y(3); + assert(opt.value_or(y) == 3); + } + { + const optional<X> opt; + assert(opt.value_or(Y(3)) == 4); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp new file mode 100644 index 00000000000..2ef485b7fe5 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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 T& optional<T>::value() &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return std::move(opt).value().test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X&&); + } + { + optional<X> opt; + opt.emplace(); + assert(std::move(opt).value().test() == 6); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp new file mode 100644 index 00000000000..bd9c393e347 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp @@ -0,0 +1,306 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// void swap(optional&) +// noexcept(is_nothrow_move_constructible<T>::value && +// is_nothrow_swappable<T>::value) + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) {TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z& x, Z& y) {TEST_THROW(6);} +}; + + +int main() +{ + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp new file mode 100644 index 00000000000..8a2c77af0ec --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// T shall be an object type and shall satisfy the requirements of Destructible + +#include <optional> + +using std::optional; + +struct X +{ +private: + ~X() {} +}; + +int main() +{ + using std::optional; + { + // expected-error@optional:* 2 {{static_assert failed "instantiation of optional with a reference type is ill-formed}} + optional<int&> opt1; + optional<int&&> opt2; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed"}} + optional<X> opt3; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + optional<void()> opt4; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + // expected-error@optional:* 1+ {{cannot form a reference to 'void'}} + optional<const void> opt4; + } + // FIXME these are garbage diagnostics that Clang should not produce + // expected-error@optional:* 0+ {{is not a base class}} +} 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 new file mode 100644 index 00000000000..fdd0f154f0e --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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_copy_constructible_v<T> && std::is_copy_assignable_v<T>) || + (std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)), + "optional<T> is move assignable if and only if T is both move assignable and " + "move constructible, or both copy constructible and 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/types.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp new file mode 100644 index 00000000000..0230a13dded --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> +// class optional +// { +// public: +// typedef T value_type; +// ... + +#include <optional> +#include <type_traits> + +using std::optional; + +template <class Opt, class T> +void +test() +{ + static_assert(std::is_same<typename Opt::value_type, T>::value, ""); +} + +int main() +{ + test<optional<int>, int>(); + test<optional<const int>, const int>(); + test<optional<double>, double>(); + test<optional<const double>, const double>(); +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp new file mode 100644 index 00000000000..6650b6720a8 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( o1 == o1 , "" ); + static_assert ( o1 == o2 , "" ); + static_assert ( !(o1 == o3), "" ); + static_assert ( !(o1 == o4), "" ); + static_assert ( !(o1 == o5), "" ); + + static_assert ( o2 == o1 , "" ); + static_assert ( o2 == o2 , "" ); + static_assert ( !(o2 == o3), "" ); + static_assert ( !(o2 == o4), "" ); + static_assert ( !(o2 == o5), "" ); + + static_assert ( !(o3 == o1), "" ); + static_assert ( !(o3 == o2), "" ); + static_assert ( o3 == o3 , "" ); + static_assert ( !(o3 == o4), "" ); + static_assert ( o3 == o5 , "" ); + + static_assert ( !(o4 == o1), "" ); + static_assert ( !(o4 == o2), "" ); + static_assert ( !(o4 == o3), "" ); + static_assert ( o4 == o4 , "" ); + static_assert ( !(o4 == o5), "" ); + + static_assert ( !(o5 == o1), "" ); + static_assert ( !(o5 == o2), "" ); + static_assert ( o5 == o3 , "" ); + static_assert ( !(o5 == o4), "" ); + static_assert ( o5 == o5 , "" ); + + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp new file mode 100644 index 00000000000..f9b30449638 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator>= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 >= o1), "" ); + static_assert ( (o1 >= o2), "" ); + static_assert ( !(o1 >= o3), "" ); + static_assert ( !(o1 >= o4), "" ); + static_assert ( !(o1 >= o5), "" ); + + static_assert ( (o2 >= o1), "" ); + static_assert ( (o2 >= o2), "" ); + static_assert ( !(o2 >= o3), "" ); + static_assert ( !(o2 >= o4), "" ); + static_assert ( !(o2 >= o5), "" ); + + static_assert ( (o3 >= o1), "" ); + static_assert ( (o3 >= o2), "" ); + static_assert ( (o3 >= o3), "" ); + static_assert ( !(o3 >= o4), "" ); + static_assert ( (o3 >= o5), "" ); + + static_assert ( (o4 >= o1), "" ); + static_assert ( (o4 >= o2), "" ); + static_assert ( (o4 >= o3), "" ); + static_assert ( (o4 >= o4), "" ); + static_assert ( (o4 >= o5), "" ); + + static_assert ( (o5 >= o1), "" ); + static_assert ( (o5 >= o2), "" ); + static_assert ( (o5 >= o3), "" ); + static_assert ( !(o5 >= o4), "" ); + static_assert ( (o5 >= o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp new file mode 100644 index 00000000000..8a27eb471f2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator> (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 > o1), "" ); + static_assert ( !(o1 > o2), "" ); + static_assert ( !(o1 > o3), "" ); + static_assert ( !(o1 > o4), "" ); + static_assert ( !(o1 > o5), "" ); + + static_assert ( !(o2 > o1), "" ); + static_assert ( !(o2 > o2), "" ); + static_assert ( !(o2 > o3), "" ); + static_assert ( !(o2 > o4), "" ); + static_assert ( !(o2 > o5), "" ); + + static_assert ( (o3 > o1), "" ); + static_assert ( (o3 > o2), "" ); + static_assert ( !(o3 > o3), "" ); + static_assert ( !(o3 > o4), "" ); + static_assert ( !(o3 > o5), "" ); + + static_assert ( (o4 > o1), "" ); + static_assert ( (o4 > o2), "" ); + static_assert ( (o4 > o3), "" ); + static_assert ( !(o4 > o4), "" ); + static_assert ( (o4 > o5), "" ); + + static_assert ( (o5 > o1), "" ); + static_assert ( (o5 > o2), "" ); + static_assert ( !(o5 > o3), "" ); + static_assert ( !(o5 > o4), "" ); + static_assert ( !(o5 > o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp new file mode 100644 index 00000000000..a7d594dd34a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator<= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 <= o1), "" ); + static_assert ( (o1 <= o2), "" ); + static_assert ( (o1 <= o3), "" ); + static_assert ( (o1 <= o4), "" ); + static_assert ( (o1 <= o5), "" ); + + static_assert ( (o2 <= o1), "" ); + static_assert ( (o2 <= o2), "" ); + static_assert ( (o2 <= o3), "" ); + static_assert ( (o2 <= o4), "" ); + static_assert ( (o2 <= o5), "" ); + + static_assert ( !(o3 <= o1), "" ); + static_assert ( !(o3 <= o2), "" ); + static_assert ( (o3 <= o3), "" ); + static_assert ( (o3 <= o4), "" ); + static_assert ( (o3 <= o5), "" ); + + static_assert ( !(o4 <= o1), "" ); + static_assert ( !(o4 <= o2), "" ); + static_assert ( !(o4 <= o3), "" ); + static_assert ( (o4 <= o4), "" ); + static_assert ( !(o4 <= o5), "" ); + + static_assert ( !(o5 <= o1), "" ); + static_assert ( !(o5 <= o2), "" ); + static_assert ( (o5 <= o3), "" ); + static_assert ( (o5 <= o4), "" ); + static_assert ( (o5 <= o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp new file mode 100644 index 00000000000..deffa5e849f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator< (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 < o1), "" ); + static_assert ( !(o1 < o2), "" ); + static_assert ( (o1 < o3), "" ); + static_assert ( (o1 < o4), "" ); + static_assert ( (o1 < o5), "" ); + + static_assert ( !(o2 < o1), "" ); + static_assert ( !(o2 < o2), "" ); + static_assert ( (o2 < o3), "" ); + static_assert ( (o2 < o4), "" ); + static_assert ( (o2 < o5), "" ); + + static_assert ( !(o3 < o1), "" ); + static_assert ( !(o3 < o2), "" ); + static_assert ( !(o3 < o3), "" ); + static_assert ( (o3 < o4), "" ); + static_assert ( !(o3 < o5), "" ); + + static_assert ( !(o4 < o1), "" ); + static_assert ( !(o4 < o2), "" ); + static_assert ( !(o4 < o3), "" ); + static_assert ( !(o4 < o4), "" ); + static_assert ( !(o4 < o5), "" ); + + static_assert ( !(o5 < o1), "" ); + static_assert ( !(o5 < o2), "" ); + static_assert ( !(o5 < o3), "" ); + static_assert ( (o5 < o4), "" ); + static_assert ( !(o5 < o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp new file mode 100644 index 00000000000..fd11b2a207c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 != o1), "" ); + static_assert ( !(o1 != o2), "" ); + static_assert ( (o1 != o3), "" ); + static_assert ( (o1 != o4), "" ); + static_assert ( (o1 != o5), "" ); + + static_assert ( !(o2 != o1), "" ); + static_assert ( !(o2 != o2), "" ); + static_assert ( (o2 != o3), "" ); + static_assert ( (o2 != o4), "" ); + static_assert ( (o2 != o5), "" ); + + static_assert ( (o3 != o1), "" ); + static_assert ( (o3 != o2), "" ); + static_assert ( !(o3 != o3), "" ); + static_assert ( (o3 != o4), "" ); + static_assert ( !(o3 != o5), "" ); + + static_assert ( (o4 != o1), "" ); + static_assert ( (o4 != o2), "" ); + static_assert ( (o4 != o3), "" ); + static_assert ( !(o4 != o4), "" ); + static_assert ( (o4 != o5), "" ); + + static_assert ( (o5 != o1), "" ); + static_assert ( (o5 != o2), "" ); + static_assert ( !(o5 != o3), "" ); + static_assert ( (o5 != o4), "" ); + static_assert ( !(o5 != o5), "" ); + + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp new file mode 100644 index 00000000000..3fbf19f8ee1 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> +// constexpr optional<decay_t<T>> make_optional(T&& v); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + using std::make_optional; + { + int arr[10]; ((void)arr); + ASSERT_SAME_TYPE(decltype(make_optional(arr)), optional<int*>); + } + { + constexpr auto opt = make_optional(2); + ASSERT_SAME_TYPE(decltype(opt), const optional<int>); + static_assert(opt.value() == 2); + } + { + optional<int> opt = make_optional(2); + assert(*opt == 2); + } + { + std::string s("123"); + optional<std::string> opt = make_optional(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + optional<std::unique_ptr<int>> opt = make_optional(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp new file mode 100644 index 00000000000..bdfeefbcc1d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T, class... Args> +// constexpr optional<T> make_optional(Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +int main() +{ + using std::optional; + using std::make_optional; + + { + constexpr auto opt = make_optional<int>('a'); + static_assert(*opt == int('a'), ""); + } + { + std::string s("123"); + auto opt = make_optional<std::string>(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + auto opt = make_optional<std::unique_ptr<int>>(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } + { + auto opt = make_optional<std::string>(4, 'X'); + assert(*opt == "XXXX"); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp new file mode 100644 index 00000000000..f17f5820d20 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T, class U, class... Args> +// constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +struct TestT { + int x; + int size; + constexpr TestT(std::initializer_list<int> il) : x(*il.begin()), size(il.size()) {} + constexpr TestT(std::initializer_list<int> il, const int*) + : x(*il.begin()), size(il.size()) {} +}; + +int main() +{ + using std::make_optional; + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}); + ASSERT_SAME_TYPE(decltype(opt), const std::optional<TestT>); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}, nullptr); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + auto opt = make_optional<std::string>({'1', '2', '3'}); + assert(*opt == "123"); + } + { + auto opt = make_optional<std::string>({'a', 'b', 'c'}, std::allocator<char>{}); + assert(*opt == "abc"); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp new file mode 100644 index 00000000000..9f1d0305022 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp @@ -0,0 +1,352 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class T> void swap(optional<T>& x, optional<T>& y) +// noexcept(noexcept(x.swap(y))); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) { TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z& x, Z& y) { TEST_THROW(6);} +}; + + +struct NonSwappable { + NonSwappable(NonSwappable const&) = delete; +}; +void swap(NonSwappable&, NonSwappable&) = delete; + +void test_swap_sfinae() { + using std::optional; + { + using T = TestTypes::TestType; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::MoveOnly; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::Copyable; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::NoCtors; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + using T = NonSwappable; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + // Even thought CopyOnly has deleted move operations, those operations + // cause optional<CopyOnly> to have implicitly deleted move operations + // that decay into copies. + using T = TestTypes::CopyOnly; + using Opt = optional<T>; + T::reset(); + Opt L(101), R(42); + T::reset_constructors(); + std::swap(L, R); + assert(L->value == 42); + assert(R->value == 101); + assert(T::copy_constructed == 1); + assert(T::constructed == T::copy_constructed); + assert(T::assigned == 2); + assert(T::assigned == T::copy_assigned); + } +} + +int main() +{ + test_swap_sfinae(); + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif // TEST_HAS_NO_EXCEPTIONS +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp new file mode 100644 index 00000000000..20c90c7e34f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) in_place_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::in_place_t; + using std::in_place; + + optional<in_place_t> opt; // expected-note {{requested here}} + // expected-error@optional:* {{"instantiation of optional with in_place_t is ill-formed"}} +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp new file mode 100644 index 00000000000..687625e8b67 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 <initializer_list> + +#include <optional> + +int main() +{ + using std::optional; + + std::initializer_list<int> list; +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp new file mode 100644 index 00000000000..56a30ccb0db --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) nullopt_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + optional<nullopt_t> opt; // expected-note 1 {{requested here}} + optional<const nullopt_t> opt1; // expected-note 1 {{requested here}} + optional<nullopt_t &> opt2; // expected-note 1 {{requested here}} + optional<nullopt_t &&> opt3; // expected-note 1 {{requested here}} + // expected-error@optional:* 4 {{instantiation of optional with nullopt_t is ill-formed}} +} diff --git a/libcxx/test/support/archetypes.hpp b/libcxx/test/support/archetypes.hpp index 5b294049658..c09aa7085ff 100644 --- a/libcxx/test/support/archetypes.hpp +++ b/libcxx/test/support/archetypes.hpp @@ -1,10 +1,186 @@ #ifndef TEST_SUPPORT_ARCHETYPES_HPP #define TEST_SUPPORT_ARCHETYPES_HPP +#include <type_traits> +#include <cassert> + #include "test_macros.h" #if TEST_STD_VER >= 11 +namespace ArchetypeBases { + +template <bool, class T> +struct DepType : T {}; + +struct NullBase {}; + +template <class Derived, bool Explicit = false> +struct TestBase { + static int alive; + static int constructed; + static int value_constructed; + static int default_constructed; + static int copy_constructed; + static int move_constructed; + static int assigned; + static int value_assigned; + static int copy_assigned; + static int move_assigned; + static int destroyed; + + static void reset() { + assert(alive == 0); + alive = 0; + reset_constructors(); + } + + static void reset_constructors() { + constructed = value_constructed = default_constructed = + copy_constructed = move_constructed = 0; + assigned = value_assigned = copy_assigned = move_assigned = destroyed = 0; + } + + TestBase() noexcept : value(0) { + ++alive; ++constructed; ++default_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(int x) noexcept : value(x) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(int x) noexcept : value(x) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(int x, int y) noexcept : value(y) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(int x, int y) noexcept : value(y) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(std::initializer_list<int>& il, int y = 0) noexcept + : value(il.size()) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(std::initializer_list<int>& il, int y = 0) noexcept : value(il.size()) { + ++alive; ++constructed; ++value_constructed; + } + TestBase& operator=(int xvalue) noexcept { + value = xvalue; + ++assigned; ++value_assigned; + return *this; + } +protected: + ~TestBase() { + assert(value != -999); assert(alive > 0); + --alive; ++destroyed; value = -999; + } + TestBase(TestBase const& o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + ++alive; ++constructed; ++copy_constructed; + } + TestBase(TestBase && o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + ++alive; ++constructed; ++move_constructed; + o.value = -1; + } + TestBase& operator=(TestBase const& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + ++assigned; ++copy_assigned; + value = o.value; + return *this; + } + TestBase& operator=(TestBase&& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + ++assigned; ++move_assigned; + value = o.value; + o.value = -1; + return *this; + } +public: + int value; +}; + +template <class D, bool E> int TestBase<D, E>::alive = 0; +template <class D, bool E> int TestBase<D, E>::constructed = 0; +template <class D, bool E> int TestBase<D, E>::value_constructed = 0; +template <class D, bool E> int TestBase<D, E>::default_constructed = 0; +template <class D, bool E> int TestBase<D, E>::copy_constructed = 0; +template <class D, bool E> int TestBase<D, E>::move_constructed = 0; +template <class D, bool E> int TestBase<D, E>::assigned = 0; +template <class D, bool E> int TestBase<D, E>::value_assigned = 0; +template <class D, bool E> int TestBase<D, E>::copy_assigned = 0; +template <class D, bool E> int TestBase<D, E>::move_assigned = 0; +template <class D, bool E> int TestBase<D, E>::destroyed = 0; + +template <bool Explicit = false> +struct ValueBase { + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + constexpr ValueBase& operator=(int xvalue) noexcept { + value = xvalue; + return *this; + } + //~ValueBase() { assert(value != -999); value = -999; } + int value; +protected: + constexpr ValueBase() noexcept : value(0) {} + constexpr ValueBase(ValueBase const& o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + } + constexpr ValueBase(ValueBase && o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + o.value = -1; + } + constexpr ValueBase& operator=(ValueBase const& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + value = o.value; + return *this; + } + constexpr ValueBase& operator=(ValueBase&& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + value = o.value; + o.value = -1; + return *this; + } +}; + + +template <bool Explicit = false> +struct TrivialValueBase { + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {}; + int value; +protected: + constexpr TrivialValueBase() noexcept : value(0) {} +}; + +} + //============================================================================// // Trivial Implicit Test Types namespace ImplicitTypes { @@ -18,9 +194,18 @@ namespace ExplicitTypes { #include "archetypes.ipp" } + +//============================================================================// +// +namespace NonConstexprTypes { +#define DEFINE_CONSTEXPR +#include "archetypes.ipp" +} + //============================================================================// -// Non-Trivial Implicit Test Types +// Non-literal implicit test types namespace NonLiteralTypes { +#define DEFINE_ASSIGN_CONSTEXPR #define DEFINE_DTOR(Name) ~Name() {} #include "archetypes.ipp" } @@ -29,9 +214,144 @@ namespace NonLiteralTypes { // Non-Trivially Copyable Implicit Test Types namespace NonTrivialTypes { #define DEFINE_CTOR {} +#define DEFINE_ASSIGN { return *this; } +#define DEFINE_DEFAULT_CTOR = default +#include "archetypes.ipp" +} + +//============================================================================// +// Implicit counting types +namespace TestTypes { +#define DEFINE_CONSTEXPR +#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} + +//============================================================================// +// Implicit counting types +namespace ExplicitTestTypes { +#define DEFINE_CONSTEXPR +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name, true> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} + +//============================================================================// +// Implicit value types +namespace ConstexprTestTypes { +#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ValueTypes + + +//============================================================================// +// +namespace ExplicitConstexprTestTypes { +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<true> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ValueTypes + + +//============================================================================// +// +namespace TrivialTestTypes { +#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<false> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace TrivialValueTypes + +//============================================================================// +// +namespace ExplicitTrivialTestTypes { +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<true> #include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; } +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ExplicitTrivialTestTypes + #endif // TEST_STD_VER >= 11 #endif // TEST_SUPPORT_ARCHETYPES_HPP diff --git a/libcxx/test/support/archetypes.ipp b/libcxx/test/support/archetypes.ipp index 094440a9783..1f94ddcf0c8 100644 --- a/libcxx/test/support/archetypes.ipp +++ b/libcxx/test/support/archetypes.ipp @@ -1,10 +1,22 @@ +#ifndef DEFINE_BASE +#define DEFINE_BASE(Name) ::ArchetypeBases::NullBase +#endif #ifndef DEFINE_EXPLICIT #define DEFINE_EXPLICIT #endif +#ifndef DEFINE_CONSTEXPR +#define DEFINE_CONSTEXPR constexpr +#endif +#ifndef DEFINE_ASSIGN_CONSTEXPR +#define DEFINE_ASSIGN_CONSTEXPR DEFINE_CONSTEXPR +#endif #ifndef DEFINE_CTOR #define DEFINE_CTOR = default #endif +#ifndef DEFINE_DEFAULT_CTOR +#define DEFINE_DEFAULT_CTOR DEFINE_CTOR +#endif #ifndef DEFINE_ASSIGN #define DEFINE_ASSIGN = default #endif @@ -12,78 +24,117 @@ #define DEFINE_DTOR(Name) #endif -struct NoDefault { - DEFINE_EXPLICIT NoDefault() = delete; +struct AllCtors : DEFINE_BASE(AllCtors) { + using Base = DEFINE_BASE(AllCtors); + using Base::Base; + using Base::operator=; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors const&) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors &&) DEFINE_CTOR; + DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN; + DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN; + DEFINE_DTOR(AllCtors) +}; + +struct NoCtors : DEFINE_BASE(NoCtors) { + using Base = DEFINE_BASE(NoCtors); + using Base::Base; + DEFINE_EXPLICIT NoCtors() = delete; + DEFINE_EXPLICIT NoCtors(NoCtors const&) = delete; + NoCtors& operator=(NoCtors const&) = delete; + DEFINE_DTOR(NoCtors) +}; + +struct NoDefault : DEFINE_BASE(NoDefault) { + using Base = DEFINE_BASE(NoDefault); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NoDefault() = delete; DEFINE_DTOR(NoDefault) }; -struct AllCtors { - DEFINE_EXPLICIT AllCtors() DEFINE_CTOR; - DEFINE_EXPLICIT AllCtors(AllCtors const&) DEFINE_CTOR; - DEFINE_EXPLICIT AllCtors(AllCtors &&) DEFINE_CTOR; - AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN; - AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN; - DEFINE_DTOR(AllCtors) +struct DefaultOnly : DEFINE_BASE(DefaultOnly) { + using Base = DEFINE_BASE(DefaultOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR DefaultOnly() DEFINE_DEFAULT_CTOR; + DefaultOnly(DefaultOnly const&) = delete; + DefaultOnly& operator=(DefaultOnly const&) = delete; + DEFINE_DTOR(DefaultOnly) }; -struct Copyable { - DEFINE_EXPLICIT Copyable() DEFINE_CTOR; - DEFINE_EXPLICIT Copyable(Copyable const &) DEFINE_CTOR; +struct Copyable : DEFINE_BASE(Copyable) { + using Base = DEFINE_BASE(Copyable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable(Copyable const &) DEFINE_CTOR; Copyable &operator=(Copyable const &) DEFINE_ASSIGN; DEFINE_DTOR(Copyable) }; -struct CopyOnly { - DEFINE_EXPLICIT CopyOnly() DEFINE_CTOR; - DEFINE_EXPLICIT CopyOnly(CopyOnly const &) DEFINE_CTOR; - DEFINE_EXPLICIT CopyOnly(CopyOnly &&) = delete; +struct CopyOnly : DEFINE_BASE(CopyOnly) { + using Base = DEFINE_BASE(CopyOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly const &) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly &&) = delete; CopyOnly &operator=(CopyOnly const &) DEFINE_ASSIGN; CopyOnly &operator=(CopyOnly &&) = delete; DEFINE_DTOR(CopyOnly) }; -struct NonCopyable { - DEFINE_EXPLICIT NonCopyable() DEFINE_CTOR; - DEFINE_EXPLICIT NonCopyable(NonCopyable const &) = delete; +struct NonCopyable : DEFINE_BASE(NonCopyable) { + using Base = DEFINE_BASE(NonCopyable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable(NonCopyable const &) = delete; NonCopyable &operator=(NonCopyable const &) = delete; DEFINE_DTOR(NonCopyable) }; -struct MoveOnly { - DEFINE_EXPLICIT MoveOnly() DEFINE_CTOR; - DEFINE_EXPLICIT MoveOnly(MoveOnly &&) DEFINE_CTOR; +struct MoveOnly : DEFINE_BASE(MoveOnly) { + using Base = DEFINE_BASE(MoveOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly(MoveOnly &&) DEFINE_CTOR; MoveOnly &operator=(MoveOnly &&) DEFINE_ASSIGN; DEFINE_DTOR(MoveOnly) }; -struct CopyAssignable { - DEFINE_EXPLICIT CopyAssignable() = delete; - CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN; - DEFINE_DTOR(CopyAssignable) +struct CopyAssignable : DEFINE_BASE(CopyAssignable) { + using Base = DEFINE_BASE(CopyAssignable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignable() = delete; + CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN; + DEFINE_DTOR(CopyAssignable) }; -struct CopyAssignOnly { - DEFINE_EXPLICIT CopyAssignOnly() = delete; - CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN; - CopyAssignOnly& operator=(CopyAssignOnly &&) = delete; - DEFINE_DTOR(CopyAssignOnly) +struct CopyAssignOnly : DEFINE_BASE(CopyAssignOnly) { + using Base = DEFINE_BASE(CopyAssignOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignOnly() = delete; + CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN; + CopyAssignOnly& operator=(CopyAssignOnly &&) = delete; + DEFINE_DTOR(CopyAssignOnly) }; -struct MoveAssignOnly { - DEFINE_EXPLICIT MoveAssignOnly() = delete; - MoveAssignOnly& operator=(MoveAssignOnly const&) = delete; - MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN; - DEFINE_DTOR(MoveAssignOnly) +struct MoveAssignOnly : DEFINE_BASE(MoveAssignOnly) { + using Base = DEFINE_BASE(MoveAssignOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveAssignOnly() = delete; + MoveAssignOnly& operator=(MoveAssignOnly const&) = delete; + MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN; + DEFINE_DTOR(MoveAssignOnly) }; -struct ConvertingType { - DEFINE_EXPLICIT ConvertingType() DEFINE_CTOR; - DEFINE_EXPLICIT ConvertingType(ConvertingType const&) DEFINE_CTOR; - DEFINE_EXPLICIT ConvertingType(ConvertingType &&) DEFINE_CTOR; +struct ConvertingType : DEFINE_BASE(ConvertingType) { + using Base = DEFINE_BASE(ConvertingType); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType const&) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType &&) DEFINE_CTOR; ConvertingType& operator=(ConvertingType const&) DEFINE_ASSIGN; ConvertingType& operator=(ConvertingType &&) DEFINE_ASSIGN; template <class ...Args> - DEFINE_EXPLICIT ConvertingType(Args&&...) {} + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(Args&&...) {} template <class Arg> ConvertingType& operator=(Arg&&) { return *this; } DEFINE_DTOR(ConvertingType) @@ -91,8 +142,10 @@ struct ConvertingType { template <template <class...> class List> using ApplyTypes = List< - NoDefault, AllCtors, + NoCtors, + NoDefault, + DefaultOnly, Copyable, CopyOnly, NonCopyable, @@ -103,7 +156,11 @@ using ApplyTypes = List< ConvertingType >; +#undef DEFINE_BASE #undef DEFINE_EXPLICIT +#undef DEFINE_CONSTEXPR +#undef DEFINE_ASSIGN_CONSTEXPR #undef DEFINE_CTOR +#undef DEFINE_DEFAULT_CTOR #undef DEFINE_ASSIGN #undef DEFINE_DTOR |