From a9e659619f592c49b352af16253ec0b79c207956 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 12 Oct 2016 07:46:20 +0000 Subject: 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` when `T` is trivially copyable. Audit P/Rs for optional LWG issues: - 2756 "C++ WP optional 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::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 --- .../optional.object.assign/copy.pass.cpp | 81 +++++ .../optional.object.assign/move.pass.cpp | 78 +++++ .../optional.object.ctor/copy.pass.cpp | 59 ++++ .../optional.object.ctor/move.pass.cpp | 60 ++++ .../optional.object/special_member_gen.pass.cpp | 66 ++++ .../libcxx/utilities/optional/version.pass.cpp | 20 ++ .../is_nothrow_swappable_with.pass.cpp | 2 +- .../optional.bad_optional_access/default.pass.cpp | 23 ++ .../optional.bad_optional_access/derive.pass.cpp | 25 ++ .../optional/optional.comp_with_t/equal.pass.cpp | 53 ++++ .../optional/optional.comp_with_t/greater.pass.cpp | 55 ++++ .../optional.comp_with_t/greater_equal.pass.cpp | 55 ++++ .../optional.comp_with_t/less_equal.pass.cpp | 55 ++++ .../optional.comp_with_t/less_than.pass.cpp | 55 ++++ .../optional.comp_with_t/not_equal.pass.cpp | 53 ++++ .../utilities/optional/optional.hash/hash.pass.cpp | 48 +++ .../optional/optional.nullops/equal.pass.cpp | 39 +++ .../optional/optional.nullops/greater.pass.cpp | 39 +++ .../optional.nullops/greater_equal.pass.cpp | 39 +++ .../optional/optional.nullops/less_equal.pass.cpp | 40 +++ .../optional/optional.nullops/less_than.pass.cpp | 39 +++ .../optional/optional.nullops/not_equal.pass.cpp | 39 +++ .../not_brace_initializable.fail.cpp | 25 ++ .../optional/optional.nullopt/nullopt_t.pass.cpp | 38 +++ .../optional.object.assign/assign_value.pass.cpp | 261 +++++++++++++++ .../const_optional_U.pass.cpp | 254 +++++++++++++++ .../optional.object.assign/copy.pass.cpp | 102 ++++++ .../optional.object.assign/emplace.pass.cpp | 237 ++++++++++++++ .../emplace_initializer_list.pass.cpp | 113 +++++++ .../optional.object.assign/move.pass.cpp | 174 ++++++++++ .../optional.object.assign/nullopt_t.pass.cpp | 67 ++++ .../optional.object.assign/optional_U.pass.cpp | 268 ++++++++++++++++ .../optional.object.ctor/U.pass.cpp | 137 ++++++++ .../optional.object.ctor/const_T.pass.cpp | 123 +++++++ .../optional.object.ctor/const_optional_U.pass.cpp | 134 ++++++++ .../optional.object.ctor/copy.pass.cpp | 150 +++++++++ .../optional.object.ctor/default.pass.cpp | 81 +++++ .../explicit_const_optional_U.pass.cpp | 121 +++++++ .../explicit_optional_U.pass.cpp | 84 +++++ .../optional.object.ctor/in_place_t.pass.cpp | 144 +++++++++ .../optional.object.ctor/initializer_list.pass.cpp | 116 +++++++ .../optional.object.ctor/move.pass.cpp | 196 ++++++++++++ .../optional.object.ctor/nullopt_t.pass.cpp | 73 +++++ .../optional.object.ctor/optional_U.pass.cpp | 93 ++++++ .../optional.object.ctor/rvalue_T.pass.cpp | 148 +++++++++ .../optional.object.dtor/dtor.pass.cpp | 68 ++++ .../optional.object.mod/reset.pass.cpp | 61 ++++ .../optional.object.observe/bool.pass.cpp | 37 +++ .../optional.object.observe/dereference.pass.cpp | 73 +++++ .../dereference_const.pass.cpp | 69 ++++ .../dereference_const_rvalue.pass.cpp | 69 ++++ .../dereference_rvalue.pass.cpp | 73 +++++ .../optional.object.observe/has_value.pass.cpp | 37 +++ .../optional.object.observe/op_arrow.pass.cpp | 72 +++++ .../op_arrow_const.pass.cpp | 76 +++++ .../optional.object.observe/value.pass.cpp | 73 +++++ .../optional.object.observe/value_const.fail.cpp | 33 ++ .../optional.object.observe/value_const.pass.cpp | 64 ++++ .../value_const_rvalue.pass.cpp | 64 ++++ .../optional.object.observe/value_or.pass.cpp | 68 ++++ .../value_or_const.pass.cpp | 77 +++++ .../optional.object.observe/value_rvalue.pass.cpp | 72 +++++ .../optional.object.swap/swap.pass.cpp | 306 ++++++++++++++++++ .../optional_requires_destructible_object.fail.cpp | 50 +++ .../optional.object/special_member_gen.pass.cpp | 74 +++++ .../optional/optional.object/types.pass.cpp | 38 +++ .../optional/optional.relops/equal.pass.cpp | 74 +++++ .../optional.relops/greater_equal.pass.cpp | 70 ++++ .../optional/optional.relops/greater_than.pass.cpp | 70 ++++ .../optional/optional.relops/less_equal.pass.cpp | 70 ++++ .../optional/optional.relops/less_than.pass.cpp | 70 ++++ .../optional/optional.relops/not_equal.pass.cpp | 74 +++++ .../optional.specalg/make_optional.pass.cpp | 51 +++ .../make_optional_explicit.pass.cpp | 45 +++ ...ake_optional_explicit_initializer_list.pass.cpp | 53 ++++ .../optional/optional.specalg/swap.pass.cpp | 352 +++++++++++++++++++++ .../optional.syn/optional_in_place_t.fail.cpp | 26 ++ .../optional_includes_initializer_list.pass.cpp | 22 ++ .../optional.syn/optional_nullopt_t.fail.cpp | 29 ++ libcxx/test/support/archetypes.hpp | 322 ++++++++++++++++++- libcxx/test/support/archetypes.ipp | 141 ++++++--- 81 files changed, 7141 insertions(+), 44 deletions(-) create mode 100644 libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp create mode 100644 libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp create mode 100644 libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp create mode 100644 libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp create mode 100644 libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp create mode 100644 libcxx/test/libcxx/utilities/optional/version.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.object/types.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp create mode 100644 libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp (limited to 'libcxx/test') 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& operator=(const optional& rhs); + +#include +#include +#include + +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 +constexpr bool +test() +{ + optional opt; + optional opt2; + opt = opt2; + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_assignable>::value), ""); +#if __cplusplus >= 201402 + static_assert(test(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_assignable>::value), ""); +#if __cplusplus >= 201402 + static_assert(test(), ""); +#endif + } + static_assert(!(std::is_trivially_copy_assignable>::value), ""); + static_assert(!(std::is_trivially_copy_assignable>::value), ""); + + static_assert(!(std::is_copy_assignable>::value), ""); + static_assert(!(std::is_copy_assignable>::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& operator=(optional&& rhs); + +#include +#include +#include +#include + +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 +constexpr bool +test() +{ + optional opt; + optional opt2; + opt = std::move(opt2); + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible>::value), ""); +#if __cplusplus >= 201402 + static_assert(test(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible>::value), ""); +#if __cplusplus >= 201402 + static_assert(test(), ""); +#endif + } + static_assert(!(std::is_trivially_move_assignable>::value), ""); + static_assert(!(std::is_trivially_move_assignable>::value), ""); + + static_assert(!(std::is_move_assignable>::value), ""); + static_assert(!(std::is_move_assignable>::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(const optional& rhs); + +#include +#include +#include + +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>::value), ""); + constexpr optional opt; + constexpr optional opt2 = opt; + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible>::value), ""); + constexpr optional opt; + constexpr optional opt2 = opt; + (void)opt2; + } + static_assert(!(std::is_trivially_copy_constructible>::value), ""); + static_assert(!(std::is_trivially_copy_constructible>::value), ""); + + static_assert(!(std::is_copy_constructible>::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&& rhs); + +#include +#include +#include +#include + +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>::value), ""); + constexpr optional opt; + constexpr optional opt2 = std::move(opt); + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible>::value), ""); + constexpr optional opt; + constexpr optional opt2 = std::move(opt); + (void)opt2; + } + static_assert(!(std::is_trivially_move_constructible>::value), ""); + static_assert(!(std::is_trivially_move_constructible>::value), ""); + + static_assert(!(std::is_move_constructible>::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 +// + + +#include +#include +#include + +#include "archetypes.hpp" + +template +struct SpecialMemberTest { + using O = std::optional; + + template