diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -316,6 +316,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_typeinfo`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_expected`` ``202202L`` + ------------------------------------------------- ----------------- ``__cpp_lib_forward_like`` ``202207L`` ------------------------------------------------- ----------------- ``__cpp_lib_invoke_r`` *unimplemented* diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -167,11 +167,11 @@ "`3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","","" "`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|" "`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" -"`3687 `__","``expected`` move constructor should move","July 2022","","" +"`3687 `__","``expected`` move constructor should move","July 2022","Complete","16.0" "`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|spaceship|" "`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","","","|format|" "`3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","" -"`3703 `__","Missing requirements for ``expected`` requires ``is_void``","July 2022","","" +"`3703 `__","Missing requirements for ``expected`` requires ``is_void``","July 2022","Complete","16.0" "`3704 `__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","","" "`3705 `__","Hashability shouldn't depend on basic_string's allocator","July 2022","|Complete|","16.0" "`3707 `__","chunk_view::outer-iterator::value_type::size should return unsigned type","July 2022","","","|ranges|" diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -38,7 +38,7 @@ "`P2393R1 `__","LWG","Cleaning up ``integer``-class types","October 2021","","" "`P2401R0 `__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0" "","","","","","" -"`P0323R12 `__","LWG","``std::expected``","February 2022","","" +"`P0323R12 `__","LWG","``std::expected``","February 2022","|Complete|","16.0" "`P0533R9 `__","LWG","``constexpr`` for ```` and ````","February 2022","","" "`P0627R6 `__","LWG","Function to mark unreachable code","February 2022","|Complete|","15.0" "`P1206R7 `__","LWG","``ranges::to``: A function to convert any range to a container","February 2022","","" @@ -86,7 +86,7 @@ "`P2517R1 `__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","","" "`P2520R0 `__","LWG","``move_iterator`` should be a random access iterator","July 2022","","" "`P2540R1 `__","LWG","Empty Product for certain Views","July 2022","","" -"`P2549R1 `__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","","" +"`P2549R1 `__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","|Complete|","16.0" "`P2553R1 `__","LWG","Make ``mdspan`` ``size_type`` controllable","July 2022","","" "`P2554R0 `__","LWG","C-Array Interoperability of MDSpan","July 2022","","" "`P2585R0 `__","LWG","Improving default container formatting","July 2022","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -269,6 +269,10 @@ __debug __debug_utils/randomize_range.h __errc + __expected/bad_expected_access.h + __expected/expected.h + __expected/unexpect.h + __expected/unexpected.h __filesystem/copy_options.h __filesystem/directory_entry.h __filesystem/directory_iterator.h @@ -724,6 +728,7 @@ errno.h exception execution + expected experimental/__config experimental/__memory experimental/algorithm diff --git a/libcxx/include/__expected/bad_expected_access.h b/libcxx/include/__expected/bad_expected_access.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__expected/bad_expected_access.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H +#define _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H + +#include <__config> +#include <__utility/move.h> + +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class bad_expected_access; + +template <> +class bad_expected_access : public exception { +protected: + _LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default; + _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default; + _LIBCPP_HIDE_FROM_ABI ~bad_expected_access() override = default; + +public: + _LIBCPP_HIDE_FROM_ABI const char* what() const noexcept override { return "bad access to std::expected"; } +}; + +template +class bad_expected_access : public bad_expected_access { +public: + _LIBCPP_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(std::move(__e)) {} + + _LIBCPP_HIDE_FROM_ABI const char* what() const noexcept override { + return static_cast const&>(*this).what(); + } + + _LIBCPP_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI const _Err& error() const& noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI _Err&& error() && noexcept { return std::move(__unex_); } + _LIBCPP_HIDE_FROM_ABI const _Err&& error() const&& noexcept { return std::move(__unex_); } + +private: + _Err __unex_; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__expected/expected.h @@ -0,0 +1,875 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_EXPECTED_H +#define _LIBCPP___EXPECTED_EXPECTED_H + +#include <__assert> +#include <__config> +#include <__expected/bad_expected_access.h> +#include <__expected/unexpect.h> +#include <__expected/unexpected.h> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_assignable.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/is_void.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include <__utility/transaction.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class expected { + static_assert(!is_reference_v<_Tp>); + static_assert(!is_function_v<_Tp>); + static_assert(!is_same_v, in_place_t>); + static_assert(!is_same_v, unexpect_t>); + static_assert(!__unexpected::__is_unexpected>); + static_assert(__unexpected::__valid_unexpected_error<_Err>); + + template + friend class expected; + + template + static constexpr bool __can_convert = + is_constructible_v<_Tp, _Uf> && // + is_constructible_v<_Err, _Gf> && // + !is_constructible_v<_Tp, expected<_Up, _Gp>&> && // + !is_constructible_v<_Tp, expected<_Up, _Gp>> && // + !is_constructible_v<_Tp, const expected<_Up, _Gp>&> && // + !is_constructible_v<_Tp, const expected<_Up, _Gp>> && // + !is_convertible_v&, _Tp> && // + !is_convertible_v&&, _Tp> && // + !is_convertible_v&, _Tp> && // + !is_convertible_v&&, _Tp> && // + !is_constructible_v, expected<_Up, _Gp>&> && // + !is_constructible_v, expected<_Up, _Gp>> && // + !is_constructible_v, const expected<_Up, _Gp>&> && // + !is_constructible_v, const expected<_Up, _Gp>>; + + template + static constexpr bool __can_assign_from_unexpected = // + is_constructible_v<_Err, _Gf> && // + is_assignable_v<_Err&, _Gf> && // + (is_nothrow_constructible_v<_Err, _Gf> || // + is_nothrow_move_constructible_v<_Tp> || // + is_nothrow_move_constructible_v<_Err>); + + template + _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) { + if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { + std::destroy_at(std::addressof(__oldval)); + std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); + } else if constexpr (is_nothrow_move_constructible_v<_T1>) { + _T1 __tmp(std::forward<_Args>(__args)...); + std::destroy_at(std::addressof(__oldval)); + std::construct_at(std::addressof(__newval), std::move(__tmp)); + } else { + _T2 __tmp(std::move(__oldval)); + std::destroy_at(std::addressof(__oldval)); + __transaction __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); + std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); + __trans.__complete(); + } + } + + _LIBCPP_HIDE_FROM_ABI static constexpr void __swap_val_unex_impl(expected& __with_val, expected& __with_err) // + noexcept(is_nothrow_move_constructible_v<_Tp>&& is_nothrow_move_constructible_v<_Err>) { + if constexpr (is_nothrow_move_constructible_v<_Err>) { + _Err __tmp(std::move(__with_err.__unex_)); + std::destroy_at(std::addressof(__with_err.__unex_)); + __transaction __trans([&] { std::construct_at(std::addressof(__with_err.__unex_), std::move(__tmp)); }); + std::construct_at(std::addressof(__with_err.__val_), std::move(__with_val.__val_)); + std::destroy_at(std::addressof(__with_val.__val_)); + std::construct_at(std::addressof(__with_val.__unex_), std::move(__tmp)); + __trans.__complete(); + } else { + _Tp __tmp(std::move(__with_val.__val_)); + std::destroy_at(std::addressof(__with_val.__val_)); + __transaction __trans([&] { std::construct_at(std::addressof(__with_val.__val_), std::move(__tmp)); }); + std::construct_at(std::addressof(__with_val.__unex_), std::move(__with_err.__unex_)); + std::destroy_at(std::addressof(__with_err.__unex_)); + std::construct_at(std::addressof(__with_err.__val_), std::move(__tmp)); + __trans.__complete(); + } + __with_val.__has_val_ = false; + __with_err.__has_val_ = true; + } + +public: + using value_type = _Tp; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + template + using rebind = expected<_Up, error_type>; + + // [expected.object.ctor], constructors + _LIBCPP_HIDE_FROM_ABI constexpr expected() // + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires is_default_constructible_v<_Tp> + : __has_val_(true), __val_() {} + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) + requires(is_copy_constructible_v<_Tp> && // + is_copy_constructible_v<_Err> && // + is_trivially_copy_constructible_v<_Tp> && // + is_trivially_copy_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) // + noexcept(is_nothrow_copy_constructible_v<_Tp>&& // + is_nothrow_copy_constructible_v<_Err>) + requires(is_copy_constructible_v<_Tp> && // + is_copy_constructible_v<_Err> && // + !(is_trivially_copy_constructible_v<_Tp> && // + is_trivially_copy_constructible_v<_Err>)) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__val_), __other.__val_); + } else { + std::construct_at(std::addressof(__unex_), __other.__unex_); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) + requires(is_move_constructible_v<_Tp> && // + is_move_constructible_v<_Err> && // + is_trivially_move_constructible_v<_Tp> && // + is_trivially_move_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) // + noexcept(is_nothrow_move_constructible_v<_Tp>&& // + is_nothrow_move_constructible_v<_Err>) + requires(is_move_constructible_v<_Tp> && // + is_move_constructible_v<_Err> && // + !(is_trivially_move_constructible_v<_Tp> && // + is_trivially_move_constructible_v<_Err>)) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__val_), std::move(__other.__val_)); + } else { + std::construct_at(std::addressof(__unex_), std::move(__other.__unex_)); + } + } + + template + requires __can_convert<_Up, _Gp, const _Up&, const _Gp&> + _LIBCPP_HIDE_FROM_ABI constexpr // + explicit(!is_convertible_v || // + !is_convertible_v) // + expected(const expected<_Up, _Gp>& __other) // + noexcept(is_nothrow_constructible_v<_Tp, const _Up&>&& // + is_nothrow_constructible_v<_Err, const _Gp&>) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__val_), __other.__val_); + } else { + std::construct_at(std::addressof(__unex_), __other.__unex_); + } + } + + template + requires __can_convert<_Up, _Gp, _Up, _Gp> + _LIBCPP_HIDE_FROM_ABI constexpr // + explicit(!is_convertible_v<_Up, _Tp> || // + !is_convertible_v<_Gp, _Err>) // + expected(expected<_Up, _Gp>&& __other) // + noexcept(is_nothrow_constructible_v<_Tp, _Up>&& // + is_nothrow_constructible_v<_Err, _Gp>) + : __has_val_(__other.__has_val_) { + if (__has_val_) { + std::construct_at(std::addressof(__val_), std::move(__other.__val_)); + } else { + std::construct_at(std::addressof(__unex_), std::move(__other.__unex_)); + } + } + + template + requires(!is_same_v, in_place_t> && // + !is_same_v> && // + !__unexpected::__is_unexpected> && // + is_constructible_v<_Tp, _Up>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) expected(_Up&& __u) // + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : __has_val_(true), __val_(std::forward<_Up>(__u)) {} + + template + requires is_constructible_v<_Err, const _Gp&> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) + expected(const unexpected<_Gp>& __unex) // + noexcept(is_nothrow_constructible_v<_Err, const _Gp&>) + : __has_val_(false), __unex_(__unex.error()) {} + + template + requires is_constructible_v<_Err, _Gp> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Gp, _Err>) // + expected(unexpected<_Gp>&& __unex) // + noexcept(is_nothrow_constructible_v<_Err, _Gp>) + : __has_val_(false), __unex_(std::move(__unex).error()) {} + + template + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + : __has_val_(true), __val_(std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) + : __has_val_(true), __val_(__il, std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, _Args...>) + : __has_val_(false), __unex_(std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) + : __has_val_(false), __unex_(__il, std::forward<_Args>(__args)...) {} + + // [expected.object.dtor], destructor + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) + { + if (__has_val_) { + std::destroy_at(std::addressof(__val_)); + } else { + std::destroy_at(std::addressof(__unex_)); + } + } + + // [expected.object.assign], assignment + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) // + noexcept((is_nothrow_copy_assignable_v<_Tp> && // + is_nothrow_copy_constructible_v<_Tp> && // + is_nothrow_copy_assignable_v<_Err> && // + is_nothrow_copy_constructible_v<_Err>)) + requires(is_copy_assignable_v<_Tp> && // + is_copy_constructible_v<_Tp> && // + is_copy_assignable_v<_Err> && // + is_copy_constructible_v<_Err> && // + (is_nothrow_move_constructible_v<_Tp> || // + is_nothrow_move_constructible_v<_Err>)) + { + if (__has_val_ && __rhs.__has_val_) { + __val_ = *__rhs; + } else if (__has_val_) { + __reinit_expected(__unex_, __val_, __rhs.__unex_); + } else if (__rhs.__has_val_) { + __reinit_expected(__val_, __unex_, *__rhs); + } else { + __unex_ = __rhs.__unex_; + } + __has_val_ = __rhs.__has_val_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) // + noexcept((is_nothrow_move_assignable_v<_Tp> && // + is_nothrow_move_constructible_v<_Tp> && // + is_nothrow_move_assignable_v<_Err> && // + is_nothrow_move_constructible_v<_Err>)) + requires(is_move_constructible_v<_Tp> && // + is_move_assignable_v<_Tp> && // + is_move_constructible_v<_Err> && // + is_move_assignable_v<_Err> && // + (is_nothrow_move_constructible_v<_Tp> || // + is_nothrow_move_constructible_v<_Err>)) + { + if (__has_val_ && __rhs.__has_val_) { + __val_ = std::move(*__rhs); + } else if (__has_val_) { + __reinit_expected(__unex_, __val_, std::move(__rhs.__unex_)); + } else if (__rhs.__has_val_) { + __reinit_expected(__val_, __unex_, std::move(*__rhs)); + } else { + __unex_ = std::move(__rhs.__unex_); + } + __has_val_ = __rhs.__has_val_; + return *this; + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) + requires(!is_same_v> && // + !__unexpected::__is_unexpected> && // + is_constructible_v<_Tp, _Up> && // + is_assignable_v<_Tp&, _Up> && // + (is_nothrow_constructible_v<_Tp, _Up> || // + is_nothrow_move_constructible_v<_Tp> || // + is_nothrow_move_constructible_v<_Err>)) + { + if (has_value()) { + __val_ = std::forward<_Up>(__v); + } else { + __reinit_expected(__val_, __unex_, std::forward<_Up>(__v)); + __has_val_ = true; + } + return *this; + } + + template + requires(__can_assign_from_unexpected) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_Gp>& __un) { + if (has_value()) { + __reinit_expected(__unex_, __val_, __un.error()); + __has_val_ = false; + } else { + __unex_ = __un.error(); + } + return *this; + } + + template + requires(__can_assign_from_unexpected<_Gp>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_Gp>&& __un) { + if (has_value()) { + __reinit_expected(__unex_, __val_, std::move(__un.error())); + __has_val_ = false; + } else { + __unex_ = std::move(__un.error()); + } + return *this; + } + + template + requires is_nothrow_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { + if (__has_val_) { + std::destroy_at(std::addressof(__val_)); + } else { + std::destroy_at(std::addressof(__unex_)); + __has_val_ = true; + } + return *std::construct_at(std::addressof(__val_), std::forward<_Args>(__args)...); + } + + template + requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { + if (__has_val_) { + std::destroy_at(std::addressof(__val_)); + } else { + std::destroy_at(std::addressof(__unex_)); + __has_val_ = true; + } + return *std::construct_at(std::addressof(__val_), __il, std::forward<_Args>(__args)...); + } + + // [expected.object.swap], swap + _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) // + noexcept((is_nothrow_move_constructible_v<_Tp> && // + is_nothrow_swappable_v<_Tp> && // + is_nothrow_move_constructible_v<_Err> && // + is_nothrow_swappable_v<_Err>)) + requires(is_swappable_v<_Tp> && // + is_swappable_v<_Err> && // + is_move_constructible_v<_Tp> && // + is_move_constructible_v<_Err> && // + (is_nothrow_move_constructible_v<_Tp> || // + is_nothrow_move_constructible_v<_Err>)) + { + if (has_value()) { + if (__rhs.has_value()) { + using std::swap; + swap(__val_, __rhs.__val_); + } else { + __swap_val_unex_impl(*this, __rhs); + } + } else { + if (__rhs.has_value()) { + __swap_val_unex_impl(__rhs, *this); + } else { + using std::swap; + swap(__unex_, __rhs.__unex_); + } + } + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) // + noexcept(noexcept(__x.swap(__y))) { + __x.swap(__y); + } + + // [expected.object.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return std::addressof(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return std::addressof(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return __val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return __val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return std::move(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { + _LIBCPP_ASSERT(__has_val_, "expected must contain a value"); + return std::move(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { + if (!__has_val_) { + throw bad_expected_access<_Err>(__unex_); + } + return __val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { + if (!__has_val_) { + throw bad_expected_access<_Err>(__unex_); + } + return __val_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { + if (!__has_val_) { + throw bad_expected_access<_Err>(std::move(__unex_)); + } + return std::move(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { + if (!__has_val_) { + throw bad_expected_access<_Err>(std::move(__unex_)); + } + return std::move(__val_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return __unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return __unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return std::move(__unex_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return std::move(__unex_); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { + static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); + return has_value() ? **this : static_cast<_Tp>(std::forward<_Up>(__v)); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { + static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); + return has_value() ? std::move(**this) : static_cast<_Tp>(std::forward<_Up>(__v)); + } + + // [expected.object.eq], equality operators + template + requires(!is_void_v<_T2>) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { + if (__x.has_value() != __y.has_value()) { + return false; + } else { + if (__x.has_value()) { + return *__x == *__y; + } else { + return __x.error() == __y.error(); + } + } + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { + return __x.has_value() && static_cast(*__x == __v); + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { + return !__x.has_value() && static_cast(__x.error() == __e.error()); + } + +private: + bool __has_val_; + union { + _Tp __val_; + _Err __unex_; + }; +}; + +template + requires is_void_v<_Tp> +class expected<_Tp, _Err> { + static_assert(__unexpected::__valid_unexpected_error<_Err>); + + template + friend class expected; + + template + static constexpr bool __can_convert = + is_void_v<_Up> && // + is_constructible_v<_Err, _Gf> && // + !is_constructible_v, expected<_Up, _Gp>&> && // + !is_constructible_v, expected<_Up, _Gp>> && // + !is_constructible_v, const expected<_Up, _Gp>&> && // + !is_constructible_v, const expected<_Up, _Gp>>; + + _LIBCPP_HIDE_FROM_ABI static constexpr void __swap_val_unex_impl(expected& __with_val, expected& __with_err) // + noexcept(is_nothrow_move_constructible_v<_Err>) { + std::construct_at(std::addressof(__with_val.__unex_), std::move(__with_err.__unex_)); + std::destroy_at(std::addressof(__with_err.__unex_)); + __with_val.__has_val_ = false; + __with_err.__has_val_ = true; + } + +public: + using value_type = _Tp; + using error_type = _Err; + using unexpected_type = unexpected<_Err>; + + template + using rebind = expected<_Up, error_type>; + + // [expected.void.ctor], constructors + _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {} + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) + requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) // + noexcept(is_nothrow_copy_constructible_v<_Err>) + requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__unex_), __rhs.error()); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) + requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) // + noexcept(is_nothrow_move_constructible_v<_Err>) + requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__unex_), std::move(__rhs.error())); + } + } + + template + requires __can_convert<_Up, _Gp, const _Gp&> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) // + expected(const expected<_Up, _Gp>& __rhs) // + noexcept(is_nothrow_constructible_v<_Err, const _Gp&>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__unex_), __rhs.error()); + } + } + + template + requires __can_convert<_Up, _Gp, _Gp> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Gp, _Err>) // + expected(expected<_Up, _Gp>&& __rhs) // + noexcept(is_nothrow_constructible_v<_Err, _Gp>) + : __has_val_(__rhs.__has_val_) { + if (!__rhs.__has_val_) { + std::construct_at(std::addressof(__unex_), std::move(__rhs.error())); + } + } + + template + requires is_constructible_v<_Err, const _Gp&> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v) + expected(const unexpected<_Gp>& __unex) // + noexcept(is_nothrow_constructible_v<_Err, const _Gp&>) + : __has_val_(false), __unex_(__unex.error()) {} + + template + requires is_constructible_v<_Err, _Gp> + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Gp, _Err>) // + expected(unexpected<_Gp>&& __unex) // + noexcept(is_nothrow_constructible_v<_Err, _Gp>) + : __has_val_(false), __unex_(std::move(__unex).error()) {} + + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {} + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, _Args...>) + : __has_val_(false), __unex_(std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) + : __has_val_(false), __unex_(__il, std::forward<_Args>(__args)...) {} + + // [expected.void.dtor], destructor + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires is_trivially_destructible_v<_Err> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr ~expected() + requires(!is_trivially_destructible_v<_Err>) + { + if (!__has_val_) { + std::destroy_at(std::addressof(__unex_)); + } + } + + // [expected.void.assign], assignment + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) // + noexcept((is_nothrow_copy_assignable_v<_Err> && // + is_nothrow_copy_constructible_v<_Err>)) + requires(is_copy_assignable_v<_Err> && // + is_copy_constructible_v<_Err>) + { + if (has_value()) { + if (!__rhs.has_value()) { + std::construct_at(std::addressof(__unex_), __rhs.__unex_); + __has_val_ = false; + } + } else { + if (__rhs.has_value()) { + std::destroy_at(std::addressof(__unex_)); + __has_val_ = true; + } else { + __unex_ = __rhs.error(); + } + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; + + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs) // + noexcept((is_nothrow_move_assignable_v<_Err> && // + is_nothrow_move_constructible_v<_Err>)) + requires(is_move_assignable_v<_Err> && // + is_move_constructible_v<_Err>) + { + if (has_value()) { + if (!__rhs.has_value()) { + std::construct_at(std::addressof(__unex_), std::move(__rhs.__unex_)); + __has_val_ = false; + } + } else { + if (__rhs.has_value()) { + std::destroy_at(std::addressof(__unex_)); + __has_val_ = true; + } else { + __unex_ = std::move(__rhs.error()); + } + } + return *this; + } + + template + requires(is_constructible_v<_Err, const _Gp&> && is_assignable_v<_Err&, const _Gp&>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_Gp>& __un) { + if (has_value()) { + std::construct_at(std::addressof(__unex_), __un.error()); + __has_val_ = false; + } else { + __unex_ = __un.error(); + } + return *this; + } + + template + requires(is_constructible_v<_Err, _Gp> && is_assignable_v<_Err&, _Gp>) + _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_Gp>&& __un) { + if (has_value()) { + std::construct_at(std::addressof(__unex_), std::move(__un.error())); + __has_val_ = false; + } else { + __unex_ = std::move(__un.error()); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { + if (!has_value()) { + std::destroy_at(std::addressof(__unex_)); + __has_val_ = true; + } + } + + // [expected.void.swap], swap + _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs) // + noexcept((is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)) + requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) + { + if (has_value()) { + if (!__rhs.has_value()) { + __swap_val_unex_impl(*this, __rhs); + } + } else { + if (__rhs.has_value()) { + __swap_val_unex_impl(__rhs, *this); + } else { + using std::swap; + swap(__unex_, __rhs.__unex_); + } + } + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) // + noexcept(noexcept(__x.swap(__y))) { + __x.swap(__y); + } + + // [expected.void.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain a value"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { + if (!has_value()) { + throw bad_expected_access<_Err>(__unex_); + } + } + + constexpr void value() && { + if (!has_value()) { + throw bad_expected_access<_Err>(std::move(__unex_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return __unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return __unex_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return std::move(__unex_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + _LIBCPP_ASSERT(!__has_val_, "expected must contain an error"); + return std::move(__unex_); + } + + // [expected.void.eq], equality operators + template + requires is_void_v<_T2> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { + if (__x.has_value() != __y.has_value()) { + return false; + } else { + return __x.has_value() || static_cast(__x.error() == __y.error()); + } + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { + return !__x.has_value() && static_cast(__x.error() == __y.error()); + } + +private: + bool __has_val_; + union { + _Err __unex_; + }; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_EXPECTED_H diff --git a/libcxx/include/__expected/unexpect.h b/libcxx/include/__expected/unexpect.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__expected/unexpect.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_UNEXPECT_H +#define _LIBCPP___EXPECTED_UNEXPECT_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct unexpect_t { + _LIBCPP_HIDE_FROM_ABI explicit unexpect_t() = default; +}; + +inline constexpr unexpect_t unexpect{}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_UNEXPECT_H diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__expected/unexpected.h @@ -0,0 +1,122 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___EXPECTED_UNEXPECTED_H +#define _LIBCPP___EXPECTED_UNEXPECTED_H + +#include <__config> +#include <__type_traits/is_array.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class unexpected; + +namespace __unexpected { + +template +inline constexpr bool __is_unexpected = false; + +template +inline constexpr bool __is_unexpected> = true; + +template +inline constexpr bool __valid_unexpected_error = + is_object_v<_Tp> && // + !is_array_v<_Tp> && // + !__is_unexpected<_Tp> && // + !is_const_v<_Tp> && // + !is_volatile_v<_Tp>; + +} // namespace __unexpected + +template +class unexpected { + static_assert(__unexpected::__valid_unexpected_error<_Err>); + +public: + _LIBCPP_HIDE_FROM_ABI constexpr unexpected(const unexpected&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr unexpected(unexpected&&) = default; + + template + requires(!is_same_v, unexpected> && // + !is_same_v, in_place_t> && // + is_constructible_v<_Err, _Error>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(_Error&& __error) // + noexcept(is_nothrow_constructible_v<_Err, _Error>) + : __unex_(std::forward<_Error>(__error)) {} + + template + requires is_constructible_v<_Err, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, _Args...>) + : __unex_(std::forward<_Args>(__args)...) {} + + template + requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) // + noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) + : __unex_(__il, std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(const unexpected&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(unexpected&&) = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { return __unex_; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { return std::move(__unex_); } + _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { return std::move(__unex_); } + + _LIBCPP_HIDE_FROM_ABI constexpr void swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Err>) { + static_assert(is_swappable_v<_Err>); + using std::swap; + swap(__unex_, __other.__unex_); + } + + template + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) { + return __x.__unex_ == __y.__unex_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(unexpected& __x, unexpected& __y) // + noexcept(noexcept(__x.swap(__y))) + requires is_swappable_v<_Err> + { + __x.swap(__y); + } + +private: + _Err __unex_; +}; + +template +unexpected(_Err) -> unexpected<_Err>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___EXPECTED_UNEXPECTED_H diff --git a/libcxx/include/__type_traits/is_member_pointer.h b/libcxx/include/__type_traits/is_member_pointer.h --- a/libcxx/include/__type_traits/is_member_pointer.h +++ b/libcxx/include/__type_traits/is_member_pointer.h @@ -12,6 +12,10 @@ #include <__config> #include <__type_traits/integral_constant.h> +#if !__has_builtin(__is_nothrow_constructible) +#include <__type_traits/is_member_function_pointer.h> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/__type_traits/is_nothrow_constructible.h b/libcxx/include/__type_traits/is_nothrow_constructible.h --- a/libcxx/include/__type_traits/is_nothrow_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_constructible.h @@ -12,6 +12,11 @@ #include <__config> #include <__type_traits/integral_constant.h> +#if !__has_builtin(__is_nothrow_constructible) +#include <__type_traits/is_reference.h> +#include <__utility/declval.h> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/__type_traits/is_scalar.h b/libcxx/include/__type_traits/is_scalar.h --- a/libcxx/include/__type_traits/is_scalar.h +++ b/libcxx/include/__type_traits/is_scalar.h @@ -13,6 +13,7 @@ #include <__type_traits/integral_constant.h> #include <__type_traits/is_arithmetic.h> #include <__type_traits/is_enum.h> +#include <__type_traits/is_fundamental.h> #include <__type_traits/is_member_pointer.h> #include <__type_traits/is_pointer.h> diff --git a/libcxx/include/__type_traits/is_void.h b/libcxx/include/__type_traits/is_void.h --- a/libcxx/include/__type_traits/is_void.h +++ b/libcxx/include/__type_traits/is_void.h @@ -12,6 +12,10 @@ #include <__config> #include <__type_traits/integral_constant.h> +#if !__has_builtin(__is_nothrow_constructible) +#include <__type_traits/is_same.h> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/expected b/libcxx/include/expected new file mode 100644 --- /dev/null +++ b/libcxx/include/expected @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXEPECTED +#define _LIBCPP_EXEPECTED + +#include <__assert> // all public C++ headers provide the assertion handler +#include <__config> +#include <__expected/bad_expected_access.h> +#include <__expected/expected.h> +#include <__expected/unexpect.h> +#include <__expected/unexpected.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +/* + Header synopsis + +namespace std { + // [expected.unexpected], class template unexpected + template class unexpected; + + // [expected.bad], class template bad_expected_access + template class bad_expected_access; + + // [expected.bad.void], specialization for void + template<> class bad_expected_access; + + // in-place construction of unexpected values + struct unexpect_t { + explicit unexpect_t() = default; + }; + inline constexpr unexpect_t unexpect{}; + + // [expected.expected], class template expected + template class expected; + + // [expected.void], partial specialization of expected for void types + template requires is_void_v class expected; +} + +*/ + +#endif // _LIBCPP_EXEPECTED + diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -619,6 +619,17 @@ header "execution" export * } + module expected { + header "expected" + export * + + module __expected { + module bad_expected_access { private header "__expected/bad_expected_access.h" } + module expected { private header "__expected/expected.h" } + module unexpect { private header "__expected/unexpect.h" } + module unexpected { private header "__expected/unexpected.h" } + } + } module filesystem { @requires_LIBCXX_ENABLE_FILESYSTEM@ header "filesystem" diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -81,6 +81,7 @@ __cpp_lib_exchange_function 201304L __cpp_lib_execution 201902L 201603L // C++17 +__cpp_lib_expected 202202L __cpp_lib_filesystem 201703L __cpp_lib_format 202106L __cpp_lib_forward_like 202207L @@ -388,6 +389,7 @@ # undef __cpp_lib_constexpr_memory # define __cpp_lib_constexpr_memory 202202L // # define __cpp_lib_constexpr_typeinfo 202106L +# define __cpp_lib_expected 202202L # define __cpp_lib_forward_like 202207L // # define __cpp_lib_invoke_r 202106L # define __cpp_lib_is_scoped_enum 202011L diff --git a/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp --- a/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp +++ b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp @@ -306,458 +306,464 @@ using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_47 -#if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) -# include +// RUN: %{build} -DTEST_46 +#if defined(TEST_46) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_49 -#if defined(TEST_49) -# include +// RUN: %{build} -DTEST_48 +#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_50 #if defined(TEST_50) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_51 -#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +#if defined(TEST_51) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_52 -#if defined(TEST_52) -# include +#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_53 -#if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS) -# include +#if defined(TEST_53) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_54 -#if defined(TEST_54) -# include +#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_56 -#if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +// RUN: %{build} -DTEST_55 +#if defined(TEST_55) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_57 #if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_58 -#if defined(TEST_58) -# include +#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_59 -#if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +#if defined(TEST_59) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_60 #if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_61 -#if defined(TEST_61) -# include +#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_62 -#if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS) -# include +#if defined(TEST_62) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_63 -#if defined(TEST_63) -# include +#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_65 -#if defined(TEST_65) -# include +// RUN: %{build} -DTEST_64 +#if defined(TEST_64) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_66 -#if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +#if defined(TEST_66) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_68 -#if defined(TEST_68) -# include +// RUN: %{build} -DTEST_67 +#if defined(TEST_67) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_70 -#if defined(TEST_70) -# include +// RUN: %{build} -DTEST_69 +#if defined(TEST_69) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_71 -#if defined(TEST_71) && !defined(_LIBCPP_HAS_NO_THREADS) -# include +#if defined(TEST_71) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_72 -#if defined(TEST_72) -# include +#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_73 #if defined(TEST_73) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_74 #if defined(TEST_74) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_75 #if defined(TEST_75) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_76 -#if defined(TEST_76) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +#if defined(TEST_76) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_77 -#if defined(TEST_77) -# include +#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_78 #if defined(TEST_78) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_79 #if defined(TEST_79) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_80 #if defined(TEST_80) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_81 -#if defined(TEST_81) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -# include +#if defined(TEST_81) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_82 -#if defined(TEST_82) -# include +#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_83 -#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_THREADS) -# include +#if defined(TEST_83) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_84 -#if defined(TEST_84) +#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS) +# include + using HandlerType = decltype(std::__libcpp_verbose_abort); +#endif + +// RUN: %{build} -DTEST_85 +#if defined(TEST_85) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_86 -#if defined(TEST_86) && !defined(_LIBCPP_HAS_NO_THREADS) +// RUN: %{build} -DTEST_87 +#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_87 -#if defined(TEST_87) +// RUN: %{build} -DTEST_88 +#if defined(TEST_88) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_88 -#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +// RUN: %{build} -DTEST_89 +#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_89 -#if defined(TEST_89) +// RUN: %{build} -DTEST_90 +#if defined(TEST_90) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_93 -#if defined(TEST_93) +// RUN: %{build} -DTEST_94 +#if defined(TEST_94) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_97 -#if defined(TEST_97) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +// RUN: %{build} -DTEST_98 +#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_98 -#if defined(TEST_98) +// RUN: %{build} -DTEST_99 +#if defined(TEST_99) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_100 -#if defined(TEST_100) +// RUN: %{build} -DTEST_101 +#if defined(TEST_101) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_101 -#if defined(TEST_101) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +// RUN: %{build} -DTEST_102 +#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_102 -#if defined(TEST_102) +// RUN: %{build} -DTEST_103 +#if defined(TEST_103) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_104 -#if defined(TEST_104) && !defined(_LIBCPP_HAS_NO_THREADS) -# include - using HandlerType = decltype(std::__libcpp_verbose_abort); -#endif - // RUN: %{build} -DTEST_105 -#if defined(TEST_105) -# include +#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_106 #if defined(TEST_106) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_107 #if defined(TEST_107) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_108 #if defined(TEST_108) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_110 -#if defined(TEST_110) -# include +// RUN: %{build} -DTEST_109 +#if defined(TEST_109) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_111 #if defined(TEST_111) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_112 #if defined(TEST_112) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_113 #if defined(TEST_113) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_114 #if defined(TEST_114) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_115 #if defined(TEST_115) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_116 #if defined(TEST_116) -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif -// RUN: %{build} -DTEST_119 -#if defined(TEST_119) && __cplusplus >= 201103L -# include +// RUN: %{build} -DTEST_117 +#if defined(TEST_117) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_120 -#if defined(TEST_120) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) -# include +#if defined(TEST_120) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_121 -#if defined(TEST_121) && __cplusplus >= 201103L -# include +#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_122 #if defined(TEST_122) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_123 #if defined(TEST_123) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_124 #if defined(TEST_124) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_125 #if defined(TEST_125) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_126 #if defined(TEST_126) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_127 #if defined(TEST_127) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_128 #if defined(TEST_128) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_129 -#if defined(TEST_129) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L -# include +#if defined(TEST_129) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_130 -#if defined(TEST_130) && __cplusplus >= 201103L -# include +#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_131 #if defined(TEST_131) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_132 #if defined(TEST_132) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_133 #if defined(TEST_133) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_134 #if defined(TEST_134) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_135 #if defined(TEST_135) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_136 #if defined(TEST_136) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_137 #if defined(TEST_137) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_138 -#if defined(TEST_138) -# include +#if defined(TEST_138) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_139 #if defined(TEST_139) +# include + using HandlerType = decltype(std::__libcpp_verbose_abort); +#endif + +// RUN: %{build} -DTEST_140 +#if defined(TEST_140) # include using HandlerType = decltype(std::__libcpp_verbose_abort); #endif diff --git a/libcxx/test/libcxx/clang_tidy.sh.cpp b/libcxx/test/libcxx/clang_tidy.sh.cpp --- a/libcxx/test/libcxx/clang_tidy.sh.cpp +++ b/libcxx/test/libcxx/clang_tidy.sh.cpp @@ -91,6 +91,7 @@ #include #include #include +#include #include #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) # include diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -93,6 +93,7 @@ #include #include #include +#include #include #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) # include diff --git a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp --- a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp +++ b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp @@ -139,6 +139,8 @@ TEST_MACROS(); #include TEST_MACROS(); +#include +TEST_MACROS(); #include TEST_MACROS(); #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) diff --git a/libcxx/test/libcxx/modules_include.sh.cpp b/libcxx/test/libcxx/modules_include.sh.cpp --- a/libcxx/test/libcxx/modules_include.sh.cpp +++ b/libcxx/test/libcxx/modules_include.sh.cpp @@ -232,378 +232,382 @@ #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_46 #if defined(TEST_46) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_47 -#if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) -#include +#if defined(TEST_47) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_48 -#if defined(TEST_48) -#include +#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_49 #if defined(TEST_49) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_50 #if defined(TEST_50) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_51 -#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_51) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_52 -#if defined(TEST_52) -#include +#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_53 -#if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_53) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_54 -#if defined(TEST_54) -#include +#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_55 #if defined(TEST_55) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_56 -#if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_56) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_57 #if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_58 -#if defined(TEST_58) -#include +#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_59 -#if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_59) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_60 #if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_61 -#if defined(TEST_61) -#include +#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_62 -#if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_62) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_63 -#if defined(TEST_63) -#include +#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_64 #if defined(TEST_64) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_65 #if defined(TEST_65) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_66 -#if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_66) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_67 #if defined(TEST_67) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_68 -#if defined(TEST_68) -#include +#if defined(TEST_68) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_69 #if defined(TEST_69) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_70 #if defined(TEST_70) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_71 -#if defined(TEST_71) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_71) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_72 -#if defined(TEST_72) -#include +#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_73 #if defined(TEST_73) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_74 #if defined(TEST_74) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_75 #if defined(TEST_75) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_76 -#if defined(TEST_76) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_76) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_77 -#if defined(TEST_77) -#include +#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_78 #if defined(TEST_78) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_79 #if defined(TEST_79) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_80 #if defined(TEST_80) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_81 -#if defined(TEST_81) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_81) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_82 -#if defined(TEST_82) -#include +#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_83 -#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_83) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_84 -#if defined(TEST_84) -#include +#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_85 #if defined(TEST_85) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_86 -#if defined(TEST_86) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_86) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_87 -#if defined(TEST_87) -#include +#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_88 -#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_88) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_89 -#if defined(TEST_89) -#include +#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_90 -#if defined(TEST_90) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_90) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_91 -#if defined(TEST_91) -#include +#if defined(TEST_91) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_92 #if defined(TEST_92) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_93 #if defined(TEST_93) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_94 #if defined(TEST_94) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_95 #if defined(TEST_95) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_96 #if defined(TEST_96) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_97 -#if defined(TEST_97) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_97) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_98 -#if defined(TEST_98) -#include +#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_99 #if defined(TEST_99) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_100 #if defined(TEST_100) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_101 -#if defined(TEST_101) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) -#include +#if defined(TEST_101) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_102 -#if defined(TEST_102) -#include +#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_103 #if defined(TEST_103) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_104 -#if defined(TEST_104) && !defined(_LIBCPP_HAS_NO_THREADS) -#include +#if defined(TEST_104) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_105 -#if defined(TEST_105) -#include +#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_106 #if defined(TEST_106) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_107 #if defined(TEST_107) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_108 #if defined(TEST_108) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_109 #if defined(TEST_109) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_110 #if defined(TEST_110) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_111 #if defined(TEST_111) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_112 #if defined(TEST_112) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_113 #if defined(TEST_113) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_114 #if defined(TEST_114) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_115 #if defined(TEST_115) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_116 #if defined(TEST_116) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_117 -#if defined(TEST_117) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) -#include +#if defined(TEST_117) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_118 #if defined(TEST_118) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_119 -#if defined(TEST_119) && __cplusplus >= 201103L -#include +#if defined(TEST_119) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_120 -#if defined(TEST_120) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) -#include +#if defined(TEST_120) && __cplusplus >= 201103L +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_121 -#if defined(TEST_121) && __cplusplus >= 201103L -#include +#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_122 #if defined(TEST_122) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_123 #if defined(TEST_123) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_124 #if defined(TEST_124) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_125 #if defined(TEST_125) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_126 #if defined(TEST_126) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_127 #if defined(TEST_127) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_128 #if defined(TEST_128) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_129 -#if defined(TEST_129) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L -#include +#if defined(TEST_129) && __cplusplus >= 201103L +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_130 -#if defined(TEST_130) && __cplusplus >= 201103L -#include +#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_131 #if defined(TEST_131) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_132 #if defined(TEST_132) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_133 #if defined(TEST_133) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_134 #if defined(TEST_134) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_135 #if defined(TEST_135) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_136 #if defined(TEST_136) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_137 #if defined(TEST_137) && __cplusplus >= 201103L -#include +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_138 -#if defined(TEST_138) -#include +#if defined(TEST_138) && __cplusplus >= 201103L +#include #endif // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_139 #if defined(TEST_139) +#include +#endif +// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_140 +#if defined(TEST_140) #include #endif // GENERATED-MARKER diff --git a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp --- a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp +++ b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp @@ -212,6 +212,7 @@ #include #include #include +#include #include #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) # include diff --git a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp --- a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp +++ b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp @@ -90,6 +90,7 @@ #include #include #include +#include #include #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) # include diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -301,6 +301,10 @@ #include <__coroutine/trivial_awaitables.h> // expected-error@*:* {{use of private header from outside its module: '__coroutine/trivial_awaitables.h'}} #include <__debug_utils/randomize_range.h> // expected-error@*:* {{use of private header from outside its module: '__debug_utils/randomize_range.h'}} #include <__errc> // expected-error@*:* {{use of private header from outside its module: '__errc'}} +#include <__expected/bad_expected_access.h> // expected-error@*:* {{use of private header from outside its module: '__expected/bad_expected_access.h'}} +#include <__expected/expected.h> // expected-error@*:* {{use of private header from outside its module: '__expected/expected.h'}} +#include <__expected/unexpect.h> // expected-error@*:* {{use of private header from outside its module: '__expected/unexpect.h'}} +#include <__expected/unexpected.h> // expected-error@*:* {{use of private header from outside its module: '__expected/unexpected.h'}} #include <__filesystem/copy_options.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/copy_options.h'}} #include <__filesystem/directory_entry.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/directory_entry.h'}} #include <__filesystem/directory_iterator.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/directory_iterator.h'}} diff --git a/libcxx/test/libcxx/transitive_includes.sh.cpp b/libcxx/test/libcxx/transitive_includes.sh.cpp --- a/libcxx/test/libcxx/transitive_includes.sh.cpp +++ b/libcxx/test/libcxx/transitive_includes.sh.cpp @@ -295,384 +295,389 @@ #if defined(TEST_45) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_47 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.filesystem +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_46 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.expected +// RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.expected %t.actual.expected +#if defined(TEST_46) +#include +#endif +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_48 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.filesystem // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.filesystem %t.actual.filesystem -#if defined(TEST_47) +#if defined(TEST_48) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_49 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.format +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_50 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.format // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.format %t.actual.format -#if defined(TEST_49) +#if defined(TEST_50) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_50 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.forward_list +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_51 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.forward_list // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.forward_list %t.actual.forward_list -#if defined(TEST_50) +#if defined(TEST_51) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_51 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.fstream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_52 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.fstream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.fstream %t.actual.fstream -#if defined(TEST_51) +#if defined(TEST_52) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_52 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.functional +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_53 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.functional // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.functional %t.actual.functional -#if defined(TEST_52) +#if defined(TEST_53) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_53 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.future +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_54 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.future // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.future %t.actual.future -#if defined(TEST_53) +#if defined(TEST_54) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_54 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.initializer_list +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_55 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.initializer_list // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.initializer_list %t.actual.initializer_list -#if defined(TEST_54) +#if defined(TEST_55) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_56 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iomanip +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_57 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iomanip // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.iomanip %t.actual.iomanip -#if defined(TEST_56) +#if defined(TEST_57) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_57 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ios +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_58 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ios // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ios %t.actual.ios -#if defined(TEST_57) +#if defined(TEST_58) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_58 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iosfwd +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_59 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iosfwd // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.iosfwd %t.actual.iosfwd -#if defined(TEST_58) +#if defined(TEST_59) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_59 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iostream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_60 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iostream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.iostream %t.actual.iostream -#if defined(TEST_59) +#if defined(TEST_60) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_60 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.istream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_61 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.istream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.istream %t.actual.istream -#if defined(TEST_60) +#if defined(TEST_61) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_61 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iterator +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_62 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.iterator // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.iterator %t.actual.iterator -#if defined(TEST_61) +#if defined(TEST_62) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_62 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.latch +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_63 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.latch // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.latch %t.actual.latch -#if defined(TEST_62) +#if defined(TEST_63) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_63 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.limits +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_64 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.limits // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.limits %t.actual.limits -#if defined(TEST_63) +#if defined(TEST_64) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_65 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.list +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_66 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.list // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.list %t.actual.list -#if defined(TEST_65) +#if defined(TEST_66) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_66 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.locale +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_67 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.locale // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.locale %t.actual.locale -#if defined(TEST_66) +#if defined(TEST_67) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_68 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.map +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_69 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.map // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.map %t.actual.map -#if defined(TEST_68) +#if defined(TEST_69) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_70 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.memory +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_71 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.memory // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.memory %t.actual.memory -#if defined(TEST_70) +#if defined(TEST_71) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_71 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.mutex +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_72 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.mutex // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.mutex %t.actual.mutex -#if defined(TEST_71) +#if defined(TEST_72) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_72 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.new +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_73 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.new // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.new %t.actual.new -#if defined(TEST_72) +#if defined(TEST_73) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_73 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.numbers +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_74 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.numbers // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.numbers %t.actual.numbers -#if defined(TEST_73) +#if defined(TEST_74) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_74 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.numeric +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_75 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.numeric // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.numeric %t.actual.numeric -#if defined(TEST_74) +#if defined(TEST_75) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_75 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.optional +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_76 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.optional // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.optional %t.actual.optional -#if defined(TEST_75) +#if defined(TEST_76) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_76 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ostream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_77 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ostream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ostream %t.actual.ostream -#if defined(TEST_76) +#if defined(TEST_77) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_77 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.queue +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_78 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.queue // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.queue %t.actual.queue -#if defined(TEST_77) +#if defined(TEST_78) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_78 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.random +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_79 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.random // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.random %t.actual.random -#if defined(TEST_78) +#if defined(TEST_79) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_79 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ranges +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_80 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ranges // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ranges %t.actual.ranges -#if defined(TEST_79) +#if defined(TEST_80) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_80 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ratio +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_81 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ratio // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ratio %t.actual.ratio -#if defined(TEST_80) +#if defined(TEST_81) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_81 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.regex +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_82 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.regex // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.regex %t.actual.regex -#if defined(TEST_81) +#if defined(TEST_82) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_82 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.scoped_allocator +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_83 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.scoped_allocator // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.scoped_allocator %t.actual.scoped_allocator -#if defined(TEST_82) +#if defined(TEST_83) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_83 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.semaphore +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_84 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.semaphore // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.semaphore %t.actual.semaphore -#if defined(TEST_83) +#if defined(TEST_84) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_84 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.set +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_85 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.set // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.set %t.actual.set -#if defined(TEST_84) +#if defined(TEST_85) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_86 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.shared_mutex +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_87 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.shared_mutex // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.shared_mutex %t.actual.shared_mutex -#if defined(TEST_86) +#if defined(TEST_87) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_87 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.span +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_88 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.span // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.span %t.actual.span -#if defined(TEST_87) +#if defined(TEST_88) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_88 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.sstream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_89 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.sstream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.sstream %t.actual.sstream -#if defined(TEST_88) +#if defined(TEST_89) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_89 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.stack +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_90 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.stack // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.stack %t.actual.stack -#if defined(TEST_89) +#if defined(TEST_90) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_93 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.stdexcept +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_94 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.stdexcept // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.stdexcept %t.actual.stdexcept -#if defined(TEST_93) +#if defined(TEST_94) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_97 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.streambuf +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_98 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.streambuf // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.streambuf %t.actual.streambuf -#if defined(TEST_97) +#if defined(TEST_98) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_98 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.string +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_99 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.string // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.string %t.actual.string -#if defined(TEST_98) +#if defined(TEST_99) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_100 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.string_view +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_101 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.string_view // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.string_view %t.actual.string_view -#if defined(TEST_100) +#if defined(TEST_101) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_101 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.strstream +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_102 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.strstream // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.strstream %t.actual.strstream -#if defined(TEST_101) +#if defined(TEST_102) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_102 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.system_error +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_103 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.system_error // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.system_error %t.actual.system_error -#if defined(TEST_102) +#if defined(TEST_103) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_104 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.thread +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_105 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.thread // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.thread %t.actual.thread -#if defined(TEST_104) +#if defined(TEST_105) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_105 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.tuple +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_106 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.tuple // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.tuple %t.actual.tuple -#if defined(TEST_105) +#if defined(TEST_106) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_106 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.type_traits +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_107 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.type_traits // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.type_traits %t.actual.type_traits -#if defined(TEST_106) +#if defined(TEST_107) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_107 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.typeindex +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_108 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.typeindex // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.typeindex %t.actual.typeindex -#if defined(TEST_107) +#if defined(TEST_108) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_108 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.typeinfo +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_109 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.typeinfo // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.typeinfo %t.actual.typeinfo -#if defined(TEST_108) +#if defined(TEST_109) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_110 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.unordered_map +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_111 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.unordered_map // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.unordered_map %t.actual.unordered_map -#if defined(TEST_110) +#if defined(TEST_111) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_111 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.unordered_set +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_112 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.unordered_set // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.unordered_set %t.actual.unordered_set -#if defined(TEST_111) +#if defined(TEST_112) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_112 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.utility +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_113 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.utility // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.utility %t.actual.utility -#if defined(TEST_112) +#if defined(TEST_113) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_113 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.valarray +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_114 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.valarray // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.valarray %t.actual.valarray -#if defined(TEST_113) +#if defined(TEST_114) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_114 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.variant +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_115 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.variant // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.variant %t.actual.variant -#if defined(TEST_114) +#if defined(TEST_115) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_115 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.vector +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_116 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.vector // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.vector %t.actual.vector -#if defined(TEST_115) +#if defined(TEST_116) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_116 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.version +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_117 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.version // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.version %t.actual.version -#if defined(TEST_116) +#if defined(TEST_117) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_119 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_algorithm +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_120 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_algorithm // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_algorithm %t.actual.experimental_algorithm -#if defined(TEST_119) +#if defined(TEST_120) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_120 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_coroutine +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_121 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_coroutine // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_coroutine %t.actual.experimental_coroutine -#if defined(TEST_120) +#if defined(TEST_121) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_121 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_deque +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_122 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_deque // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_deque %t.actual.experimental_deque -#if defined(TEST_121) +#if defined(TEST_122) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_122 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_forward_list +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_123 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_forward_list // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_forward_list %t.actual.experimental_forward_list -#if defined(TEST_122) +#if defined(TEST_123) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_123 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_functional +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_124 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_functional // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_functional %t.actual.experimental_functional -#if defined(TEST_123) +#if defined(TEST_124) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_124 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_iterator +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_125 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_iterator // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_iterator %t.actual.experimental_iterator -#if defined(TEST_124) +#if defined(TEST_125) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_125 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_list +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_126 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_list // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_list %t.actual.experimental_list -#if defined(TEST_125) +#if defined(TEST_126) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_126 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_map +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_127 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_map // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_map %t.actual.experimental_map -#if defined(TEST_126) +#if defined(TEST_127) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_127 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_memory_resource +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_128 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_memory_resource // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_memory_resource %t.actual.experimental_memory_resource -#if defined(TEST_127) +#if defined(TEST_128) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_128 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_propagate_const +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_129 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_propagate_const // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_propagate_const %t.actual.experimental_propagate_const -#if defined(TEST_128) +#if defined(TEST_129) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_129 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_regex +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_130 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_regex // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_regex %t.actual.experimental_regex -#if defined(TEST_129) +#if defined(TEST_130) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_130 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_set +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_131 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_set // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_set %t.actual.experimental_set -#if defined(TEST_130) +#if defined(TEST_131) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_131 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_simd +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_132 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_simd // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_simd %t.actual.experimental_simd -#if defined(TEST_131) +#if defined(TEST_132) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_132 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_string +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_133 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_string // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_string %t.actual.experimental_string -#if defined(TEST_132) +#if defined(TEST_133) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_133 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_type_traits +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_134 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_type_traits // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_type_traits %t.actual.experimental_type_traits -#if defined(TEST_133) +#if defined(TEST_134) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_134 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_unordered_map +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_135 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_unordered_map // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_unordered_map %t.actual.experimental_unordered_map -#if defined(TEST_134) +#if defined(TEST_135) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_135 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_unordered_set +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_136 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_unordered_set // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_unordered_set %t.actual.experimental_unordered_set -#if defined(TEST_135) +#if defined(TEST_136) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_136 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_utility +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_137 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_utility // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_utility %t.actual.experimental_utility -#if defined(TEST_136) +#if defined(TEST_137) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_137 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_vector +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_138 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.experimental_vector // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.experimental_vector %t.actual.experimental_vector -#if defined(TEST_137) +#if defined(TEST_138) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_138 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ext_hash_map +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_139 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ext_hash_map // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ext_hash_map %t.actual.ext_hash_map -#if defined(TEST_138) +#if defined(TEST_139) #include #endif -// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_139 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ext_hash_set +// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fsyntax-only -DTEST_140 2>&1 | %{python} %S/transitive_includes.sanitize.py > %t.actual.ext_hash_set // RUN: diff -w %S/transitive_includes/%{cxx_std}/expected.ext_hash_set %t.actual.ext_hash_set -#if defined(TEST_139) +#if defined(TEST_140) #include #endif // GENERATED-MARKER diff --git a/libcxx/test/libcxx/transitive_includes/cxx03/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx03/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx03/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/transitive_includes/cxx11/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx11/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx11/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/transitive_includes/cxx14/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx14/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx14/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/transitive_includes/cxx17/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx17/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx17/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/transitive_includes/cxx20/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx20/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx20/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b/expected.expected b/libcxx/test/libcxx/transitive_includes/cxx2b/expected.expected new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/cxx2b/expected.expected @@ -0,0 +1,8 @@ +cstddef +cstdint +cstdlib +exception +initializer_list +new +type_traits +version diff --git a/libcxx/test/libcxx/utilities/expected/version.pass.cpp b/libcxx/test/libcxx/utilities/expected/version.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/expected/version.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include + +#include "test_macros.h" + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main(int, char**) +{ + + return 0; +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// WARNING: This test was generated by generate_feature_test_macro_components.py +// and should not be edited manually. +// +// clang-format off + +// + +// Test the feature test macros defined by + +/* Constant Value + __cpp_lib_expected 202202L [C++2b] +*/ + +#include +#include "test_macros.h" + +#if TEST_STD_VER < 14 + +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 14 + +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 17 + +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 20 + +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + +#elif TEST_STD_VER > 20 + +# ifndef __cpp_lib_expected +# error "__cpp_lib_expected should be defined in c++2b" +# endif +# if __cpp_lib_expected != 202202L +# error "__cpp_lib_expected should have the value 202202L in c++2b" +# endif + +#endif // TEST_STD_VER > 20 + diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -75,6 +75,7 @@ __cpp_lib_exchange_function 201304L [C++14] __cpp_lib_execution 201603L [C++17] 201902L [C++20] + __cpp_lib_expected 202202L [C++2b] __cpp_lib_filesystem 201703L [C++17] __cpp_lib_format 202106L [C++20] __cpp_lib_forward_like 202207L [C++2b] @@ -411,6 +412,10 @@ # error "__cpp_lib_execution should not be defined before c++17" # endif +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + # ifdef __cpp_lib_filesystem # error "__cpp_lib_filesystem should not be defined before c++17" # endif @@ -1050,6 +1055,10 @@ # error "__cpp_lib_execution should not be defined before c++17" # endif +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + # ifdef __cpp_lib_filesystem # error "__cpp_lib_filesystem should not be defined before c++17" # endif @@ -1794,6 +1803,10 @@ # endif # endif +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) # ifndef __cpp_lib_filesystem # error "__cpp_lib_filesystem should be defined in c++17" @@ -2835,6 +2848,10 @@ # endif # endif +# ifdef __cpp_lib_expected +# error "__cpp_lib_expected should not be defined before c++2b" +# endif + # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) # ifndef __cpp_lib_filesystem # error "__cpp_lib_filesystem should be defined in c++20" @@ -4077,6 +4094,13 @@ # endif # endif +# ifndef __cpp_lib_expected +# error "__cpp_lib_expected should be defined in c++2b" +# endif +# if __cpp_lib_expected != 202202L +# error "__cpp_lib_expected should have the value 202202L in c++2b" +# endif + # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) # ifndef __cpp_lib_filesystem # error "__cpp_lib_filesystem should be defined in c++2b" diff --git a/libcxx/test/std/utilities/expected/expected.bad/ctor.error.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/ctor.error.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.bad/ctor.error.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// explicit bad_expected_access(E e); + +// Effects: Initializes unex with std::move(e). + +#include +#include +#include + +#include "test_macros.h" +#include "MoveOnly.h" + +// test explicit +static_assert(std::convertible_to); +static_assert(!std::convertible_to>); + +int main(int, char**) { + std::bad_expected_access b(MoveOnly{3}); + assert(b.error().get() == 3); + + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.bad/error.member.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/error.member.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.bad/error.member.pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// E& error() & noexcept; +// const E& error() const & noexcept; +// E&& error() && noexcept; +// const E&& error() const && noexcept; + +#include +#include +#include +#include + +template +concept ErrorNoexcept = + requires(T&& t) { + { std::forward(t).error() } noexcept; + }; + +static_assert(!ErrorNoexcept); +static_assert(ErrorNoexcept&>); +static_assert(ErrorNoexcept const&>); +static_assert(ErrorNoexcept&&>); +static_assert(ErrorNoexcept const&&>); + +void test() { + // & + { + std::bad_expected_access e(5); + std::same_as decltype(auto) i = e.error(); + assert(i == 5); + } + + // const & + { + const std::bad_expected_access e(5); + std::same_as decltype(auto) i = e.error(); + assert(i == 5); + } + + // && + { + std::bad_expected_access e(5); + std::same_as decltype(auto) i = std::move(e).error(); + assert(i == 5); + } + + // const && + { + const std::bad_expected_access e(5); + std::same_as decltype(auto) i = std::move(e).error(); + assert(i == 5); + } +} + +int main(int, char**) { + test(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp b/libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// const char* what() const noexcept override; + +#include +#include + +template +concept WhatNoexcept = + requires(const T& t) { + { t.what() } noexcept; + }; + +struct foo{}; + +static_assert(!WhatNoexcept); +static_assert(WhatNoexcept>); +static_assert(WhatNoexcept>); diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.U.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.U.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.U.pass.cpp @@ -0,0 +1,322 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr expected& operator=(U&& v); +// +// Constraints: +// - is_same_v> is false; and +// - remove_cvref_t is not a specialization of unexpected; and +// - is_constructible_v is true; and +// - is_assignable_v is true; and +// - is_nothrow_constructible_v || is_nothrow_move_constructible_v || +// is_nothrow_move_constructible_v is true. +// +// Effects: +// - If has_value() is true, equivalent to: val = std::forward(v); +// - Otherwise, equivalent to: +// reinit-expected(val, unex, std::forward(v)); +// has_val = true; +// - Returns: *this. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotCopyConstructible { + NotCopyConstructible(const NotCopyConstructible&) = delete; + NotCopyConstructible& operator=(const NotCopyConstructible&) = default; +}; + +struct NotCopyAssignable { + NotCopyAssignable(const NotCopyAssignable&) = default; + NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; +}; + +// Test constraints +static_assert(std::is_assignable_v&, int>); + +// is_same_v> +// it is true because it covered by the copy assignment +static_assert(std::is_assignable_v&, std::expected>); + +// remove_cvref_t is a specialization of unexpected +// it is true because it covered the unepxected overload +static_assert(std::is_assignable_v&, std::unexpected>); + +// !is_constructible_v +struct NoCtorFromInt { + NoCtorFromInt(int) = delete; + NoCtorFromInt& operator=(int); +}; +static_assert(!std::is_assignable_v&, int>); + +// !is_assignable_v +struct NoAssignFromInt { + explicit NoAssignFromInt(int); + NoAssignFromInt& operator=(int) = delete; +}; +static_assert(!std::is_assignable_v&, int>); + +template +struct MaybeNoexcept { + explicit MaybeNoexcept(int) noexcept(convertNoexcept); + MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept); + MaybeNoexcept& operator=(MaybeNoexcept&&) = default; + MaybeNoexcept& operator=(int); +}; + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, int>&, int>); + +// is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, int>); + +// !is_nothrow_constructible_v && is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, int>); + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(!std::is_assignable_v, MaybeNoexcept>&, int>); + +constexpr bool test() { + // If has_value() is true, equivalent to: val = std::forward(v); + // Copy + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + Traced u(newState, 10); + std::same_as&> decltype(auto) x = (e1 = u); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + assert(oldState.copyAssignCalled); + } + + // If has_value() is true, equivalent to: val = std::forward(v); + // Move + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + Traced u(newState, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(u)); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + assert(oldState.moveAssignCalled); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // is_nothrow_constructible_v && !is_nothrow_move_constructible_v && + // !is_nothrow_move_constructible_v + // copy + // + // In this case, it should call the branch + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + { + BothMayThrow::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + const int i = 10; + std::same_as&> decltype(auto) x = (e1 = i); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e1.value().copiedFromInt); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // is_nothrow_constructible_v && !is_nothrow_move_constructible_v && + // !is_nothrow_move_constructible_v + // move + // + // In this case, it should call the branch + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + { + BothMayThrow::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + std::same_as&> decltype(auto) x = (e1 = 10); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e1.value().movedFromInt); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // !is_nothrow_constructible_v && is_nothrow_move_constructible_v && + // !is_nothrow_move_constructible_v + // copy + // + // In this case, it should call the branch + // T tmp(std::forward(args)...); + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::move(tmp)); + { + BothMayThrow::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + const int i = 10; + std::same_as&> decltype(auto) x = (e1 = i); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!e1.value().copiedFromInt); + assert(e1.value().movedFromTmp); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // !is_nothrow_constructible_v && is_nothrow_move_constructible_v && + // !is_nothrow_move_constructible_v + // move + // + // In this case, it should call the branch + // T tmp(std::forward(args)...); + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::move(tmp)); + { + BothMayThrow::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + std::same_as&> decltype(auto) x = (e1 = 10); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!e1.value().copiedFromInt); + assert(e1.value().movedFromTmp); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && + // is_nothrow_move_constructible_v + // copy + // + // In this case, it should call the branch + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + { + TracedNoexcept::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + const int i = 10; + std::same_as&> decltype(auto) x = (e1 = i); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e1.value().copiedFromInt); + } + + // Otherwise, equivalent to: + // reinit-expected(val, unex, std::forward(v)); + // !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && + // is_nothrow_move_constructible_v + // move + // + // In this case, it should call the branch + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + { + TracedNoexcept::state oldState{}; + std::expected e1(std::unexpect, oldState, 5); + std::same_as&> decltype(auto) x = (e1 = 10); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyCtorCalled); + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e1.value().movedFromInt); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnConvert { + ThrowOnConvert() = default; + ThrowOnConvert(int) { throw Except{}; } + ThrowOnConvert(const ThrowOnConvert&) noexcept(false) {} + ThrowOnConvert& operator=(const ThrowOnConvert&) = default; + ThrowOnConvert(ThrowOnConvert&&) noexcept(false) {} + ThrowOnConvert& operator=(ThrowOnConvert&&) = default; + }; + + std::expected e1(std::unexpect, 5); + try { + e1 = 10; + assert(false); + } catch (Except) { + assert(!e1.has_value()); + assert(e1.error() == 5); + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp @@ -0,0 +1,284 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected& operator=(const expected& rhs); +// +// Effects: +// - If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs. +// - Otherwise, if this->has_value() is true, equivalent to: +// reinit-expected(unex, val, rhs.error()) +// - Otherwise, if rhs.has_value() is true, equivalent to: +// reinit-expected(val, unex, *rhs) +// - Otherwise, equivalent to unex = rhs.error(). +// +// - Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this; +// +// Returns: *this. +// +// Remarks: This operator is defined as deleted unless: +// - is_copy_assignable_v is true and +// - is_copy_constructible_v is true and +// - is_copy_assignable_v is true and +// - is_copy_constructible_v is true and +// - is_nothrow_move_constructible_v || is_nothrow_move_constructible_v is true. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotCopyConstructible { + NotCopyConstructible(const NotCopyConstructible&) = delete; + NotCopyConstructible& operator=(const NotCopyConstructible&) = default; +}; + +struct NotCopyAssignable { + NotCopyAssignable(const NotCopyAssignable&) = default; + NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow const&) = default; + MoveMayThrow& operator=(const MoveMayThrow&) = default; + MoveMayThrow(MoveMayThrow&&) noexcept(false) {} + MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; } +}; + +// Test constraints +static_assert(std::is_copy_assignable_v>); + +// !is_copy_assignable_v +static_assert(!std::is_copy_assignable_v>); + +// !is_copy_constructible_v +static_assert(!std::is_copy_assignable_v>); + +// !is_copy_assignable_v +static_assert(!std::is_copy_assignable_v>); + +// !is_copy_constructible_v +static_assert(!std::is_copy_assignable_v>); + +// !is_nothrow_move_constructible_v && is_nothrow_move_constructible_v +static_assert(std::is_copy_assignable_v>); + +// is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(std::is_copy_assignable_v>); + +// !is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(!std::is_copy_assignable_v>); + +constexpr bool test() { + // If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs. + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + const std::expected e2(std::in_place, newState, 10); + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + assert(oldState.copyAssignCalled); + } + + // - Otherwise, if this->has_value() is true, equivalent to: + // reinit-expected(unex, val, rhs.error()) + // E move is not noexcept + // In this case, it should call the branch + // + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + // + { + TracedNoexcept::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + const std::expected e2(std::unexpect, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(!oldState.copyAssignCalled); + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(newState.copyCtorCalled); + assert(!newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if this->has_value() is true, equivalent to: + // reinit-expected(unex, val, rhs.error()) + // E move is noexcept + // In this case, it should call the branch + // + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + // + { + Traced::state oldState{}; + TracedNoexcept::state newState{}; + std::expected e1(std::in_place, oldState, 5); + const std::expected e2(std::unexpect, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(!oldState.copyAssignCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(newState.copyCtorCalled); + assert(!newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if rhs.has_value() is true, equivalent to: + // reinit-expected(val, unex, *rhs) + // T move is not noexcept + // In this case, it should call the branch + // + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + // + { + TracedNoexcept::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + const std::expected e2(std::in_place, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyAssignCalled); + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(newState.copyCtorCalled); + assert(!newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if rhs.has_value() is true, equivalent to: + // reinit-expected(val, unex, *rhs) + // T move is noexcept + // In this case, it should call the branch + // + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + // + { + Traced::state oldState{}; + TracedNoexcept::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + const std::expected e2(std::in_place, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.copyAssignCalled); + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(newState.copyCtorCalled); + assert(!newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // Otherwise, equivalent to unex = rhs.error(). + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + const std::expected e2(std::unexpect, newState, 10); + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(oldState.copyAssignCalled); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnCopy { + ThrowOnCopy() = default; + ThrowOnCopy(const ThrowOnCopy&) { throw Except{}; }; + ThrowOnCopy& operator=(const ThrowOnCopy&) = default; + ThrowOnCopy(ThrowOnCopy&&) noexcept(false) {} + }; + + // assign value throw on copy + { + std::expected e1(std::unexpect, 5); + const std::expected e2(std::in_place); + try { + e1 = e2; + assert(false); + } catch (Except) { + assert(!e1.has_value()); + assert(e1.error() == 5); + } + } + + // assign error throw on copy + { + std::expected e1(5); + const std::expected e2(std::unexpect); + try { + e1 = e2; + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(e1.value() == 5); + } + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp @@ -0,0 +1,301 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected& operator=(expected&& rhs) noexcept(see below); +// +// Constraints: +// - is_move_constructible_v is true and +// - is_move_assignable_v is true and +// - is_move_constructible_v is true and +// - is_move_assignable_v is true and +// - is_nothrow_move_constructible_v || is_nothrow_move_constructible_v is true. +// +// Effects: +// - If this->has_value() && rhs.has_value() is true, equivalent to val = std::move(*rhs). +// - Otherwise, if this->has_value() is true, equivalent to: +// reinit-expected(unex, val, std::move(rhs.error())) +// - Otherwise, if rhs.has_value() is true, equivalent to: +// reinit-expected(val, unex, std::move(*rhs)) +// - Otherwise, equivalent to unex = std::move(rhs.error()). +// - Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this; +// +// Returns: *this. +// +// Remarks: The exception specification is equivalent to: +// is_nothrow_move_assignable_v && is_nothrow_move_constructible_v && +// is_nothrow_move_assignable_v && is_nothrow_move_constructible_v + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotMoveConstructible { + NotMoveConstructible(NotMoveConstructible&&) = delete; + NotMoveConstructible& operator=(NotMoveConstructible&&) = default; +}; + +struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&) = default; + NotMoveAssignable& operator=(NotMoveAssignable&&) = delete; +}; + +struct MoveCtorMayThrow { + MoveCtorMayThrow(MoveCtorMayThrow&&) noexcept(false) {} + MoveCtorMayThrow& operator=(MoveCtorMayThrow&&) noexcept = default; +}; + +// Test constraints +static_assert(std::is_move_assignable_v>); + +// !is_move_assignable_v +static_assert(!std::is_move_assignable_v>); + +// !is_move_constructible_v +static_assert(!std::is_move_assignable_v>); + +// !is_move_assignable_v +static_assert(!std::is_move_assignable_v>); + +// !is_move_constructible_v +static_assert(!std::is_move_assignable_v>); + +// !is_nothrow_move_constructible_v && is_nothrow_move_constructible_v +static_assert(std::is_move_assignable_v>); + +// is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(std::is_move_assignable_v>); + +// !is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(!std::is_move_assignable_v>); + +struct MoveAssignMayThrow { + MoveAssignMayThrow(MoveAssignMayThrow&&) noexcept = default; + MoveAssignMayThrow& operator=(MoveAssignMayThrow&&) noexcept(false) { return *this; } +}; + +// Test noexcept +static_assert(std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_assignable_v +static_assert(!std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_constructible_v +static_assert(!std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_assignable_v +static_assert(!std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_constructible_v +static_assert(!std::is_nothrow_move_assignable_v>); + +constexpr bool test() { + // If this->has_value() && rhs.has_value() is true, equivalent to val = std::move(*rhs). + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + std::expected e2(std::in_place, newState, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + assert(oldState.moveAssignCalled); + } + + // - Otherwise, if this->has_value() is true, equivalent to: + // reinit-expected(unex, val, rhs.error()) + // E move is not noexcept + // In this case, it should call the branch + // + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + // + { + TracedNoexcept::state oldState{}; + Traced::state newState{}; + std::expected e1(std::in_place, oldState, 5); + std::expected e2(std::unexpect, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(!oldState.moveAssignCalled); + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(!newState.copyCtorCalled); + assert(newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if this->has_value() is true, equivalent to: + // reinit-expected(unex, val, rhs.error()) + // E move is noexcept + // In this case, it should call the branch + // + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + // + { + Traced::state oldState{}; + TracedNoexcept::state newState{}; + std::expected e1(std::in_place, oldState, 5); + std::expected e2(std::unexpect, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(!newState.copyCtorCalled); + assert(newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if rhs.has_value() is true, equivalent to: + // reinit-expected(val, unex, *rhs) + // T move is not noexcept + // In this case, it should call the branch + // + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + // + { + TracedNoexcept::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + std::expected e2(std::in_place, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(!newState.copyCtorCalled); + assert(newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // - Otherwise, if rhs.has_value() is true, equivalent to: + // reinit-expected(val, unex, *rhs) + // T move is noexcept + // In this case, it should call the branch + // + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + // + { + Traced::state oldState{}; + TracedNoexcept::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + std::expected e2(std::in_place, newState, 10); + + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(e1.has_value()); + assert(e1.value().data_ == 10); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!oldState.copyCtorCalled); + assert(!newState.copyCtorCalled); + assert(newState.moveCtorCalled); + assert(!newState.dtorCalled); + } + + // Otherwise, equivalent to unex = rhs.error(). + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + std::expected e2(std::unexpect, newState, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(oldState.moveAssignCalled); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnMove { + ThrowOnMove() = default; + ThrowOnMove(ThrowOnMove&&) { throw Except{}; }; + ThrowOnMove& operator=(ThrowOnMove&&) = default; + }; + + // assign value throw on move + { + std::expected e1(std::unexpect, 5); + std::expected e2(std::in_place); + try { + e1 = std::move(e2); + assert(false); + } catch (Except) { + assert(!e1.has_value()); + assert(e1.error() == 5); + } + } + + // assign error throw on move + { + std::expected e1(5); + std::expected e2(std::unexpect); + try { + e1 = std::move(e2); + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.copy.pass.cpp @@ -0,0 +1,205 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr expected& operator=(const unexpected& e); +// +// Let GF be const G& +// Constraints: +// - is_constructible_v is true; and +// - is_assignable_v is true; and +// - is_nothrow_constructible_v || is_nothrow_move_constructible_v || +// is_nothrow_move_constructible_v is true. +// +// Effects: +// - If has_value() is true, equivalent to: +// reinit-expected(unex, val, std::forward(e.error())); +// has_val = false; +// - Otherwise, equivalent to: unex = std::forward(e.error()); +// Returns: *this. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotCopyConstructible { + NotCopyConstructible(const NotCopyConstructible&) = delete; + NotCopyConstructible& operator=(const NotCopyConstructible&) = default; +}; + +struct NotCopyAssignable { + NotCopyAssignable(const NotCopyAssignable&) = default; + NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow const&) = default; + MoveMayThrow& operator=(const MoveMayThrow&) = default; + MoveMayThrow(MoveMayThrow&&) noexcept(false) {} + MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; } +}; + +// Test constraints +static_assert(std::is_assignable_v&, const std::unexpected&>); + +// !is_constructible_v +static_assert( + !std::is_assignable_v&, const std::unexpected&>); + +// !is_assignable_v +static_assert(!std::is_assignable_v&, const std::unexpected&>); + +template +struct MaybeNoexcept { + explicit MaybeNoexcept(int) noexcept(convertNoexcept); + MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept); + MaybeNoexcept& operator=(MaybeNoexcept&&) = default; + MaybeNoexcept& operator=(int); +}; + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + const std::unexpected&>); + +// is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + const std::unexpected&>); + +// !is_nothrow_constructible_v && is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + const std::unexpected&>); + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(!std::is_assignable_v, MaybeNoexcept>&, + const std::unexpected&>); + +constexpr bool test() { + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // is_nothrow_constructible_v + // + // In this case, it should call the branch + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + const std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = un); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().copiedFromInt); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // T tmp(std::forward(args)...); + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::move(tmp)); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + const std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = un); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!e.error().copiedFromInt); + assert(e.error().movedFromTmp); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && !is_nothrow_move_constructible_v + // is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + const std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = un); + assert(&x == &e); + + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().copiedFromInt); + } + + // Otherwise, equivalent to: unex = std::forward(e.error()); + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + const std::unexpected e(std::in_place, newState, 10); + std::same_as&> decltype(auto) x = (e1 = e); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(oldState.copyAssignCalled); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnConvert { + ThrowOnConvert() = default; + ThrowOnConvert(const int&) { throw Except{}; } + ThrowOnConvert(int&&) {} + ThrowOnConvert(const ThrowOnConvert&) noexcept(false) {} + ThrowOnConvert& operator=(const ThrowOnConvert&) = default; + ThrowOnConvert(ThrowOnConvert&&) noexcept(false) {} + ThrowOnConvert& operator=(ThrowOnConvert&&) = default; + }; + + std::expected e1(std::in_place, 5); + const std::unexpected un(10); + try { + e1 = un; + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.move.pass.cpp @@ -0,0 +1,205 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr expected& operator=(unexpected&& e); +// +// Let GF be G +// Constraints: +// - is_constructible_v is true; and +// - is_assignable_v is true; and +// - is_nothrow_constructible_v || is_nothrow_move_constructible_v || +// is_nothrow_move_constructible_v is true. +// +// Effects: +// - If has_value() is true, equivalent to: +// reinit-expected(unex, val, std::forward(e.error())); +// has_val = false; +// - Otherwise, equivalent to: unex = std::forward(e.error()); +// Returns: *this. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotMoveConstructible { + NotMoveConstructible(NotMoveConstructible&&) = delete; + NotMoveConstructible& operator=(NotMoveConstructible&&) = default; +}; + +struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&) = default; + NotMoveAssignable& operator=(NotMoveAssignable&&) = delete; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow const&) = default; + MoveMayThrow& operator=(const MoveMayThrow&) = default; + MoveMayThrow(MoveMayThrow&&) noexcept(false) {} + MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; } +}; + +// Test constraints +static_assert(std::is_assignable_v&, std::unexpected&&>); + +// !is_constructible_v +static_assert( + !std::is_assignable_v&, std::unexpected&&>); + +// !is_assignable_v +static_assert(!std::is_assignable_v&, std::unexpected&&>); + +template +struct MaybeNoexcept { + explicit MaybeNoexcept(int) noexcept(convertNoexcept); + MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept); + MaybeNoexcept& operator=(MaybeNoexcept&&) = default; + MaybeNoexcept& operator=(int); +}; + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// !is_nothrow_constructible_v && is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(!std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +constexpr bool test() { + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // is_nothrow_constructible_v + // + // In this case, it should call the branch + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().movedFromInt); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // T tmp(std::forward(args)...); + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::move(tmp)); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!e.error().movedFromInt); + assert(e.error().movedFromTmp); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && !is_nothrow_move_constructible_v + // is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().movedFromInt); + } + + // Otherwise, equivalent to: unex = std::forward(e.error()); + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + std::unexpected e(std::in_place, newState, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(e)); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(oldState.moveAssignCalled); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnConvert { + ThrowOnConvert() = default; + ThrowOnConvert(const int&) {} + ThrowOnConvert(int&&) { throw Except{}; } + ThrowOnConvert(const ThrowOnConvert&) noexcept(false) {} + ThrowOnConvert& operator=(const ThrowOnConvert&) = default; + ThrowOnConvert(ThrowOnConvert&&) noexcept(false) {} + ThrowOnConvert& operator=(ThrowOnConvert&&) = default; + }; + + std::expected e1(std::in_place, 5); + std::unexpected un(10); + try { + e1 = std::move(un); + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.intializer_list.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.intializer_list.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.intializer_list.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr T& emplace(initializer_list il, Args&&... args) noexcept; +// Constraints: is_nothrow_constructible_v&, Args...> is true. +// +// Effects: Equivalent to: +// if (has_value()) { +// destroy_at(addressof(val)); +// } else { +// destroy_at(addressof(unex)); +// has_val = true; +// } +// return *construct_at(addressof(val), il, std::forward(args)...); + +#include +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +template +concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward(args)...); }; + +static_assert(CanEmplace, int>); + +template +struct CtorFromInitalizerList { + CtorFromInitalizerList(std::initializer_list&) noexcept(Noexcept); + CtorFromInitalizerList(std::initializer_list&, int) noexcept(Noexcept); +}; + +static_assert(CanEmplace, int>, std::initializer_list&>); +static_assert(!CanEmplace, int>, std::initializer_list&>); +static_assert(CanEmplace, int>, std::initializer_list&, int>); +static_assert(!CanEmplace, int>, std::initializer_list&, int>); + +struct Data { + std::initializer_list il; + int i; + + constexpr Data(std::initializer_list& l, int ii) noexcept : il(l), i(ii) {} +}; + +constexpr bool test() { + // has_value + { + auto list1 = {1, 2, 3}; + auto list2 = {4, 5, 6}; + std::expected e(std::in_place, list1, 5); + std::same_as decltype(auto) x = e.emplace(list2, 10); + assert(&x == &(*e)); + + assert(e.has_value()); + assert(std::ranges::equal(e.value().il, list2)); + assert(e.value().i == 10); + } + + // !has_value + { + auto list = {4, 5, 6}; + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.emplace(list, 10); + assert(&x == &(*e)); + + assert(e.has_value()); + assert(std::ranges::equal(e.value().il, list)); + assert(e.value().i == 10); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr T& emplace(Args&&... args) noexcept; +// Constraints: is_nothrow_constructible_v is true. +// +// Effects: Equivalent to: +// if (has_value()) { +// destroy_at(addressof(val)); +// } else { +// destroy_at(addressof(unex)); +// has_val = true; +// } +// return *construct_at(addressof(val), std::forward(args)...); + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +template +concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward(args)...); }; + +static_assert(CanEmplace, int>); + +template +struct CtorFromInt { + CtorFromInt(int) noexcept(Noexcept); + CtorFromInt(int, int) noexcept(Noexcept); +}; + +static_assert(CanEmplace, int>, int>); +static_assert(CanEmplace, int>, int, int>); +static_assert(!CanEmplace, int>, int>); +static_assert(!CanEmplace, int>, int, int>); + +constexpr bool test() { + // has_value + { + BothNoexcept::state oldState{}; + BothNoexcept::state newState{}; + std::expected e(std::in_place, oldState, 5); + std::same_as decltype(auto) x = e.emplace(newState, 10); + assert(&x == &(*e)); + + assert(oldState.dtorCalled); + assert(e.has_value()); + assert(e.value().data_ == 10); + } + + // !has_value + { + BothMayThrow::state oldState{}; + std::expected e(std::unexpect, oldState, 5); + std::same_as decltype(auto) x = e.emplace(10); + assert(&x == &(*e)); + + assert(oldState.dtorCalled); + assert(e.has_value()); + assert(e.value() == 10); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.copy.pass.cpp @@ -0,0 +1,203 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(see below) expected(const expected&); +// +// Let: +// - UF be const U& +// - GF be const G& +// +// Constraints: +// - is_constructible_v is true; and +// - is_constructible_v is true; and +// - is_constructible_v&> is false; and +// - is_constructible_v> is false; and +// - is_constructible_v&> is false; and +// - is_constructible_v> is false; and +// - is_convertible_v&, T> is false; and +// - is_convertible_v&&, T> is false; and +// - is_convertible_v&, T> is false; and +// - is_convertible_v&&, T> is false; and +// - is_constructible_v, expected&> is false; and +// - is_constructible_v, expected> is false; and +// - is_constructible_v, const expected&> is false; and +// - is_constructible_v, const expected> is false. +// +// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward(*rhs). Otherwise, direct-non-list-initializes unex with std::forward(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of val or unex. +// +// Remarks: The expression inside explicit is equivalent to !is_convertible_v || !is_convertible_v. + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Constraints: +template +concept canCstrFromExpected = std::is_constructible_v, const std::expected&>; + +struct CtorFromInt { + CtorFromInt(int); +}; + +static_assert(canCstrFromExpected); + +struct NoCtorFromInt {}; + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +template +struct CtorFrom { + explicit CtorFrom(int) + requires(!std::same_as); + explicit CtorFrom(T); + explicit CtorFrom(auto&&) = delete; +}; + +// is_constructible_v&> +static_assert(!canCstrFromExpected&>, int, int, int>); + +// is_constructible_v> +static_assert(!canCstrFromExpected&&>, int, int, int>); + +// is_constructible_v&> +// note that this is true because it is covered by the other overload +// template constexpr explicit(see below) expected(U&& v); +// The fact that it is not ambiguous proves that the overload under testing is removed +static_assert(canCstrFromExpected const&>, int, int, int>); + +// is_constructible_v> +static_assert(!canCstrFromExpected const&&>, int, int, int>); + +template +struct ConvertFrom { + ConvertFrom(int) + requires(!std::same_as); + ConvertFrom(T); + ConvertFrom(auto&&) = delete; +}; + +// is_convertible_v&, T> +static_assert(!canCstrFromExpected&>, int, int, int>); + +// is_convertible_v&&, T> +static_assert(!canCstrFromExpected&&>, int, int, int>); + +// is_convertible_v&, T> +// note that this is true because it is covered by the other overload +// template constexpr explicit(see below) expected(U&& v); +// The fact that it is not ambiguous proves that the overload under testing is removed +static_assert(canCstrFromExpected const&>, int, int, int>); + +// is_convertible_v&&, T> +static_assert(!canCstrFromExpected const&&>, int, int, int>); + +// Note for below 4 tests, because their E is constructible from cvref of std::expected, +// unexpected will be constructible from cvref of std::expected +// is_constructible_v, expected&> +static_assert(!canCstrFromExpected&>, int, int>); + +// is_constructible_v, expected> +static_assert(!canCstrFromExpected&&>, int, int>); + +// is_constructible_v, const expected&> is false +static_assert(!canCstrFromExpected const&>, int, int>); + +// is_constructible_v, const expected> +static_assert(!canCstrFromExpected const&&>, int, int>); + +// test explicit +static_assert(std::is_convertible_v&, std::expected>); + +// !is_convertible_v +static_assert(std::is_constructible_v, int>, const std::expected&>); +static_assert(!std::is_convertible_v&, std::expected, int>>); + +// !is_convertible_v. +static_assert(std::is_constructible_v>, const std::expected&>); +static_assert(!std::is_convertible_v&, std::expected>>); + +struct Data { + int i; + constexpr Data(int ii) : i(ii) {} +}; + +constexpr bool test() { + // convert the value + { + const std::expected e1(5); + std::expected e2 = e1; + assert(e2.has_value()); + assert(e2.value().i == 5); + assert(e1.has_value()); + assert(e1.value() == 5); + } + + // convert the error + { + const std::expected e1(std::unexpect, 5); + std::expected e2 = e1; + assert(!e2.has_value()); + assert(e2.error().i == 5); + assert(!e1.has_value()); + assert(e1.error() == 5); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowingInt { + ThrowingInt(int) { throw Except{}; } + }; + + // throw on converting value + { + const std::expected e1; + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + + // throw on converting error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.move.pass.cpp @@ -0,0 +1,202 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(see below) expected(expected&&); +// +// Let: +// - UF be const U +// - GF be const G +// +// Constraints: +// - is_constructible_v is true; and +// - is_constructible_v is true; and +// - is_constructible_v&> is false; and +// - is_constructible_v> is false; and +// - is_constructible_v&> is false; and +// - is_constructible_v> is false; and +// - is_convertible_v&, T> is false; and +// - is_convertible_v&&, T> is false; and +// - is_convertible_v&, T> is false; and +// - is_convertible_v&&, T> is false; and +// - is_constructible_v, expected&> is false; and +// - is_constructible_v, expected> is false; and +// - is_constructible_v, const expected&> is false; and +// - is_constructible_v, const expected> is false. +// +// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward(*rhs). Otherwise, direct-non-list-initializes unex with std::forward(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of val or unex. +// +// Remarks: The expression inside explicit is equivalent to !is_convertible_v || !is_convertible_v. + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +template +concept canCstrFromExpected = std::is_constructible_v, std::expected&&>; + +struct CtorFromInt { + CtorFromInt(int); +}; + +static_assert(canCstrFromExpected); + +struct NoCtorFromInt {}; + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +template +struct CtorFrom { + explicit CtorFrom(int) + requires(!std::same_as); + explicit CtorFrom(T); + explicit CtorFrom(auto&&) = delete; +}; + +// is_constructible_v&> +static_assert(!canCstrFromExpected&>, int, int, int>); + +// is_constructible_v> +// note that this is true because it is covered by the other overload +// template constexpr explicit(see below) expected(U&& v); +// The fact that it is not ambiguous proves that the overload under testing is removed +static_assert(canCstrFromExpected&&>, int, int, int>); + +// is_constructible_v&> +static_assert(!canCstrFromExpected const&>, int, int, int>); + +// is_constructible_v> +static_assert(!canCstrFromExpected const&&>, int, int, int>); + +template +struct ConvertFrom { + ConvertFrom(int) + requires(!std::same_as); + ConvertFrom(T); + ConvertFrom(auto&&) = delete; +}; + +// is_convertible_v&, T> +static_assert(!canCstrFromExpected&>, int, int, int>); + +// is_convertible_v&&, T> +// note that this is true because it is covered by the other overload +// template constexpr explicit(see below) expected(U&& v); +// The fact that it is not ambiguous proves that the overload under testing is removed +static_assert(canCstrFromExpected&&>, int, int, int>); + +// is_convertible_v&, T> +static_assert(!canCstrFromExpected const&>, int, int, int>); + +// is_convertible_v&&, T> +static_assert(!canCstrFromExpected const&&>, int, int, int>); + +// is_constructible_v, expected&> +static_assert(!canCstrFromExpected&>, int, int>); + +// is_constructible_v, expected> +static_assert(!canCstrFromExpected&&>, int, int>); + +// is_constructible_v, const expected&> is false +static_assert(!canCstrFromExpected const&>, int, int>); + +// is_constructible_v, const expected> +static_assert(!canCstrFromExpected const&&>, int, int>); + +// test explicit +static_assert(std::is_convertible_v&&, std::expected>); + +// !is_convertible_v +static_assert(std::is_constructible_v, int>, std::expected&&>); +static_assert(!std::is_convertible_v&&, std::expected, int>>); + +// !is_convertible_v. +static_assert(std::is_constructible_v>, std::expected&&>); +static_assert(!std::is_convertible_v&&, std::expected>>); + +struct Data { + MoveOnly data; + constexpr Data(MoveOnly&& m) : data(std::move(m)) {} +}; + +constexpr bool test() { + // convert the value + { + std::expected e1(5); + std::expected e2 = std::move(e1); + assert(e2.has_value()); + assert(e2.value().data.get() == 5); + assert(e1.has_value()); + assert(e1.value().get() == 0); + } + + // convert the error + { + std::expected e1(std::unexpect, 5); + std::expected e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error().data.get() == 5); + assert(!e1.has_value()); + assert(e1.error().get() == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowingInt { + ThrowingInt(int) { throw Except{}; } + }; + + // throw on converting value + { + const std::expected e1; + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + + // throw on converting error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected(const expected& rhs); +// +// Effects: If rhs.has_value() is true, direct-non-list-initializes val with *rhs. +// Otherwise, direct-non-list-initializes unex with rhs.error(). +// +// Postconditions: rhs.has_value() == this->has_value(). +// +// Throws: Any exception thrown by the initialization of val or unex. +// +// Remarks: This constructor is defined as deleted unless +// - is_copy_constructible_v is true and +// - is_copy_constructible_v is true. +// +// This constructor is trivial if +// - is_trivially_copy_constructible_v is true and +// - is_trivially_copy_constructible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +struct NonCopyable { + NonCopyable(const NonCopyable&) = delete; +}; + +struct CopyableNonTrivial { + int i; + constexpr CopyableNonTrivial(int ii) : i(ii) {} + constexpr CopyableNonTrivial(const CopyableNonTrivial& o) { i = o.i; } + friend constexpr bool operator==(const CopyableNonTrivial&, const CopyableNonTrivial&) = default; +}; + +// Test: This constructor is defined as deleted unless +// - is_copy_constructible_v is true and +// - is_copy_constructible_v is true. +static_assert(std::is_copy_constructible_v>); +static_assert(std::is_copy_constructible_v>); +static_assert(std::is_copy_constructible_v>); +static_assert(std::is_copy_constructible_v>); +static_assert(!std::is_copy_constructible_v>); +static_assert(!std::is_copy_constructible_v>); +static_assert(!std::is_copy_constructible_v>); + +// Test: This constructor is trivial if +// - is_trivially_copy_constructible_v is true and +// - is_trivially_copy_constructible_v is true. +static_assert(std::is_trivially_copy_constructible_v>); +static_assert(!std::is_trivially_copy_constructible_v>); +static_assert(!std::is_trivially_copy_constructible_v>); +static_assert(!std::is_trivially_copy_constructible_v>); + +constexpr bool test() { + // copy the value non-trivial + { + const std::expected e1(5); + auto e2 = e1; + assert(e2.has_value()); + assert(e2.value().i == 5); + } + + // copy the error non-trivial + { + const std::expected e1(std::unexpect, 5); + auto e2 = e1; + assert(!e2.has_value()); + assert(e2.error().i == 5); + } + + // copy the value trivial + { + const std::expected e1(5); + auto e2 = e1; + assert(e2.has_value()); + assert(e2.value() == 5); + } + + // copy the error trivial + { + const std::expected e1(std::unexpect, 5); + auto e2 = e1; + assert(!e2.has_value()); + assert(e2.error() == 5); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() = default; + Throwing(const Throwing&) { throw Except{}; } + }; + + // throw on copying value + { + const std::expected e1; + try { + [[maybe_unused]] auto e2 = e1; + assert(false); + } catch (Except) { + } + } + + // throw on copying error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] auto e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.default.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.default.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// +// constexpr expected(); + +// Constraints: is_default_constructible_v is true. +// +// Effects: Value-initializes val. +// Postconditions: has_value() is true. +// +// Throws: Any exception thrown by the initialization of val. + +#include +#include +#include + +#include "test_macros.h" + +struct NoDedefaultCtor { + NoDedefaultCtor() = delete; +}; + +// Test constraints +static_assert(std::is_default_constructible_v>); +static_assert(!std::is_default_constructible_v>); + +struct MyInt { + int i; + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +template +constexpr void testDefaultCtor() { + std::expected e; + assert(e.has_value()); + assert(e.value() == T()); +} + +template +constexpr void testTypes() { + testDefaultCtor(); + testDefaultCtor(); +} + +constexpr bool test() { + testTypes(); + testTypes(); + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() { throw Except{}; }; + }; + + try { + std::expected u; + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(in_place_t, Args&&... args); +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes val with std::forward(args).... +// +// Postconditions: has_value() is true. +// +// Throws: Any exception thrown by the initialization of val. + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert(std::is_constructible_v, std::in_place_t>); +static_assert(std::is_constructible_v, std::in_place_t, int>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, std::in_place_t, int>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert(!ImplicitlyConstructible, std::in_place_t>); +static_assert(!ImplicitlyConstructible, std::in_place_t, int>); + +struct CopyOnly { + int i; + constexpr CopyOnly(int ii) : i(ii) {} + CopyOnly(const CopyOnly&) = default; + CopyOnly(CopyOnly&&) = delete; + friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; } +}; + +template +constexpr void testInt() { + std::expected e(std::in_place, 5); + assert(e.has_value()); + assert(e.value() == 5); +} + +template +constexpr void testLValue() { + T t(5); + std::expected e(std::in_place, t); + assert(e.has_value()); + assert(e.value() == 5); +} + +template +constexpr void testRValue() { + std::expected e(std::in_place, T(5)); + assert(e.has_value()); + assert(e.value() == 5); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testLValue(); + testLValue(); + testRValue(); + testRValue(); + + // no arg + { + std::expected e(std::in_place); + assert(e.has_value()); + assert(e.value() == 0); + } + + // one arg + { + std::expected e(std::in_place, 5); + assert(e.has_value()); + assert(e.value() == 5); + } + + // multi args + { + std::expected, int> e(std::in_place, 1, 2, MoveOnly(3)); + assert(e.has_value()); + assert((e.value() == std::tuple(1, 2, MoveOnly(3)))); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; }; + }; + + try { + std::expected u(std::in_place, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace_init_list.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace_init_list.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace_init_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(in_place_t, initializer_list il, Args&&... args); +// +// Constraints: is_constructible_v&, Args...> is true. +// +// Effects: Direct-non-list-initializes val with il, std::forward(args).... +// +// Postconditions: has_value() is true. +// +// Throws: Any exception thrown by the initialization of val. + +#include +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert( + std::is_constructible_v, int>, std::in_place_t, std::initializer_list>); + +// !is_constructible_v&, Args...> +static_assert(!std::is_constructible_v, std::in_place_t, std::initializer_list>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert( + !ImplicitlyConstructible, int>, std::in_place_t, std::initializer_list>); + +template +struct Data { + std::vector vec_; + std::tuple tuple_; + + template + requires std::is_constructible_v, Us&&...> + constexpr Data(std::initializer_list il, Us&&... us) : vec_(il), tuple_(std::forward(us)...) {} +}; + +constexpr bool test() { + // no arg + { + std::expected, int> e(std::in_place, {1, 2, 3}); + assert(e.has_value()); + auto expectedList = {1, 2, 3}; + assert(std::ranges::equal(e.value().vec_, expectedList)); + } + + // one arg + { + std::expected, int> e(std::in_place, {4, 5, 6}, MoveOnly(5)); + assert(e.has_value()); + auto expectedList = {4, 5, 6}; + assert((std::ranges::equal(e.value().vec_, expectedList))); + assert(std::get<0>(e.value().tuple_) == 5); + } + + // multi args + { + int i = 5; + int j = 6; + MoveOnly m(7); + std::expected, int> e(std::in_place, {1, 2}, i, std::move(j), std::move(m)); + assert(e.has_value()); + auto expectedList = {1, 2}; + assert((std::ranges::equal(e.value().vec_, expectedList))); + assert(&std::get<0>(e.value().tuple_) == &i); + assert(&std::get<1>(e.value().tuple_) == &j); + assert(std::get<2>(e.value().tuple_) == 7); + assert(m.get() == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(std::initializer_list, int) { throw Except{}; }; + }; + + try { + std::expected u(std::in_place, {1, 2}, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.move.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected(expected&& rhs) noexcept(see below); +// +// Constraints: +// - is_move_constructible_v is true and +// - is_move_constructible_v is true. +// +// Effects: If rhs.has_value() is true, direct-non-list-initializes val with std::move(*rhs). +// Otherwise, direct-non-list-initializes unex with std::move(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of val or unex. +// +// Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v && is_nothrow_move_constructible_v. +// +// This constructor is trivial if +// - is_trivially_move_constructible_v is true and +// - is_trivially_move_constructible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +struct NonMovable { + NonMovable(NonMovable&&) = delete; +}; + +struct MovableNonTrivial { + int i; + constexpr MovableNonTrivial(int ii) : i(ii) {} + constexpr MovableNonTrivial(MovableNonTrivial&& o) : i(o.i) { o.i = 0; } + friend constexpr bool operator==(const MovableNonTrivial&, const MovableNonTrivial&) = default; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) {} +}; + +// Test Constraints: +// - is_move_constructible_v is true and +// - is_move_constructible_v is true. +static_assert(std::is_move_constructible_v>); +static_assert(std::is_move_constructible_v>); +static_assert(std::is_move_constructible_v>); +static_assert(std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); + +// Test: This constructor is trivial if +// - is_trivially_move_constructible_v is true and +// - is_trivially_move_constructible_v is true. +static_assert(std::is_trivially_move_constructible_v>); +static_assert(!std::is_trivially_move_constructible_v>); +static_assert(!std::is_trivially_move_constructible_v>); +static_assert(!std::is_trivially_move_constructible_v>); + +// Test: The exception specification is equivalent to +// is_nothrow_move_constructible_v && is_nothrow_move_constructible_v. +static_assert(std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); + +constexpr bool test() { + // move the value non-trivial + { + std::expected e1(5); + auto e2 = std::move(e1); + assert(e2.has_value()); + assert(e2.value().i == 5); + assert(e1.has_value()); + assert(e1.value().i == 0); + } + + // move the error non-trivial + { + std::expected e1(std::unexpect, 5); + auto e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error().i == 5); + assert(!e1.has_value()); + assert(e1.error().i == 0); + } + + // move the value trivial + { + std::expected e1(5); + auto e2 = std::move(e1); + assert(e2.has_value()); + assert(e2.value() == 5); + assert(e1.has_value()); + } + + // move the error trivial + { + std::expected e1(std::unexpect, 5); + auto e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error() == 5); + assert(!e1.has_value()); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() = default; + Throwing(Throwing&&) { throw Except{}; } + }; + + // throw on moving value + { + std::expected e1; + try { + [[maybe_unused]] auto e2 = std::move(e1); + assert(false); + } catch (Except) { + } + } + + // throw on moving error + { + std::expected e1(std::unexpect); + try { + [[maybe_unused]] auto e2 = std::move(e1); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(U&& v); +// +// Constraints: +// - is_same_v, in_place_t> is false; and +// - is_same_v> is false; and +// - remove_cvref_t is not a specialization of unexpected; and +// - is_constructible_v is true. +// +// Effects: Direct-non-list-initializes val with std::forward(v). +// +// Postconditions: has_value() is true. +// +// Throws: Any exception thrown by the initialization of val. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert(std::is_constructible_v, int>); + +// is_same_v, in_place_t> +struct FromJustInplace { + FromJustInplace(std::in_place_t); +}; +static_assert(!std::is_constructible_v, std::in_place_t>); +static_assert(!std::is_constructible_v, std::in_place_t const&>); + +// is_same_v> +// Note that result is true because it is covered by the constructors that take expected +static_assert(std::is_constructible_v, std::expected&>); + +// remove_cvref_t is a specialization of unexpected +// Note that result is true because it is covered by the constructors that take unexpected +static_assert(std::is_constructible_v, std::unexpected&>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, foo>); + +// test explicit(!is_convertible_v) +struct NotConvertible { + explicit NotConvertible(int); +}; +static_assert(std::is_convertible_v>); +static_assert(!std::is_convertible_v>); + +struct CopyOnly { + int i; + constexpr CopyOnly(int ii) : i(ii) {} + CopyOnly(const CopyOnly&) = default; + CopyOnly(CopyOnly&&) = delete; + friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; } +}; + +template +constexpr void testInt() { + std::expected e(5); + assert(e.has_value()); + assert(e.value() == 5); +} + +template +constexpr void testLValue() { + T t(5); + std::expected e(t); + assert(e.has_value()); + assert(e.value() == 5); +} + +template +constexpr void testRValue() { + std::expected e(T(5)); + assert(e.has_value()); + assert(e.value() == 5); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testLValue(); + testLValue(); + testRValue(); + testRValue(); + + // this is a confusing example, but the behaviour + // is exactly what is specified in the spec + { + struct BaseError {}; + struct DerivedError : BaseError {}; + + std::expected e1(false); + std::expected e2(e1); + assert(e2.has_value()); + assert(e2.value()); // yes, e2 holds "true" + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; }; + }; + + try { + std::expected u(5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(unexpect_t, Args&&... args); +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(args).... +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert(std::is_constructible_v, std::unexpect_t>); +static_assert(std::is_constructible_v, std::unexpect_t, int>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, std::unexpect_t, int>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert(!ImplicitlyConstructible, std::unexpect_t>); +static_assert(!ImplicitlyConstructible, std::unexpect_t, int>); + +struct CopyOnly { + int i; + constexpr CopyOnly(int ii) : i(ii) {} + CopyOnly(const CopyOnly&) = default; + CopyOnly(CopyOnly&&) = delete; + friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; } +}; + +template +constexpr void testInt() { + std::expected e(std::unexpect, 5); + assert(!e.has_value()); + assert(e.error() == 5); +} + +template +constexpr void testLValue() { + T t(5); + std::expected e(std::unexpect, t); + assert(!e.has_value()); + assert(e.error() == 5); +} + +template +constexpr void testRValue() { + std::expected e(std::unexpect, T(5)); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testLValue(); + testLValue(); + testRValue(); + testRValue(); + + // no arg + { + std::expected e(std::unexpect); + assert(!e.has_value()); + assert(e.error() == 0); + } + + // one arg + { + std::expected e(std::unexpect, 5); + assert(!e.has_value()); + assert(e.error() == 5); + } + + // multi args + { + std::expected> e(std::unexpect, 1, 2, MoveOnly(3)); + assert(!e.has_value()); + assert((e.error() == std::tuple(1, 2, MoveOnly(3)))); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; }; + }; + + try { + std::expected u(std::unexpect, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect_init_list.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect_init_list.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect_init_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); +// +// Constraints: is_constructible_v&, Args...> is true. +// +// Effects: Direct-non-list-initializes unex with il, std::forward(args).... +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert( + std::is_constructible_v>, std::unexpect_t, std::initializer_list>); + +// !is_constructible_v&, Args...> +static_assert(!std::is_constructible_v, std::unexpect_t, std::initializer_list>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert( + !ImplicitlyConstructible>, std::unexpect_t, std::initializer_list>); + +template +struct Data { + std::vector vec_; + std::tuple tuple_; + + template + requires std::is_constructible_v, Us&&...> + constexpr Data(std::initializer_list il, Us&&... us) : vec_(il), tuple_(std::forward(us)...) {} +}; + +constexpr bool test() { + // no arg + { + std::expected> e(std::unexpect, {1, 2, 3}); + assert(!e.has_value()); + auto expectedList = {1, 2, 3}; + assert(std::ranges::equal(e.error().vec_, expectedList)); + } + + // one arg + { + std::expected> e(std::unexpect, {4, 5, 6}, MoveOnly(5)); + assert(!e.has_value()); + auto expectedList = {4, 5, 6}; + assert((std::ranges::equal(e.error().vec_, expectedList))); + assert(std::get<0>(e.error().tuple_) == 5); + } + + // multi args + { + int i = 5; + int j = 6; + MoveOnly m(7); + std::expected> e(std::unexpect, {1, 2}, i, std::move(j), std::move(m)); + assert(!e.has_value()); + auto expectedList = {1, 2}; + assert((std::ranges::equal(e.error().vec_, expectedList))); + assert(&std::get<0>(e.error().tuple_) == &i); + assert(&std::get<1>(e.error().tuple_) == &j); + assert(std::get<2>(e.error().tuple_) == 7); + assert(m.get() == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(std::initializer_list, int) { throw Except{}; }; + }; + + try { + std::expected u(std::unexpect, {1, 2}, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.copy.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(const unexpected& e); +// +// Let GF be const G& +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(e.error()). +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints +static_assert(std::is_constructible_v, const std::unexpected&>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, const std::unexpected&>); +static_assert(!std::is_constructible_v, const std::unexpected&>); + +// explicit(!is_convertible_v) +struct NotConvertible { + explicit NotConvertible(int); +}; +static_assert(std::is_convertible_v&, std::expected>); +static_assert(!std::is_convertible_v&, std::expected>); + +struct MyInt { + int i; + constexpr MyInt(int ii) : i(ii) {} + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +template +constexpr void testUnexpected() { + const std::unexpected u(5); + std::expected e(u); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr bool test() { + testUnexpected(); + testUnexpected(); + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; } + }; + + { + const std::unexpected u(5); + try { + [[maybe_unused]] std::expected e(u); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.move.pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(unexpected&& e); +// +// Let GF be G +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(e.error()). +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints +static_assert(std::is_constructible_v, std::unexpected>); +static_assert(std::is_constructible_v, std::unexpected>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, std::unexpected>); + +// explicit(!is_convertible_v) +struct NotConvertible { + explicit NotConvertible(int); +}; +static_assert(std::is_convertible_v&&, std::expected>); +static_assert(!std::is_convertible_v&&, std::expected>); + +struct MyInt { + int i; + constexpr MyInt(int ii) : i(ii) {} + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +template +constexpr void testInt() { + std::unexpected u(5); + std::expected e(std::move(u)); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr void testMoveOnly() { + std::unexpected u(MoveOnly(5)); + std::expected e(std::move(u)); + assert(!e.has_value()); + assert(e.error() == 5); + assert(u.error() == 0); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testMoveOnly(); + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; } + }; + + { + std::unexpected u(5); + try { + [[maybe_unused]] std::expected e(std::move(u)); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/dtor.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/dtor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/dtor.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr ~expected(); +// +// Effects: If has_value() is true, destroys val, otherwise destroys unex. +// +// Remarks: If is_trivially_destructible_v is true, and is_trivially_destructible_v is true, +// then this destructor is a trivial destructor. + +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Remarks: If is_trivially_destructible_v is true, and is_trivially_destructible_v is true, +// then this destructor is a trivial destructor. +struct NonTrivial { + ~NonTrivial() {} +}; + +static_assert(std::is_trivially_destructible_v>); +static_assert(!std::is_trivially_destructible_v>); +static_assert(!std::is_trivially_destructible_v>); +static_assert(!std::is_trivially_destructible_v>); + +struct TrackedDestroy { + bool& destroyed; + constexpr TrackedDestroy(bool& b) : destroyed(b) {} + constexpr ~TrackedDestroy() { destroyed = true; } +}; + +constexpr bool test() { + // has value + { + bool valueDestroyed = false; + { [[maybe_unused]] std::expected e(std::in_place, valueDestroyed); } + assert(valueDestroyed); + } + + // has error + { + bool errorDestroyed = false; + { [[maybe_unused]] std::expected e(std::unexpect, errorDestroyed); } + assert(errorDestroyed); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/equality/equality.T2.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.T2.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.T2.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template friend constexpr bool operator==(const expected& x, const T2& v); + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Data { + int i; + constexpr Data(int ii) : i(ii) {} + + friend constexpr bool operator==(const Data& data, int ii) { return data.i == ii; } +}; + +constexpr bool test() { + // x.has_value() + { + const std::expected e1(std::in_place, 5); + int i2 = 10; + int i3 = 5; + assert(e1 != i2); + assert(e1 == i3); + } + + // !x.has_value() + { + const std::expected e1(std::unexpect, 5); + int i2 = 10; + int i3 = 5; + assert(e1 != i2); + assert(e1 != i3); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template requires (!is_void_v) +// friend constexpr bool operator==(const expected& x, const expected& y); + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test constraint +template +concept CanCompare = requires(T1 t1, T2 t2) { t1 == t2; }; + +struct Foo{}; +static_assert(!CanCompare); + +static_assert(CanCompare, std::expected>); +static_assert(CanCompare, std::expected>); + +// Note this is true because other overloads are unconstrained +static_assert(CanCompare, std::expected>); + +constexpr bool test() { + // x.has_value() && y.has_value() + { + const std::expected e1(5); + const std::expected e2(10); + const std::expected e3(5); + assert(e1 != e2); + assert(e1 == e3); + } + + // !x.has_value() && y.has_value() + { + const std::expected e1(std::unexpect, 5); + const std::expected e2(10); + const std::expected e3(5); + assert(e1 != e2); + assert(e1 != e3); + } + + // x.has_value() && !y.has_value() + { + const std::expected e1(5); + const std::expected e2(std::unexpect, 10); + const std::expected e3(std::unexpect, 5); + assert(e1 != e2); + assert(e1 != e3); + } + + // !x.has_value() && !y.has_value() + { + const std::expected e1(std::unexpect, 5); + const std::expected e2(std::unexpect, 10); + const std::expected e3(std::unexpect, 5); + assert(e1 != e2); + assert(e1 == e3); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/equality/equality.unexpected.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.unexpected.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/equality/equality.unexpected.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template friend constexpr bool operator==(const expected& x, const unexpected& e); + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Data { + int i; + constexpr Data(int ii) : i(ii) {} + + friend constexpr bool operator==(const Data& data, int ii) { return data.i == ii; } +}; + +constexpr bool test() { + // x.has_value() + { + const std::expected e1(std::in_place, 5); + std::unexpected un2(10); + std::unexpected un3(5); + assert(e1 != un2); + assert(e1 != un3); + } + + // !x.has_value() + { + const std::expected e1(std::unexpect, 5); + std::unexpected un2(10); + std::unexpected un3(5); + assert(e1 != un2); + assert(e1 == un3); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/arrow.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/arrow.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/arrow.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const T* operator->() const noexcept; +// constexpr T* operator->() noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept ArrowNoexcept = + requires(T t) { + { t.operator->() } noexcept; + }; + +static_assert(!ArrowNoexcept); + +static_assert(ArrowNoexcept>); +static_assert(ArrowNoexcept>); + +constexpr bool test() { + // const + { + const std::expected e(5); + std::same_as decltype(auto) x = e.operator->(); + assert(x == &(e.value())); + assert(*x == 5); + } + + // non-const + { + std::expected e(5); + std::same_as decltype(auto) x = e.operator->(); + assert(x == &(e.value())); + assert(*x == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/bool.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/bool.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/bool.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr explicit operator bool() const noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept OpBoolNoexcept = + requires(T t) { + { static_cast(t) } noexcept; + }; + +struct Foo {}; +static_assert(!OpBoolNoexcept); + +static_assert(OpBoolNoexcept>); +static_assert(OpBoolNoexcept>); + +// Test explicit +static_assert(!std::is_convertible_v, bool>); + +constexpr bool test() { + // has_value + { + const std::expected e(5); + assert(static_cast(e)); + } + + // !has_value + { + const std::expected e(std::unexpect, 5); + assert(!static_cast(e)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/deref.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/deref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/deref.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const T& operator*() const & noexcept; +// constexpr T& operator*() & noexcept; +// constexpr T&& operator*() && noexcept; +// constexpr const T&& operator*() const && noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept DerefNoexcept = + requires(T t) { + { std::forward(t).operator*() } noexcept; + }; + +static_assert(!DerefNoexcept); + +static_assert(DerefNoexcept&>); +static_assert(DerefNoexcept&>); +static_assert(DerefNoexcept&&>); +static_assert(DerefNoexcept&&>); + +constexpr bool test() { + // non-const & + { + std::expected e(5); + std::same_as decltype(auto) x = *e; + assert(&x == &(e.value())); + assert(x == 5); + } + + // const & + { + const std::expected e(5); + std::same_as decltype(auto) x = *e; + assert(&x == &(e.value())); + assert(x == 5); + } + + // non-const && + { + std::expected e(5); + std::same_as decltype(auto) x = *std::move(e); + assert(&x == &(e.value())); + assert(x == 5); + } + + // const && + { + const std::expected e(5); + std::same_as decltype(auto) x = *std::move(e); + assert(&x == &(e.value())); + assert(x == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/error.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/error.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/error.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const E& error() const & noexcept; +// constexpr E& error() & noexcept; +// constexpr E&& error() && noexcept; +// constexpr const E&& error() const && noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept ErrorNoexcept = + requires(T t) { + { std::forward(t).error() } noexcept; + }; + +static_assert(!ErrorNoexcept); + +static_assert(ErrorNoexcept&>); +static_assert(ErrorNoexcept&>); +static_assert(ErrorNoexcept&&>); +static_assert(ErrorNoexcept&&>); + +constexpr bool test() { + // non-const & + { + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.error(); + assert(x == 5); + } + + // const & + { + const std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.error(); + assert(x == 5); + } + + // non-const && + { + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = std::move(e).error(); + assert(x == 5); + } + + // const && + { + const std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = std::move(e).error(); + assert(x == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/has_value.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/has_value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/has_value.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr bool has_value() const noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept HasValueNoexcept = + requires(T t) { + { t.has_value() } noexcept; + }; + +struct Foo {}; +static_assert(!HasValueNoexcept); + +static_assert(HasValueNoexcept>); +static_assert(HasValueNoexcept>); + +constexpr bool test() { + // has_value + { + const std::expected e(5); + assert(e.has_value()); + } + + // !has_value + { + const std::expected e(std::unexpect, 5); + assert(!e.has_value()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const T& value() const &; +// constexpr T& value() &; +// constexpr T&& value() &&; +// constexpr const T&& value() const &&; + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +constexpr bool test() { + // non-const & + { + std::expected e(5); + std::same_as decltype(auto) x = e.value(); + assert(&x == &(*e)); + assert(x == 5); + } + + // const & + { + const std::expected e(5); + std::same_as decltype(auto) x = e.value(); + assert(&x == &(*e)); + assert(x == 5); + } + + // non-const && + { + std::expected e(5); + std::same_as decltype(auto) x = std::move(e).value(); + assert(&x == &(*e)); + assert(x == 5); + } + + // const && + { + const std::expected e(5); + std::same_as decltype(auto) x = std::move(e).value(); + assert(&x == &(*e)); + assert(x == 5); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + + // int + { + const std::expected e(std::unexpect, 5); + try { + e.value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + + // MoveOnly + { + std::expected e(std::unexpect, 5); + try { + std::move(e).value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/observers/value_or.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/observers/value_or.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/observers/value_or.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template constexpr T value_or(U&& v) const &; +// template constexpr T value_or(U&& v) &&; + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +constexpr bool test() { + // const &, has_value() + { + const std::expected e(5); + std::same_as decltype(auto) x = e.value_or(10); + assert(x == 5); + } + + // const &, !has_value() + { + const std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.value_or(10); + assert(x == 10); + } + + // &&, has_value() + { + std::expected e(std::in_place, 5); + std::same_as decltype(auto) x = std::move(e).value_or(10); + assert(x == 5); + } + + // &&, !has_value() + { + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = std::move(e).value_or(10); + assert(x == 10); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + + // int + { + const std::expected e(std::unexpect, 5); + try { + e.value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + + // MoveOnly + { + std::expected e(std::unexpect, 5); + try { + std::move(e).value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/swap/free.swap.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/swap/free.swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/swap/free.swap.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); + +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) noexcept(false); + friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {} +}; + +// Test noexcept +template +concept FreeSwapNoexcept = + requires(std::expected x, std::expected y) { + { swap(x, y) } noexcept; + }; + +static_assert(FreeSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!FreeSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!FreeSwapNoexcept); + +struct SwapMayThrow { + friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {} +}; + +// !is_nothrow_swappable_v +static_assert(!FreeSwapNoexcept); + +// !is_nothrow_swappable_v +static_assert(!FreeSwapNoexcept); + +constexpr bool test() { + // this->has_value() && rhs.has_value() + { + std::expected x(std::in_place, 5); + std::expected y(std::in_place, 10); + swap(x, y); + + assert(x.has_value()); + assert(x->i == 10); + assert(x->adlSwapCalled); + assert(y.has_value()); + assert(y->i == 5); + assert(y->adlSwapCalled); + } + + // !this->has_value() && !rhs.has_value() + { + std::expected x(std::unexpect, 5); + std::expected y(std::unexpect, 10); + swap(x, y); + + assert(!x.has_value()); + assert(x.error().i == 10); + assert(x.error().adlSwapCalled); + assert(!y.has_value()); + assert(y.error().i == 5); + assert(y.error().adlSwapCalled); + } + + // this->has_value() && !rhs.has_value() + // && is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::in_place, 5); + std::expected, TrackedMove> e2(std::unexpect, 10); + + swap(e1, e2); + + assert(!e1.has_value()); + assert(e1.error().i == 10); + assert(e2.has_value()); + assert(e2->i == 5); + + assert(e1.error().numberOfMoves == 2); + assert(!e1.error().swapCalled); + assert(e2->numberOfMoves == 1); + assert(!e2->swapCalled); + } + + // this->has_value() && !rhs.has_value() + // && !is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::in_place, 5); + std::expected, TrackedMove> e2(std::unexpect, 10); + + e1.swap(e2); + + assert(!e1.has_value()); + assert(e1.error().i == 10); + assert(e2.has_value()); + assert(e2->i == 5); + + assert(e1.error().numberOfMoves == 1); + assert(!e1.error().swapCalled); + assert(e2->numberOfMoves == 2); + assert(!e2->swapCalled); + } + + // !this->has_value() && rhs.has_value() + // && is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::unexpect, 10); + std::expected, TrackedMove> e2(std::in_place, 5); + + swap(e1, e2); + + assert(e1.has_value()); + assert(e1->i == 5); + assert(!e2.has_value()); + assert(e2.error().i == 10); + + assert(e1->numberOfMoves == 1); + assert(!e1->swapCalled); + assert(e2.error().numberOfMoves == 2); + assert(!e2.error().swapCalled); + } + + // !this->has_value() && rhs.has_value() + // && !is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::unexpect, 10); + std::expected, TrackedMove> e2(std::in_place, 5); + + swap(e1, e2); + + assert(e1.has_value()); + assert(e1->i == 5); + assert(!e2.has_value()); + assert(e2.error().i == 10); + + assert(e1->numberOfMoves == 2); + assert(!e1->swapCalled); + assert(e2.error().numberOfMoves == 1); + assert(!e2.error().swapCalled); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnMove { + ThrowOnMove() = default; + ThrowOnMove(ThrowOnMove&&) { throw Except{}; }; + ThrowOnMove& operator=(ThrowOnMove&&) = default; + }; + + // !e1.has_value() && e2.has_value() + { + std::expected e1(std::unexpect, 5); + std::expected e2(std::in_place); + try { + swap(e1, e2); + assert(false); + } catch (Except) { + assert(!e1.has_value()); + assert(e1.error() == 5); + } + } + + // e1.has_value() && !e2.has_value() + { + std::expected e1(5); + std::expected e2(std::unexpect); + try { + swap(e1, e2); + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp @@ -0,0 +1,247 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void swap(expected& rhs) noexcept(see below); +// +// Constraints: +// is_swappable_v is true and +// is_swappable_v is true and +// is_move_constructible_v && is_move_constructible_v is true, and +// is_nothrow_move_constructible_v || is_nothrow_move_constructible_v is true. +// +// Throws: Any exception thrown by the expressions in the Effects. +// Remarks: The exception specification is equivalent to: +// is_nothrow_move_constructible_v && is_nothrow_swappable_v && +// is_nothrow_move_constructible_v && is_nothrow_swappable_v + +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +// Test Constraints: +template +concept HasMemberSwap = requires(std::expected x, std::expected y) { x.swap(y); }; + +static_assert(HasMemberSwap); + +struct NotSwappable {}; +void swap(NotSwappable&, NotSwappable&) = delete; + +// !is_swappable_v +static_assert(!HasMemberSwap); + +// !is_swappable_v +static_assert(!HasMemberSwap); + +struct NotMoveContructible { + NotMoveContructible(NotMoveContructible&&) = delete; + friend void swap(NotMoveContructible&, NotMoveContructible&) {} +}; + +// !is_move_constructible_v +static_assert(!HasMemberSwap); + +// !is_move_constructible_v +static_assert(!HasMemberSwap); + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) noexcept(false); + friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {} +}; + +// !is_nothrow_move_constructible_v && is_nothrow_move_constructible_v +static_assert(HasMemberSwap); + +// is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(HasMemberSwap); + +// !is_nothrow_move_constructible_v && !is_nothrow_move_constructible_v +static_assert(!HasMemberSwap); + +// Test noexcept +template +concept MemberSwapNoexcept = + requires(std::expected x, std::expected y) { + { x.swap(y) } noexcept; + }; + +static_assert(MemberSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!MemberSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!MemberSwapNoexcept); + +struct SwapMayThrow { + friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {} +}; + +// !is_nothrow_swappable_v +static_assert(!MemberSwapNoexcept); + +// !is_nothrow_swappable_v +static_assert(!MemberSwapNoexcept); + +constexpr bool test() { + // this->has_value() && rhs.has_value() + { + std::expected x(std::in_place, 5); + std::expected y(std::in_place, 10); + x.swap(y); + + assert(x.has_value()); + assert(x->i == 10); + assert(x->adlSwapCalled); + assert(y.has_value()); + assert(y->i == 5); + assert(y->adlSwapCalled); + } + + // !this->has_value() && !rhs.has_value() + { + std::expected x(std::unexpect, 5); + std::expected y(std::unexpect, 10); + x.swap(y); + + assert(!x.has_value()); + assert(x.error().i == 10); + assert(x.error().adlSwapCalled); + assert(!y.has_value()); + assert(y.error().i == 5); + assert(y.error().adlSwapCalled); + } + + // this->has_value() && !rhs.has_value() + // && is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::in_place, 5); + std::expected, TrackedMove> e2(std::unexpect, 10); + + e1.swap(e2); + + assert(!e1.has_value()); + assert(e1.error().i == 10); + assert(e2.has_value()); + assert(e2->i == 5); + + assert(e1.error().numberOfMoves == 2); + assert(!e1.error().swapCalled); + assert(e2->numberOfMoves == 1); + assert(!e2->swapCalled); + } + + // this->has_value() && !rhs.has_value() + // && !is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::in_place, 5); + std::expected, TrackedMove> e2(std::unexpect, 10); + + e1.swap(e2); + + assert(!e1.has_value()); + assert(e1.error().i == 10); + assert(e2.has_value()); + assert(e2->i == 5); + + assert(e1.error().numberOfMoves == 1); + assert(!e1.error().swapCalled); + assert(e2->numberOfMoves == 2); + assert(!e2->swapCalled); + } + + // !this->has_value() && rhs.has_value() + // && is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::unexpect, 10); + std::expected, TrackedMove> e2(std::in_place, 5); + + e1.swap(e2); + + assert(e1.has_value()); + assert(e1->i == 5); + assert(!e2.has_value()); + assert(e2.error().i == 10); + + assert(e1->numberOfMoves == 1); + assert(!e1->swapCalled); + assert(e2.error().numberOfMoves == 2); + assert(!e2.error().swapCalled); + } + + // !this->has_value() && rhs.has_value() + // && !is_nothrow_move_constructible_v + { + std::expected, TrackedMove> e1(std::unexpect, 10); + std::expected, TrackedMove> e2(std::in_place, 5); + + e1.swap(e2); + + assert(e1.has_value()); + assert(e1->i == 5); + assert(!e2.has_value()); + assert(e2.error().i == 10); + + assert(e1->numberOfMoves == 2); + assert(!e1->swapCalled); + assert(e2.error().numberOfMoves == 1); + assert(!e2.error().swapCalled); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnMove { + ThrowOnMove() = default; + ThrowOnMove(ThrowOnMove&&) { throw Except{}; }; + ThrowOnMove& operator=(ThrowOnMove&&) = default; + }; + + // !e1.has_value() && e2.has_value() + { + std::expected e1(std::unexpect, 5); + std::expected e2(std::in_place); + try { + e1.swap(e2); + assert(false); + } catch (Except) { + assert(!e1.has_value()); + assert(e1.error() == 5); + } + } + + // e1.has_value() && !e2.has_value() + { + std::expected e1(5); + std::expected e2(std::unexpect); + try { + e1.swap(e2); + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.copy.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr unexpected& operator=(const unexpected&) = default; + +#include +#include + +struct Error { + int i; + constexpr Error(int ii) : i(ii) {} +}; + +constexpr bool test() { + std::unexpected unex1(4); + const std::unexpected unex2(5); + unex1 = unex2; + assert(unex1.error().i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.move.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr unexpected& operator=(unexpected&&) = default; + +#include +#include +#include + +struct Error { + int i; + constexpr Error(int ii) : i(ii) {} + constexpr Error& operator=(Error&& other) { + i = other.i; + other.i = 0; + return *this; + } +}; + +constexpr bool test() { + std::unexpected unex1(4); + std::unexpected unex2(5); + unex1 = std::move(unex2); + assert(unex1.error().i == 5); + assert(unex2.error().i == 0); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/array.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/array.compile.fail.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/array.compile.fail.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A program that instantiates the definition of unexpected for an array type is ill-formed. + +#include + +template class std::unexpected; diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/const.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/const.compile.fail.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/const.compile.fail.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A program that instantiates the definition of unexpected for a cv-qualified type is ill-formed. + +#include + +template class std::unexpected; diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/non_object.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/non_object.compile.fail.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/non_object.compile.fail.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A program that instantiates the definition of unexpected for a non-object type is ill-formed. + +#include + +template class std::unexpected; diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/unexpected.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/unexpected.compile.fail.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/unexpected.compile.fail.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A program that instantiates the definition of unexpected for a specialization of unexpected is ill-formed. + +#include + +template class std::unexpected>; diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/volatile.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/volatile.compile.fail.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/class_mandates/volatile.compile.fail.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A program that instantiates the definition of unexpected for a cv-qualified type is ill-formed. + +#include + +template class std::unexpected; diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template unexpected(E) -> unexpected; + +#include +#include + +struct Foo{}; + +static_assert(std::same_as>); +static_assert(std::same_as>); +static_assert(std::same_as(5))), std::unexpected>); diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.copy.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr unexpected(const unexpected&) = default; + +#include +#include + +struct Error { + int i; + constexpr Error(int ii) : i(ii) {} +}; + +constexpr bool test() { + const std::unexpected unex(5); + auto unex2 = unex; + assert(unex2.error().i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit unexpected(Err&& e); +// +// Constraints: +// - is_same_v, unexpected> is false; and +// - is_same_v, in_place_t> is false; and +// - is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(e). +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Constraints: +static_assert(std::constructible_from, int>); + +// is_same_v, unexpected> +struct CstrFromUnexpected { + CstrFromUnexpected(CstrFromUnexpected const&) = delete; + CstrFromUnexpected(std::unexpected const&); +}; +static_assert(!std::constructible_from, std::unexpected>); + +// is_same_v, in_place_t> +struct CstrFromInplace { + CstrFromInplace(std::in_place_t); +}; +static_assert(!std::constructible_from, std::in_place_t>); + +// !is_constructible_v +struct Foo {}; +static_assert(!std::constructible_from, int>); + +// test explicit +static_assert(std::convertible_to); +static_assert(!std::convertible_to>); + +struct Error { + int i; + constexpr Error(int ii) : i(ii) {} + constexpr Error(const Error& other) : i(other.i) {} + constexpr Error(Error&& other) : i(other.i) { other.i = 0; } + Error(std::initializer_list) { assert(false); } +}; + +constexpr bool test() { + // lvalue + { + Error e(5); + std::unexpected unex(e); + assert(unex.error().i == 5); + assert(e.i == 5); + } + + // rvalue + { + Error e(5); + std::unexpected unex(std::move(e)); + assert(unex.error().i == 5); + assert(e.i == 0); + } + + // Direct-non-list-initializes: does not trigger initializer_list overload + { + Error e(5); + [[maybe_unused]] std::unexpected unex(e); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() = default; + Throwing(const Throwing&) { throw Except{}; } + }; + + Throwing t; + try { + std::unexpected u(t); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace.pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit unexpected(in_place_t, Args&&... args); +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(args).... +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Constraints: +static_assert(std::constructible_from, std::in_place_t, int>); + +// !is_constructible_v +struct Foo {}; +static_assert(!std::constructible_from, std::in_place_t, int>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; + +static_assert(ImplicitlyConstructible); +static_assert(!ImplicitlyConstructible, std::in_place_t, int>); + +struct Arg { + int i; + constexpr Arg(int ii) : i(ii) {} + constexpr Arg(const Arg& other) : i(other.i) {} + constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; } +}; + +struct Error { + Arg arg; + constexpr explicit Error(const Arg& a) : arg(a) {} + constexpr explicit Error(Arg&& a) : arg(std::move(a)) {} + Error(std::initializer_list) :arg(0){ assert(false); } +}; + +constexpr bool test() { + // lvalue + { + Arg a{5}; + std::unexpected unex(std::in_place, a); + assert(unex.error().arg.i == 5); + assert(a.i == 5); + } + + // rvalue + { + Arg a{5}; + std::unexpected unex(std::in_place, std::move(a)); + assert(unex.error().arg.i == 5); + assert(a.i == 0); + } + + // Direct-non-list-initializes: does not trigger initializer_list overload + { + Error e(5); + [[maybe_unused]] std::unexpected unex(std::in_place, e); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; } + }; + + try { + std::unexpected u(std::in_place, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace_init_list.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace_init_list.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace_init_list.pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit unexpected(in_place_t, initializer_list il, Args&&... args); +// +// Constraints: is_constructible_v&, Args...> is true. +// +// Effects: Direct-non-list-initializes unex with il, std::forward(args).... +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Arg { + int i; + constexpr Arg(int ii) : i(ii) {} + constexpr Arg(const Arg& other) : i(other.i) {} + constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; } +}; + +struct Error { + std::initializer_list list; + Arg arg; + constexpr explicit Error(std::initializer_list l, const Arg& a) : list(l), arg(a) {} + constexpr explicit Error(std::initializer_list l, Arg&& a) : list(l), arg(std::move(a)) {} +}; + +// Test Constraints: +static_assert(std::constructible_from, std::in_place_t, std::initializer_list, Arg>); + +// !is_constructible_v&, Args...> +struct Foo {}; +static_assert(!std::constructible_from, std::in_place_t, std::initializer_list, Arg>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; + +static_assert(ImplicitlyConstructible); +static_assert(!ImplicitlyConstructible, std::in_place_t, std::initializer_list, Arg>); + +constexpr bool test() { + // lvalue + { + Arg a{5}; + auto l = {1, 2, 3}; + std::unexpected unex(std::in_place, l, a); + assert(unex.error().arg.i == 5); + assert(std::ranges::equal(unex.error().list, l)); + assert(a.i == 5); + } + + // rvalue + { + Arg a{5}; + auto l = {1, 2, 3}; + std::unexpected unex(std::in_place, l, std::move(a)); + assert(unex.error().arg.i == 5); + assert(std::ranges::equal(unex.error().list, l)); + assert(a.i == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(std::initializer_list, int) { throw Except{}; } + }; + + try { + std::unexpected u(std::in_place, {1, 2}, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.move.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr unexpected(unexpected&&) = default; + +#include +#include +#include + +struct Error { + int i; + constexpr Error(int ii) : i(ii) {} + constexpr Error(Error&& other) : i(other.i) {other.i = 0;} +}; + +constexpr bool test() { + std::unexpected unex(5); + auto unex2 = std::move(unex); + assert(unex2.error().i == 5); + assert(unex.error().i == 0); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// friend constexpr bool operator==(const unexpected& x, const unexpected& y); +// +// Mandates: The expression x.error() == y.error() is well-formed and its result is convertible to bool. +// +// Returns: x.error() == y.error(). + +#include +#include +#include +#include + +struct Error{ + int i; + friend constexpr bool operator==(const Error&, const Error&) = default; +}; + +constexpr bool test() { + std::unexpected unex1(Error{2}); + std::unexpected unex2(Error{3}); + std::unexpected unex3(Error{2}); + assert(unex1 == unex3); + assert(unex1 != unex2); + assert(unex2 != unex3); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const E& error() const & noexcept; + +#include +#include +#include +#include + +template +concept ErrorNoexcept = + requires(const T& t) { + { t.error() } noexcept; + }; + +static_assert(!ErrorNoexcept); +static_assert(ErrorNoexcept>); + +constexpr bool test() { + const std::unexpected unex(5); + std::same_as decltype(auto) i = unex.error(); + assert(i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref_ref.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref_ref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref_ref.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const E&& error() const && noexcept; + +#include +#include +#include +#include + +template +concept ErrorNoexcept = + requires(const T&& t) { + { std::move(t).error() } noexcept; + }; + +static_assert(!ErrorNoexcept); +static_assert(ErrorNoexcept>); + +constexpr bool test() { + const std::unexpected unex(5); + std::same_as decltype(auto) i = std::move(unex).error(); + assert(i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr E& error() & noexcept; + +#include +#include +#include +#include + +template +concept ErrorNoexcept = + requires(T& t) { + { t.error() } noexcept; + }; + +static_assert(!ErrorNoexcept); +static_assert(ErrorNoexcept>); + +constexpr bool test() { + std::unexpected unex(5); + std::same_as decltype(auto) i = unex.error(); + assert(i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref_ref.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref_ref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref_ref.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr E&& error() && noexcept; + +#include +#include +#include +#include + +template +concept ErrorNoexcept = + requires(T&& t) { + { std::move(t).error() } noexcept; + }; + +static_assert(!ErrorNoexcept); +static_assert(ErrorNoexcept>); + +constexpr bool test() { + std::unexpected unex(5); + std::same_as decltype(auto) i = std::move(unex).error(); + assert(i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.free.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.free.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.free.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); +// +// Constraints: is_swappable_v is true. +// +// Effects: Equivalent to x.swap(y). + +#include +#include +#include +#include + +// test noexcept +struct NoexceptSwap { + friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept; +}; + +struct MayThrowSwap { + friend void swap(MayThrowSwap&, MayThrowSwap&); +}; + +template +concept ADLSwapNoexcept = + requires(T& t1, T& t2) { + { swap(t1, t2) } noexcept; + }; + +static_assert(ADLSwapNoexcept>); +static_assert(!ADLSwapNoexcept>); + +// test constraint +struct NonSwappable { + NonSwappable& operator=(const NonSwappable&) = delete; +}; + +static_assert(std::is_swappable_v>); +static_assert(std::is_swappable_v>); +static_assert(!std::is_swappable_v>); + +struct ADLSwap { + constexpr ADLSwap(int ii) : i(ii) {} + ADLSwap& operator=(const ADLSwap&) = delete; + int i; + constexpr friend void swap(ADLSwap& x, ADLSwap& y) { std::swap(x.i, y.i); } +}; + +constexpr bool test() { + std::unexpected unex1(5); + std::unexpected unex2(6); + swap(unex1, unex2); + assert(unex1.error().i == 6); + assert(unex2.error().i == 5); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.member.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.member.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.member.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v); +// +// Mandates: is_swappable_v is true. +// +// Effects: Equivalent to: using std::swap; swap(unex, other.unex); + +#include +#include +#include +#include + +// test noexcept +struct NoexceptSwap { + friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept; +}; + +struct MayThrowSwap { + friend void swap(MayThrowSwap&, MayThrowSwap&); +}; + +template +concept MemberSwapNoexcept = + requires(T& t1, T& t2) { + { t1.swap(t2) } noexcept; + }; + +static_assert(MemberSwapNoexcept>); +static_assert(!MemberSwapNoexcept>); + +struct ADLSwap { + constexpr ADLSwap(int ii) : i(ii) {} + ADLSwap& operator=(const ADLSwap&) = delete; + int i; + constexpr friend void swap(ADLSwap& x, ADLSwap& y) { std::swap(x.i, y.i); } +}; + +constexpr bool test() { + // using std::swap; + { + std::unexpected unex1(5); + std::unexpected unex2(6); + unex1.swap(unex2); + assert(unex1.error() == 6); + assert(unex2.error() == 5); + } + + // adl swap + { + std::unexpected unex1(5); + std::unexpected unex2(6); + unex1.swap(unex2); + assert(unex1.error().i == 6); + assert(unex2.error().i == 5); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected& operator=(const expected& rhs); +// +// Effects: +// - If this->has_value() && rhs.has_value() is true, no effects. +// - Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false; +// - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. +// - Otherwise, equivalent to unex = rhs.error(). +// +// Returns: *this. +// +// Remarks: This operator is defined as deleted unless is_copy_assignable_v is true and is_copy_constructible_v is true. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotCopyConstructible { + NotCopyConstructible(const NotCopyConstructible&) = delete; + NotCopyConstructible& operator=(const NotCopyConstructible&) = default; +}; + +struct NotCopyAssignable { + NotCopyAssignable(const NotCopyAssignable&) = default; + NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; +}; + +// Test constraints +static_assert(std::is_copy_assignable_v>); + +// !is_copy_assignable_v +static_assert(!std::is_copy_assignable_v>); + +// !is_copy_constructible_v +static_assert(!std::is_copy_assignable_v>); + +constexpr bool test() { + // If this->has_value() && rhs.has_value() is true, no effects. + { + std::expected e1; + std::expected e2; + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + assert(e1.has_value()); + } + + // Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false; + { + Traced::state state{}; + std::expected e1; + std::expected e2(std::unexpect, state, 5); + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + assert(!e1.has_value()); + assert(e1.error().data_ == 5); + + assert(state.copyCtorCalled); + } + + // Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. + { + Traced::state state{}; + std::expected e1(std::unexpect, state, 5); + std::expected e2; + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + assert(e1.has_value()); + + assert(state.dtorCalled); + } + + // Otherwise, equivalent to unex = rhs.error(). + { + Traced::state state{}; + std::expected e1(std::unexpect, state, 5); + std::expected e2(std::unexpect, state, 10); + std::same_as&> decltype(auto) x = (e1 = e2); + assert(&x == &e1); + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(state.copyAssignCalled); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/assign/assign.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/assign/assign.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.move.pass.cpp @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected& operator=(expected&& rhs) noexcept(see below); +// +// Effects: +// - If this->has_value() && rhs.has_value() is true, no effects. +// - Otherwise, if this->has_value() is true, equivalent to: +// construct_at(addressof(unex), std::move(rhs.unex)); +// has_val = false; +// - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. +// - Otherwise, equivalent to unex = std::move(rhs.error()). +// +// Returns: *this. +// +// Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v && is_nothrow_move_assignable_v. +// +// This operator is defined as deleted unless is_move_constructible_v is true and is_move_assignable_v is true. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotMoveConstructible { + NotMoveConstructible(NotMoveConstructible&&) = delete; + NotMoveConstructible& operator=(NotMoveConstructible&&) = default; +}; + +struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&) = default; + NotMoveAssignable& operator=(NotMoveAssignable&&) = delete; +}; + +// Test constraints +static_assert(std::is_move_assignable_v>); + +// !is_move_assignable_v +static_assert(!std::is_move_assignable_v>); + +// !is_move_constructible_v +static_assert(!std::is_move_assignable_v>); + +// Test noexcept +struct MoveCtorMayThrow { + MoveCtorMayThrow(MoveCtorMayThrow&&) noexcept(false) {} + MoveCtorMayThrow& operator=(MoveCtorMayThrow&&) noexcept = default; +}; + +struct MoveAssignMayThrow { + MoveAssignMayThrow(MoveAssignMayThrow&&) noexcept = default; + MoveAssignMayThrow& operator=(MoveAssignMayThrow&&) noexcept(false) { return *this; } +}; + +// Test noexcept +static_assert(std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_assignable_v +static_assert(!std::is_nothrow_move_assignable_v>); + +// !is_nothrow_move_constructible_v +static_assert(!std::is_nothrow_move_assignable_v>); + +constexpr bool test() { + // If this->has_value() && rhs.has_value() is true, no effects. + { + std::expected e1; + std::expected e2; + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + assert(e1.has_value()); + } + + // Otherwise, if this->has_value() is true, equivalent to: + // construct_at(addressof(unex), std::move(rhs.unex)); + // has_val = false; + { + Traced::state state{}; + std::expected e1; + std::expected e2(std::unexpect, state, 5); + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + assert(!e1.has_value()); + assert(e1.error().data_ == 5); + + assert(state.moveCtorCalled); + } + + // Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. + { + Traced::state state{}; + std::expected e1(std::unexpect, state, 5); + std::expected e2; + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + assert(e1.has_value()); + + assert(state.dtorCalled); + } + + // Otherwise, equivalent to unex = rhs.error(). + { + Traced::state state{}; + std::expected e1(std::unexpect, state, 5); + std::expected e2(std::unexpect, state, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(e2)); + assert(&x == &e1); + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + + assert(state.moveAssignCalled); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr expected& operator=(const unexpected& e); +// +// Let GF be const G& +// +// Constraints: is_constructible_v is true and is_assignable_v is true. +// +// Effects: +// - If has_value() is true, equivalent to: +// construct_at(addressof(unex), std::forward(e.error())); +// has_val = false; +// - Otherwise, equivalent to: unex = std::forward(e.error()); +// +// Returns: *this. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotCopyConstructible { + NotCopyConstructible(const NotCopyConstructible&) = delete; + NotCopyConstructible& operator=(const NotCopyConstructible&) = default; +}; + +struct NotCopyAssignable { + NotCopyAssignable(const NotCopyAssignable&) = default; + NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow const&) = default; + MoveMayThrow& operator=(const MoveMayThrow&) = default; + MoveMayThrow(MoveMayThrow&&) noexcept(false) {} + MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; } +}; + +// Test constraints +static_assert(std::is_assignable_v&, const std::unexpected&>); + +// !is_constructible_v +static_assert( + !std::is_assignable_v&, const std::unexpected&>); + +// !is_assignable_v +static_assert( + !std::is_assignable_v&, const std::unexpected&>); + +constexpr bool test() { + // - If has_value() is true, equivalent to: + // construct_at(addressof(unex), std::forward(e.error())); + // has_val = false; + { + Traced::state state{}; + std::expected e; + std::unexpected un(std::in_place, state, 5); + std::same_as&> decltype(auto) x = (e = un); + assert(&x == &e); + assert(!e.has_value()); + assert(e.error().data_ == 5); + + assert(state.copyCtorCalled); + } + + // - Otherwise, equivalent to: unex = std::forward(e.error()); + { + Traced::state state1{}; + Traced::state state2{}; + std::expected e(std::unexpect, state1, 5); + std::unexpected un(std::in_place, state2, 10); + std::same_as&> decltype(auto) x = (e = un); + assert(&x == &e); + assert(!e.has_value()); + assert(e.error().data_ == 10); + + assert(state1.copyAssignCalled); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.move.pass.cpp @@ -0,0 +1,205 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr expected& operator=(unexpected&& e); +// +// Let GF be G +// Constraints: +// - is_constructible_v is true; and +// - is_assignable_v is true; and +// - is_nothrow_constructible_v || is_nothrow_move_constructible_v || +// is_nothrow_move_constructible_v is true. +// +// Effects: +// - If has_value() is true, equivalent to: +// reinit-expected(unex, val, std::forward(e.error())); +// has_val = false; +// - Otherwise, equivalent to: unex = std::forward(e.error()); +// Returns: *this. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct NotMoveConstructible { + NotMoveConstructible(NotMoveConstructible&&) = delete; + NotMoveConstructible& operator=(NotMoveConstructible&&) = default; +}; + +struct NotMoveAssignable { + NotMoveAssignable(NotMoveAssignable&&) = default; + NotMoveAssignable& operator=(NotMoveAssignable&&) = delete; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow const&) = default; + MoveMayThrow& operator=(const MoveMayThrow&) = default; + MoveMayThrow(MoveMayThrow&&) noexcept(false) {} + MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; } +}; + +// Test constraints +static_assert(std::is_assignable_v&, std::unexpected&&>); + +// !is_constructible_v +static_assert( + !std::is_assignable_v&, std::unexpected&&>); + +// !is_assignable_v +static_assert(!std::is_assignable_v&, std::unexpected&&>); + +template +struct MaybeNoexcept { + explicit MaybeNoexcept(int) noexcept(convertNoexcept); + MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept); + MaybeNoexcept& operator=(MaybeNoexcept&&) = default; + MaybeNoexcept& operator=(int); +}; + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// !is_nothrow_constructible_v && is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +// !is_nothrow_constructible_v && !is_nothrow_move_constructible_v && +// !is_nothrow_move_constructible_v +static_assert(!std::is_assignable_v, MaybeNoexcept>&, + std::unexpected&&>); + +constexpr bool test() { + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // is_nothrow_constructible_v + // + // In this case, it should call the branch + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::forward(args)...); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().movedFromInt); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // T tmp(std::forward(args)...); + // destroy_at(addressof(oldval)); + // construct_at(addressof(newval), std::move(tmp)); + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(!oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(!e.error().movedFromInt); + assert(e.error().movedFromTmp); + } + + // - If has_value() is true, equivalent to: + // reinit-expected(unex, val, std::forward(e.error())); + // !is_nothrow_constructible_v && !is_nothrow_move_constructible_v + // is_nothrow_move_constructible_v + // + // In this case, it should call the branch + // U tmp(std::move(oldval)); + // destroy_at(addressof(oldval)); + // try { + // construct_at(addressof(newval), std::forward(args)...); + // } catch (...) { + // construct_at(addressof(oldval), std::move(tmp)); + // throw; + // } + { + BothNoexcept::state oldState{}; + std::expected e(std::in_place, oldState, 5); + std::unexpected un(10); + std::same_as&> decltype(auto) x = (e = std::move(un)); + assert(&x == &e); + + assert(oldState.moveCtorCalled); + assert(oldState.dtorCalled); + assert(e.error().movedFromInt); + } + + // Otherwise, equivalent to: unex = std::forward(e.error()); + { + Traced::state oldState{}; + Traced::state newState{}; + std::expected e1(std::unexpect, oldState, 5); + std::unexpected e(std::in_place, newState, 10); + std::same_as&> decltype(auto) x = (e1 = std::move(e)); + assert(&x == &e1); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(oldState.moveAssignCalled); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowOnConvert { + ThrowOnConvert() = default; + ThrowOnConvert(const int&) {} + ThrowOnConvert(int&&) { throw Except{}; } + ThrowOnConvert(const ThrowOnConvert&) noexcept(false) {} + ThrowOnConvert& operator=(const ThrowOnConvert&) = default; + ThrowOnConvert(ThrowOnConvert&&) noexcept(false) {} + ThrowOnConvert& operator=(ThrowOnConvert&&) = default; + }; + + std::expected e1(std::in_place, 5); + std::unexpected un(10); + try { + e1 = std::move(un); + assert(false); + } catch (Except) { + assert(e1.has_value()); + assert(*e1 == 5); + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/assign/emplace.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/assign/emplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/assign/emplace.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void emplace() noexcept; +// +// Effects: If has_value() is false, destroys unex and sets has_val to true. + +#include +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +template +concept EmplaceNoexcept = + requires(T t) { + { t.emplace() } noexcept; + }; +static_assert(!EmplaceNoexcept); + +static_assert(EmplaceNoexcept>); + +constexpr bool test() { + // has_value + { + std::expected e; + e.emplace(); + assert(e.has_value()); + } + + // !has_value + { + Traced::state state{}; + std::expected e(std::unexpect, state, 5); + e.emplace(); + + assert(state.dtorCalled); + assert(e.has_value()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.copy.pass.cpp @@ -0,0 +1,129 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(const expected& rhs); +// +// Let GF be const G& +// +// Constraints: +// - is_void_v is true; and +// - is_constructible_v is true; and +// - is_constructible_v, expected&> is false; and +// - is_constructible_v, expected> is false; and +// - is_constructible_v, const expected&> is false; and +// - is_constructible_v, const expected> is false. +// +// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::forward(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Constraints: +template +concept canCstrFromExpected = std::is_constructible_v, const std::expected&>; + +struct CtorFromInt { + CtorFromInt(int); +}; + +static_assert(canCstrFromExpected); + +struct NoCtorFromInt {}; + +// !is_void_v +static_assert(!canCstrFromExpected); + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +template +struct CtorFrom { + explicit CtorFrom(int) + requires(!std::same_as); + explicit CtorFrom(T); + explicit CtorFrom(auto&&) = delete; +}; + +// Note for below 4 tests, because their E is constructible from cvref of std::expected, +// unexpected will be constructible from cvref of std::expected +// is_constructible_v, expected&> +static_assert(!canCstrFromExpected&>, void, int>); + +// is_constructible_v, expected> +static_assert(!canCstrFromExpected&&>, void, int>); + +// is_constructible_v, const expected&> is false +static_assert(!canCstrFromExpected const&>, void, int>); + +// is_constructible_v, const expected> +static_assert(!canCstrFromExpected const&&>, void, int>); + +// test explicit +static_assert(std::is_convertible_v&, std::expected>); + +// !is_convertible_v. +static_assert(std::is_constructible_v>, const std::expected&>); +static_assert(!std::is_convertible_v&, std::expected>>); + +struct Data { + int i; + constexpr Data(int ii) : i(ii) {} +}; + +constexpr bool test() { + // convert the error + { + const std::expected e1(std::unexpect, 5); + std::expected e2 = e1; + assert(!e2.has_value()); + assert(e2.error().i == 5); + assert(!e1.has_value()); + assert(e1.error() == 5); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowingInt { + ThrowingInt(int) { throw Except{}; } + }; + + // throw on converting error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.move.pass.cpp @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(expected&& rhs); +// +// Let GF be G +// +// Constraints: +// - is_void_v is true; and +// - is_constructible_v is true; and +// - is_constructible_v, expected&> is false; and +// - is_constructible_v, expected> is false; and +// - is_constructible_v, const expected&> is false; and +// - is_constructible_v, const expected> is false. +// +// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::forward(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +template +concept canCstrFromExpected = std::is_constructible_v, std::expected&&>; + +struct CtorFromInt { + CtorFromInt(int); +}; + +static_assert(canCstrFromExpected); + +struct NoCtorFromInt {}; + +// !is_void_v +static_assert(!canCstrFromExpected); + +// !is_constructible_v +static_assert(!canCstrFromExpected); + +template +struct CtorFrom { + explicit CtorFrom(int) + requires(!std::same_as); + explicit CtorFrom(T); + explicit CtorFrom(auto&&) = delete; +}; + +// Note for below 4 tests, because their E is constructible from cvref of std::expected, +// unexpected will be constructible from cvref of std::expected +// is_constructible_v, expected&> +static_assert(!canCstrFromExpected&>, void, int>); + +// is_constructible_v, expected> +static_assert(!canCstrFromExpected&&>, void, int>); + +// is_constructible_v, const expected&> is false +static_assert(!canCstrFromExpected const&>, void, int>); + +// is_constructible_v, const expected> +static_assert(!canCstrFromExpected const&&>, void, int>); + +// test explicit +static_assert(std::is_convertible_v&&, std::expected>); + +// !is_convertible_v. +static_assert(std::is_constructible_v>, std::expected&&>); +static_assert(!std::is_convertible_v&&, std::expected>>); + +struct Data { + MoveOnly data; + constexpr Data(MoveOnly&& m) : data(std::move(m)) {} +}; + +constexpr bool test() { + // convert the error + { + std::expected e1(std::unexpect, 5); + std::expected e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error().data.get() == 5); + assert(!e1.has_value()); + assert(e1.error().get() == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct ThrowingInt { + ThrowingInt(int) { throw Except{}; } + }; + + // throw on converting error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] std::expected e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.copy.pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected(const expected& rhs); +// +// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with rhs.error(). +// +// Postconditions: rhs.has_value() == this->has_value(). +// +// Throws: Any exception thrown by the initialization of unex. +// +// Remarks: +// - This constructor is defined as deleted unless is_copy_constructible_v is true. +// - This constructor is trivial if is_trivially_copy_constructible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +struct NonCopyable { + NonCopyable(const NonCopyable&) = delete; +}; + +struct CopyableNonTrivial { + int i; + constexpr CopyableNonTrivial(int ii) : i(ii) {} + constexpr CopyableNonTrivial(const CopyableNonTrivial& o) { i = o.i; } + friend constexpr bool operator==(const CopyableNonTrivial&, const CopyableNonTrivial&) = default; +}; + +// Test: This constructor is defined as deleted unless is_copy_constructible_v is true. +static_assert(std::is_copy_constructible_v>); +static_assert(std::is_copy_constructible_v>); +static_assert(!std::is_copy_constructible_v>); + +// Test: This constructor is trivial if is_trivially_copy_constructible_v is true. +static_assert(std::is_trivially_copy_constructible_v>); +static_assert(!std::is_trivially_copy_constructible_v>); + +constexpr bool test() { + // copy the error non-trivial + { + const std::expected e1(std::unexpect, 5); + auto e2 = e1; + assert(!e2.has_value()); + assert(e2.error().i == 5); + } + + // copy the error trivial + { + const std::expected e1(std::unexpect, 5); + auto e2 = e1; + assert(!e2.has_value()); + assert(e2.error() == 5); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() = default; + Throwing(const Throwing&) { throw Except{}; } + }; + + // throw on copying error + { + const std::expected e1(std::unexpect); + try { + [[maybe_unused]] auto e2 = e1; + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.default.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.default.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected() noexcept; + +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept + +struct NoDefaultCtor { + constexpr NoDefaultCtor() = delete; +}; + +static_assert(std::is_nothrow_default_constructible_v>); +static_assert(std::is_nothrow_default_constructible_v>); + +struct MyInt { + int i; + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +constexpr bool test() { + // default constructible + { + std::expected e; + assert(e.has_value()); + } + + // non-default constructible + { + std::expected e; + assert(e.has_value()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.inplace.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.inplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.inplace.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr explicit expected(in_place_t) noexcept; + +#include +#include +#include +#include + +// test explicit +static_assert(std::is_constructible_v, std::in_place_t>); +static_assert(!std::is_convertible_v>); + +// test noexcept +static_assert(std::is_nothrow_constructible_v, std::in_place_t>); + +constexpr bool test() { + std::expected e(std::in_place); + assert(e.has_value()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); +// +// Constraints: is_move_constructible_v is true. +// +// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::move(rhs.error()). +// +// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true. +// +// Throws: Any exception thrown by the initialization of unex. +// +// Remarks: This constructor is trivial if is_trivially_move_constructible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +struct NonMovable { + NonMovable(NonMovable&&) = delete; +}; + +struct MovableNonTrivial { + int i; + constexpr MovableNonTrivial(int ii) : i(ii) {} + constexpr MovableNonTrivial(MovableNonTrivial&& o) : i(o.i) { o.i = 0; } + friend constexpr bool operator==(const MovableNonTrivial&, const MovableNonTrivial&) = default; +}; + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) {} +}; + +// Test Constraints: +// - is_move_constructible_v is true. +static_assert(std::is_move_constructible_v>); +static_assert(std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); + +// Test: This constructor is trivial if is_trivially_move_constructible_v is true. +static_assert(std::is_trivially_move_constructible_v>); +static_assert(!std::is_trivially_move_constructible_v>); + +// Test: noexcept(is_nothrow_move_constructible_v) +static_assert(std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); +static_assert(!std::is_nothrow_move_constructible_v>); + +constexpr bool test() { + // move the error non-trivial + { + std::expected e1(std::unexpect, 5); + auto e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error().i == 5); + assert(!e1.has_value()); + assert(e1.error().i == 0); + } + + // move the error trivial + { + std::expected e1(std::unexpect, 5); + auto e2 = std::move(e1); + assert(!e2.has_value()); + assert(e2.error() == 5); + assert(!e1.has_value()); + } + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing() = default; + Throwing(Throwing&&) { throw Except{}; } + }; + + // throw on moving error + { + std::expected e1(std::unexpect); + try { + [[maybe_unused]] auto e2 = std::move(e1); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(unexpect_t, Args&&... args); +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(args).... +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert(std::is_constructible_v, std::unexpect_t>); +static_assert(std::is_constructible_v, std::unexpect_t, int>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, std::unexpect_t, int>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert(!ImplicitlyConstructible, std::unexpect_t>); +static_assert(!ImplicitlyConstructible, std::unexpect_t, int>); + +struct CopyOnly { + int i; + constexpr CopyOnly(int ii) : i(ii) {} + CopyOnly(const CopyOnly&) = default; + CopyOnly(CopyOnly&&) = delete; + friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; } +}; + +template +constexpr void testInt() { + std::expected e(std::unexpect, 5); + assert(!e.has_value()); + assert(e.error() == 5); +} + +template +constexpr void testLValue() { + T t(5); + std::expected e(std::unexpect, t); + assert(!e.has_value()); + assert(e.error() == 5); +} + +template +constexpr void testRValue() { + std::expected e(std::unexpect, T(5)); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testLValue(); + testLValue(); + testRValue(); + testRValue(); + + // no arg + { + std::expected e(std::unexpect); + assert(!e.has_value()); + assert(e.error() == 0); + } + + // one arg + { + std::expected e(std::unexpect, 5); + assert(!e.has_value()); + assert(e.error() == 5); + } + + // multi args + { + std::expected> e(std::unexpect, 1, 2, MoveOnly(3)); + assert(!e.has_value()); + assert((e.error() == std::tuple(1, 2, MoveOnly(3)))); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; }; + }; + + try { + std::expected u(std::unexpect, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect_init_list.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect_init_list.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect_init_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); +// +// Constraints: is_constructible_v&, Args...> is true. +// +// Effects: Direct-non-list-initializes unex with il, std::forward(args).... +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints: +static_assert( + std::is_constructible_v>, std::unexpect_t, std::initializer_list>); + +// !is_constructible_v&, Args...> +static_assert(!std::is_constructible_v, std::unexpect_t, std::initializer_list>); + +// test explicit +template +void conversion_test(T); + +template +concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test({std::forward(args)...}); }; +static_assert(ImplicitlyConstructible); + +static_assert( + !ImplicitlyConstructible>, std::unexpect_t, std::initializer_list>); + +template +struct Data { + std::vector vec_; + std::tuple tuple_; + + template + requires std::is_constructible_v, Us&&...> + constexpr Data(std::initializer_list il, Us&&... us) : vec_(il), tuple_(std::forward(us)...) {} +}; + +constexpr bool test() { + // no arg + { + std::expected> e(std::unexpect, {1, 2, 3}); + assert(!e.has_value()); + auto expectedList = {1, 2, 3}; + assert(std::ranges::equal(e.error().vec_, expectedList)); + } + + // one arg + { + std::expected> e(std::unexpect, {4, 5, 6}, MoveOnly(5)); + assert(!e.has_value()); + auto expectedList = {4, 5, 6}; + assert((std::ranges::equal(e.error().vec_, expectedList))); + assert(std::get<0>(e.error().tuple_) == 5); + } + + // multi args + { + int i = 5; + int j = 6; + MoveOnly m(7); + std::expected> e(std::unexpect, {1, 2}, i, std::move(j), std::move(m)); + assert(!e.has_value()); + auto expectedList = {1, 2}; + assert((std::ranges::equal(e.error().vec_, expectedList))); + assert(&std::get<0>(e.error().tuple_) == &i); + assert(&std::get<1>(e.error().tuple_) == &j); + assert(std::get<2>(e.error().tuple_) == 7); + assert(m.get() == 0); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(std::initializer_list, int) { throw Except{}; }; + }; + + try { + std::expected u(std::unexpect, {1, 2}, 5); + assert(false); + } catch (Except) { + } +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.copy.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.copy.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(const unexpected& e); +// +// Let GF be const G& +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(e.error()). +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints +static_assert(std::is_constructible_v, const std::unexpected&>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, const std::unexpected&>); +static_assert(!std::is_constructible_v, const std::unexpected&>); + +// explicit(!is_convertible_v) +struct NotConvertible { + explicit NotConvertible(int); +}; +static_assert(std::is_convertible_v&, std::expected>); +static_assert(!std::is_convertible_v&, std::expected>); + +struct MyInt { + int i; + constexpr MyInt(int ii) : i(ii) {} + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +template +constexpr void testUnexpected() { + const std::unexpected u(5); + std::expected e(u); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr bool test() { + testUnexpected(); + testUnexpected(); + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; } + }; + + { + const std::unexpected u(5); + try { + [[maybe_unused]] std::expected e(u); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.move.pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// constexpr explicit(!is_convertible_v) expected(unexpected&& e); +// +// Let GF be G +// +// Constraints: is_constructible_v is true. +// +// Effects: Direct-non-list-initializes unex with std::forward(e.error()). +// +// Postconditions: has_value() is false. +// +// Throws: Any exception thrown by the initialization of unex. + +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +// Test Constraints +static_assert(std::is_constructible_v, std::unexpected>); +static_assert(std::is_constructible_v, std::unexpected>); + +// !is_constructible_v +struct foo {}; +static_assert(!std::is_constructible_v, std::unexpected>); + +// explicit(!is_convertible_v) +struct NotConvertible { + explicit NotConvertible(int); +}; +static_assert(std::is_convertible_v&&, std::expected>); +static_assert(!std::is_convertible_v&&, std::expected>); + +struct MyInt { + int i; + constexpr MyInt(int ii) : i(ii) {} + friend constexpr bool operator==(const MyInt&, const MyInt&) = default; +}; + +template +constexpr void testInt() { + std::unexpected u(5); + std::expected e(std::move(u)); + assert(!e.has_value()); + assert(e.error() == 5); +} + +constexpr void testMoveOnly() { + std::unexpected u(MoveOnly(5)); + std::expected e(std::move(u)); + assert(!e.has_value()); + assert(e.error() == 5); + assert(u.error() == 0); +} + +constexpr bool test() { + testInt(); + testInt(); + testInt(); + testMoveOnly(); + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Except {}; + + struct Throwing { + Throwing(int) { throw Except{}; } + }; + + { + std::unexpected u(5); + try { + [[maybe_unused]] std::expected e(std::move(u)); + assert(false); + } catch (Except) { + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/dtor.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/dtor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/dtor.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr ~expected(); +// +// Effects: If has_value() is false, destroys unex. +// +// Remarks: If is_trivially_destructible_v is true, then this destructor is a trivial destructor. + +#include +#include +#include +#include + +#include "test_macros.h" + +// Test Remarks: If is_trivially_destructible_v is true, then this destructor is a trivial destructor. +struct NonTrivial { + ~NonTrivial() {} +}; + +static_assert(std::is_trivially_destructible_v>); +static_assert(!std::is_trivially_destructible_v>); + +struct TrackedDestroy { + bool& destroyed; + constexpr TrackedDestroy(bool& b) : destroyed(b) {} + constexpr ~TrackedDestroy() { destroyed = true; } +}; + +constexpr bool test() { + // has value + { [[maybe_unused]] std::expected e(std::in_place); } + + // has error + { + bool errorDestroyed = false; + { [[maybe_unused]] std::expected e(std::unexpect, errorDestroyed); } + assert(errorDestroyed); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/equality/equality.other_expected.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/equality/equality.other_expected.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/equality/equality.other_expected.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template requires (is_void_v) +// friend constexpr bool operator==(const expected& x, const expected& y); + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test constraint +template +concept CanCompare = requires(T1 t1, T2 t2) { t1 == t2; }; + +struct Foo{}; +static_assert(!CanCompare); + +static_assert(CanCompare, std::expected>); +static_assert(CanCompare, std::expected>); + +// Note this is true because other overloads in expected are unconstrained +static_assert(CanCompare, std::expected>); + +constexpr bool test() { + // x.has_value() && y.has_value() + { + const std::expected e1; + const std::expected e2; + assert(e1 == e2); + } + + // !x.has_value() && y.has_value() + { + const std::expected e1(std::unexpect, 5); + const std::expected e2; + assert(e1 != e2); + } + + // x.has_value() && !y.has_value() + { + const std::expected e1; + const std::expected e2(std::unexpect, 10); + const std::expected e3(std::unexpect, 5); + assert(e1 != e2); + assert(e1 != e3); + } + + // !x.has_value() && !y.has_value() + { + const std::expected e1(std::unexpect, 5); + const std::expected e2(std::unexpect, 10); + const std::expected e3(std::unexpect, 5); + assert(e1 != e2); + assert(e1 == e3); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/equality/equality.unexpected.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/equality/equality.unexpected.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/equality/equality.unexpected.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template friend constexpr bool operator==(const expected& x, const unexpected& e); + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Data { + int i; + constexpr Data(int ii) : i(ii) {} + + friend constexpr bool operator==(const Data& data, int ii) { return data.i == ii; } +}; + +constexpr bool test() { + // x.has_value() + { + const std::expected e1; + std::unexpected un2(10); + std::unexpected un3(5); + assert(e1 != un2); + assert(e1 != un3); + } + + // !x.has_value() + { + const std::expected e1(std::unexpect, 5); + std::unexpected un2(10); + std::unexpected un3(5); + assert(e1 != un2); + assert(e1 == un3); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/bool.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/bool.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/bool.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr explicit operator bool() const noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept OpBoolNoexcept = + requires(T t) { + { static_cast(t) } noexcept; + }; + +struct Foo {}; +static_assert(!OpBoolNoexcept); + +static_assert(OpBoolNoexcept>); +static_assert(OpBoolNoexcept>); + +// Test explicit +static_assert(!std::is_convertible_v, bool>); + +constexpr bool test() { + // has_value + { + const std::expected e; + assert(static_cast(e)); + } + + // !has_value + { + const std::expected e(std::unexpect, 5); + assert(!static_cast(e)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/deref.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/deref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/deref.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void operator*() const & noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept DerefNoexcept = + requires(T t) { + { std::forward(t).operator*() } noexcept; + }; + +static_assert(!DerefNoexcept); + +static_assert(DerefNoexcept>); + +constexpr bool test() { + const std::expected e; + *e; + static_assert(std::is_same_v); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/error.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/error.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/error.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const E& error() const & noexcept; +// constexpr E& error() & noexcept; +// constexpr E&& error() && noexcept; +// constexpr const E&& error() const && noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept ErrorNoexcept = + requires(T t) { + { std::forward(t).error() } noexcept; + }; + +static_assert(!ErrorNoexcept); + +static_assert(ErrorNoexcept&>); +static_assert(ErrorNoexcept&>); +static_assert(ErrorNoexcept&&>); +static_assert(ErrorNoexcept&&>); + +constexpr bool test() { + // non-const & + { + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.error(); + assert(x == 5); + } + + // const & + { + const std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = e.error(); + assert(x == 5); + } + + // non-const && + { + std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = std::move(e).error(); + assert(x == 5); + } + + // const && + { + const std::expected e(std::unexpect, 5); + std::same_as decltype(auto) x = std::move(e).error(); + assert(x == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/has_value.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/has_value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/has_value.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr bool has_value() const noexcept; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Test noexcept +template +concept HasValueNoexcept = + requires(T t) { + { t.has_value() } noexcept; + }; + +struct Foo {}; +static_assert(!HasValueNoexcept); + +static_assert(HasValueNoexcept>); +static_assert(HasValueNoexcept>); + +constexpr bool test() { + // has_value + { + const std::expected e; + assert(e.has_value()); + } + + // !has_value + { + const std::expected e(std::unexpect, 5); + assert(!e.has_value()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void value() const &; +// constexpr void value() &&; + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" +#include "test_macros.h" + +constexpr bool test() { + // const & + { + const std::expected e; + e.value(); + static_assert(std::is_same_v); + } + + // && + { + std::expected e; + e.value(); + static_assert(std::is_same_v); + } + + return true; +} + +void testException() { +#ifndef TEST_HAS_NO_EXCEPTIONS + + // int + { + const std::expected e(std::unexpect, 5); + try { + e.value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + + // MoveOnly + { + std::expected e(std::unexpect, 5); + try { + std::move(e).value(); + assert(false); + } catch (const std::bad_expected_access& ex) { + assert(ex.error() == 5); + } + } + +#endif +} + +int main(int, char**) { + test(); + static_assert(test()); + testException(); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(swap(x,y))); + +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) noexcept(false); + friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {} +}; + +// Test noexcept +template +concept FreeSwapNoexcept = + requires(std::expected x, std::expected y) { + { swap(x, y) } noexcept; + }; + +static_assert(FreeSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!FreeSwapNoexcept); + +struct SwapMayThrow { + friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {} +}; + +// !is_nothrow_swappable_v +static_assert(!FreeSwapNoexcept); + +constexpr bool test() { + // this->has_value() && rhs.has_value() + { + std::expected x; + std::expected y; + swap(x, y); + + assert(x.has_value()); + assert(y.has_value()); + } + + // !this->has_value() && !rhs.has_value() + { + std::expected x(std::unexpect, 5); + std::expected y(std::unexpect, 10); + swap(x, y); + + assert(!x.has_value()); + assert(x.error().i == 10); + assert(x.error().adlSwapCalled); + assert(!y.has_value()); + assert(y.error().i == 5); + assert(y.error().adlSwapCalled); + } + + // this->has_value() && !rhs.has_value() + { + Traced::state s{}; + std::expected e1(std::in_place); + std::expected e2(std::unexpect, s, 10); + + e1.swap(e2); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(e2.has_value()); + + assert(s.moveCtorCalled); + assert(s.dtorCalled); + } + + // !this->has_value() && rhs.has_value() + { + Traced::state s{}; + std::expected e1(std::unexpect, s, 10); + std::expected e2(std::in_place); + + e1.swap(e2); + + assert(e1.has_value()); + assert(!e2.has_value()); + assert(e2.error().data_ == 10); + + assert(s.moveCtorCalled); + assert(s.dtorCalled); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr void swap(expected& rhs) noexcept(see below); +// +// Constraints: +// is_swappable_v is true and is_move_constructible_v is true. +// +// Throws: Any exception thrown by the expressions in the Effects. +// +// Remarks: The exception specification is equivalent to: +// is_nothrow_move_constructible_v && is_nothrow_swappable_v. + +#include +#include +#include +#include + +#include "../../types.h" +#include "test_macros.h" + +// Test Constraints: +template +concept HasMemberSwap = requires(std::expected x, std::expected y) { x.swap(y); }; + +static_assert(HasMemberSwap); + +struct NotSwappable {}; +void swap(NotSwappable&, NotSwappable&) = delete; + +// !is_swappable_v +static_assert(!HasMemberSwap); + +struct NotMoveContructible { + NotMoveContructible(NotMoveContructible&&) = delete; + friend void swap(NotMoveContructible&, NotMoveContructible&) {} +}; + +// !is_move_constructible_v +static_assert(!HasMemberSwap); + +// Test noexcept +struct MoveMayThrow { + MoveMayThrow(MoveMayThrow&&) noexcept(false); + friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {} +}; + +template +concept MemberSwapNoexcept = + requires(std::expected x, std::expected y) { + { x.swap(y) } noexcept; + }; + +static_assert(MemberSwapNoexcept); + +// !is_nothrow_move_constructible_v +static_assert(!MemberSwapNoexcept); + +struct SwapMayThrow { + friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {} +}; + +// !is_nothrow_swappable_v +static_assert(!MemberSwapNoexcept); + +constexpr bool test() { + // this->has_value() && rhs.has_value() + { + std::expected x; + std::expected y; + x.swap(y); + + assert(x.has_value()); + assert(y.has_value()); + } + + // !this->has_value() && !rhs.has_value() + { + std::expected x(std::unexpect, 5); + std::expected y(std::unexpect, 10); + x.swap(y); + + assert(!x.has_value()); + assert(x.error().i == 10); + assert(x.error().adlSwapCalled); + assert(!y.has_value()); + assert(y.error().i == 5); + assert(y.error().adlSwapCalled); + } + + // this->has_value() && !rhs.has_value() + { + Traced::state s{}; + std::expected e1(std::in_place); + std::expected e2(std::unexpect, s, 10); + + e1.swap(e2); + + assert(!e1.has_value()); + assert(e1.error().data_ == 10); + assert(e2.has_value()); + + assert(s.moveCtorCalled); + assert(s.dtorCalled); + } + + // !this->has_value() && rhs.has_value() + { + Traced::state s{}; + std::expected e1(std::unexpect, s, 10); + std::expected e2(std::in_place); + + e1.swap(e2); + + assert(e1.has_value()); + assert(!e2.has_value()); + assert(e2.error().data_ == 10); + + assert(s.moveCtorCalled); + assert(s.dtorCalled); + } + + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/utilities/expected/types.h b/libcxx/test/std/utilities/expected/types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/expected/types.h @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_UTILITIES_EXPECTED_TYPES_H +#define TEST_STD_UTILITIES_EXPECTED_TYPES_H + +#include + +template +struct TracedBase { + struct state { + bool copyCtorCalled = false; + bool copyAssignCalled = false; + bool moveCtorCalled = false; + bool moveAssignCalled = false; + bool dtorCalled = false; + }; + + state* state_ = nullptr; + bool copiedFromInt = false; + bool movedFromInt = false; + bool copiedFromTmp = false; + bool movedFromTmp = false; + int data_; + + constexpr TracedBase(const int& ii) noexcept(convertNoexcept) : data_(ii) { copiedFromInt = true; } + constexpr TracedBase(int&& ii) noexcept(convertNoexcept) : data_(ii) { movedFromInt = true; } + constexpr TracedBase(state& s, int ii) noexcept : state_(&s), data_(ii) {} + constexpr TracedBase(const TracedBase& other) noexcept(copyMoveNoexcept) : state_(other.state_), data_(other.data_) { + if (state_) { + state_->copyCtorCalled = true; + } else { + copiedFromTmp = true; + } + } + constexpr TracedBase(TracedBase&& other) noexcept(copyMoveNoexcept) : state_(other.state_), data_(other.data_) { + if (state_) { + state_->moveCtorCalled = true; + } else { + movedFromTmp = true; + } + } + constexpr TracedBase& operator=(const TracedBase& other) noexcept(copyMoveNoexcept) { + data_ = other.data_; + state_->copyAssignCalled = true; + return *this; + } + constexpr TracedBase& operator=(TracedBase&& other) noexcept(copyMoveNoexcept) { + data_ = other.data_; + state_->moveAssignCalled = true; + return *this; + } + constexpr ~TracedBase() { + if (state_) { + state_->dtorCalled = true; + } + } +}; + +using Traced = TracedBase; +using TracedNoexcept = TracedBase; + +using MoveThrowConvNoexcept = TracedBase; +using MoveNoexceptConvThrow = TracedBase; +using BothMayThrow = TracedBase; +using BothNoexcept = TracedBase; + +struct ADLSwap { + int i; + bool adlSwapCalled = false; + constexpr ADLSwap(int ii) : i(ii) {} + constexpr friend void swap(ADLSwap& x, ADLSwap& y) { + std::swap(x.i, y.i); + x.adlSwapCalled = true; + y.adlSwapCalled = true; + } +}; + +template +struct TrackedMove { + int i; + int numberOfMoves = 0; + bool swapCalled = false; + + constexpr TrackedMove(int ii) : i(ii) {} + constexpr TrackedMove(TrackedMove&& other) noexcept(Noexcept) + : i(other.i), numberOfMoves(other.numberOfMoves), swapCalled(other.swapCalled) { + ++numberOfMoves; + } + + constexpr friend void swap(TrackedMove& x, TrackedMove& y) { + std::swap(x.i, y.i); + std::swap(x.numberOfMoves, y.numberOfMoves); + x.swapCalled = true; + y.swapCalled = true; + } +}; + +#endif // TEST_STD_UTILITIES_EXPECTED_TYPES_H diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -305,6 +305,10 @@ "values": { "c++17": 201603, "c++20": 201902 }, "headers": ["execution"], "unimplemented": True, + }, { + "name": "__cpp_lib_expected", + "values": { "c++2b": 202202 }, + "headers": ["expected"], }, { "name": "__cpp_lib_filesystem", "values": { "c++17": 201703 }, diff --git a/libcxx/utils/generate_header_inclusion_tests.py b/libcxx/utils/generate_header_inclusion_tests.py --- a/libcxx/utils/generate_header_inclusion_tests.py +++ b/libcxx/utils/generate_header_inclusion_tests.py @@ -68,6 +68,7 @@ "concepts": "20", "coroutine": "20", "cuchar": "11", + "expected": "23", "filesystem": "17", "initializer_list": "11", "optional": "17",