[libcxx-commits] [libcxx] e356f68 - [libc++] Implement `std::expected` P0323R12
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 14 07:44:56 PST 2022
Author: Hui Xie
Date: 2022-12-14T15:43:42Z
New Revision: e356f681f6c46ac35f933dc0cef3b25ceee8b210
URL: https://github.com/llvm/llvm-project/commit/e356f681f6c46ac35f933dc0cef3b25ceee8b210
DIFF: https://github.com/llvm/llvm-project/commit/e356f681f6c46ac35f933dc0cef3b25ceee8b210.diff
LOG: [libc++] Implement `std::expected` P0323R12
Implement `std::expected` https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0323r12.html
Added tests
Differential Revision: https://reviews.llvm.org/D124516
address comment
Added:
libcxx/include/__expected/bad_expected_access.h
libcxx/include/__expected/expected.h
libcxx/include/__expected/unexpect.h
libcxx/include/__expected/unexpected.h
libcxx/include/expected
libcxx/test/libcxx/utilities/expected/expected.expected/assert.arrow.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.expected/assert.deref.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.expected/assert.error.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.expected/noexcept.extension.compile.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.expected/value_or.mandates.verify.cpp
libcxx/test/libcxx/utilities/expected/expected.unexpected/class.mandates.verify.cpp
libcxx/test/libcxx/utilities/expected/expected.unexpected/noexcept.extension.compile.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.unexpected/swap.mandates.verify.cpp
libcxx/test/libcxx/utilities/expected/expected.void/assert.deref.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.void/assert.error.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
libcxx/test/libcxx/utilities/expected/expected.void/noexcept.extension.compile.pass.cpp
libcxx/test/libcxx/utilities/expected/types.h
libcxx/test/libcxx/utilities/expected/version.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/expected.version.compile.pass.cpp
libcxx/test/std/utilities/expected/expected.bad/ctor.error.pass.cpp
libcxx/test/std/utilities/expected/expected.bad/error.member.pass.cpp
libcxx/test/std/utilities/expected/expected.bad/what.noexcept.compile.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/assign.U.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.move.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/emplace.intializer_list.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.convert.move.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.default.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace_init_list.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.move.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect_init_list.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpected.move.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/dtor.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/equality/equality.T2.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/equality/equality.other_expected.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/equality/equality.unexpected.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/arrow.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/bool.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/deref.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/error.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/has_value.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/observers/value_or.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/swap/free.swap.pass.cpp
libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/assign/assign.move.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace_init_list.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.move.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref_ref.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref_ref.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.free.pass.cpp
libcxx/test/std/utilities/expected/expected.unexpected/swap/swap.member.pass.cpp
libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.void/assign/assign.move.pass.cpp
libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.move.pass.cpp
libcxx/test/std/utilities/expected/expected.void/assign/emplace.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.convert.move.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.default.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.inplace.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect_init_list.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.copy.pass.cpp
libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpected.move.pass.cpp
libcxx/test/std/utilities/expected/expected.void/dtor.pass.cpp
libcxx/test/std/utilities/expected/expected.void/equality/equality.other_expected.pass.cpp
libcxx/test/std/utilities/expected/expected.void/equality/equality.unexpected.pass.cpp
libcxx/test/std/utilities/expected/expected.void/observers/bool.pass.cpp
libcxx/test/std/utilities/expected/expected.void/observers/deref.pass.cpp
libcxx/test/std/utilities/expected/expected.void/observers/error.pass.cpp
libcxx/test/std/utilities/expected/expected.void/observers/has_value.pass.cpp
libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp
libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp
libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp
libcxx/test/std/utilities/expected/types.h
Modified:
libcxx/docs/FeatureTestMacroTable.rst
libcxx/docs/Status/Cxx2bIssues.csv
libcxx/docs/Status/Cxx2bPapers.csv
libcxx/include/CMakeLists.txt
libcxx/include/__type_traits/is_member_pointer.h
libcxx/include/__type_traits/is_scalar.h
libcxx/include/__type_traits/is_void.h
libcxx/include/libcxx.imp
libcxx/include/module.modulemap.in
libcxx/include/version
libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
libcxx/test/libcxx/clang_tidy.sh.cpp
libcxx/test/libcxx/double_include.sh.cpp
libcxx/test/libcxx/min_max_macros.compile.pass.cpp
libcxx/test/libcxx/modules_include.sh.cpp
libcxx/test/libcxx/nasty_macros.compile.pass.cpp
libcxx/test/libcxx/no_assert_include.compile.pass.cpp
libcxx/test/libcxx/private_headers.verify.cpp
libcxx/test/libcxx/transitive_includes.sh.cpp
libcxx/test/libcxx/transitive_includes/cxx03.csv
libcxx/test/libcxx/transitive_includes/cxx11.csv
libcxx/test/libcxx/transitive_includes/cxx14.csv
libcxx/test/libcxx/transitive_includes/cxx17.csv
libcxx/test/libcxx/transitive_includes/cxx20.csv
libcxx/test/libcxx/transitive_includes/cxx2b.csv
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
libcxx/utils/generate_feature_test_macro_components.py
libcxx/utils/generate_header_inclusion_tests.py
Removed:
################################################################################
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a1371267cd32b..c4ecbd6279924 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -318,6 +318,8 @@ Status
------------------------------------------------- -----------------
``__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
index 4f3d82b530397..67f46373029e0 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -167,11 +167,11 @@
"`3671 <https://wg21.link/LWG3671>`__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","",""
"`3672 <https://wg21.link/LWG3672>`__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|"
"`3683 <https://wg21.link/LWG3683>`__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","",""
-"`3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","July 2022","",""
+"`3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","July 2022","Complete","16.0"
"`3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|"
"`3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","July 2022","","","|format|"
"`3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","","|ranges| |spaceship|"
-"`3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","July 2022","",""
+"`3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","July 2022","Complete","16.0"
"`3704 <https://wg21.link/LWG3704>`__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","",""
"`3705 <https://wg21.link/LWG3705>`__","Hashability shouldn't depend on basic_string's allocator","July 2022","|Complete|","16.0"
"`3707 <https://wg21.link/LWG3707>`__","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
index 402e233aaea24..e6245261a7d0a 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -38,7 +38,7 @@
"`P2393R1 <https://wg21.link/P2393R1>`__","LWG","Cleaning up ``integer``-class types","October 2021","",""
"`P2401R0 <https://wg21.link/P2401R0>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0"
"","","","","",""
-"`P0323R12 <https://wg21.link/P0323R12>`__","LWG","``std::expected``","February 2022","",""
+"`P0323R12 <https://wg21.link/P0323R12>`__","LWG","``std::expected``","February 2022","|Complete|","16.0"
"`P0533R9 <https://wg21.link/P0533R9>`__","LWG","``constexpr`` for ``<cmath>`` and ``<cstdlib>``","February 2022","",""
"`P0627R6 <https://wg21.link/P0627R6>`__","LWG","Function to mark unreachable code","February 2022","|Complete|","15.0"
"`P1206R7 <https://wg21.link/P1206R7>`__","LWG","``ranges::to``: A function to convert any range to a container","February 2022","","","|ranges|"
@@ -86,7 +86,7 @@
"`P2517R1 <https://wg21.link/P2517R1>`__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","",""
"`P2520R0 <https://wg21.link/P2520R0>`__","LWG","``move_iterator`` should be a random access iterator","July 2022","","","|ranges|"
"`P2540R1 <https://wg21.link/P2540R1>`__","LWG","Empty Product for certain Views","July 2022","","","|ranges|"
-"`P2549R1 <https://wg21.link/P2549R1>`__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","",""
+"`P2549R1 <https://wg21.link/P2549R1>`__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","|Complete|","16.0"
"`P2553R1 <https://wg21.link/P2553R1>`__","LWG","Make ``mdspan`` ``size_type`` controllable","July 2022","",""
"`P2554R0 <https://wg21.link/P2554R0>`__","LWG","C-Array Interoperability of MDSpan","July 2022","",""
"`P2585R0 <https://wg21.link/P2585R0>`__","LWG","Improving default container formatting","July 2022","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 7dc3ffa252a8a..1c8ce896ada50 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -269,6 +269,10 @@ set(files
__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
@@ -740,6 +744,7 @@ set(files
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
index 0000000000000..361eab4b60187
--- /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 <exception>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Err>
+class bad_expected_access;
+
+template <>
+class bad_expected_access<void> : 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;
+ ~bad_expected_access() override = default;
+
+public:
+ // The way this has been designed (by using a class template below) means that we'll already
+ // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch
+ // of work to do. So it is not worth hiding the <void> specialization in the dylib, given that
+ // it adds deployment target restrictions.
+ const char* what() const noexcept override { return "bad access to std::expected"; }
+};
+
+template <class _Err>
+class bad_expected_access : public bad_expected_access<void> {
+public:
+ _LIBCPP_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(std::move(__e)) {}
+
+ _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
index 0000000000000..593ec4bb39f88
--- /dev/null
+++ b/libcxx/include/__expected/expected.h
@@ -0,0 +1,971 @@
+// -*- 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/conjunction.h>
+#include <__type_traits/disjunction.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/lazy.h>
+#include <__type_traits/negation.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 <cstdlib> // for std::abort
+#include <initializer_list>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace __expected {
+
+template <class _Err, class _Arg>
+_LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
+# ifndef _LIBCPP_NO_EXCEPTIONS
+ throw bad_expected_access<_Err>(std::forward<_Arg>(__arg));
+# else
+ (void)__arg;
+ std::abort();
+# endif
+}
+
+} // namespace __expected
+
+template <class _Tp, class _Err>
+class expected {
+ static_assert(
+ !is_reference_v<_Tp> &&
+ !is_function_v<_Tp> &&
+ !is_same_v<remove_cv_t<_Tp>, in_place_t> &&
+ !is_same_v<remove_cv_t<_Tp>, unexpect_t> &&
+ !__unexpected::__is_unexpected<remove_cv_t<_Tp>>::value &&
+ __unexpected::__valid_unexpected<_Err>::value
+ ,
+ "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a "
+ "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a "
+ "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the "
+ "definition of the template expected<T, E> with a type for the E parameter that is not a valid "
+ "template argument for unexpected is ill-formed.");
+
+ template <class _Up, class _OtherErr>
+ friend class expected;
+
+public:
+ using value_type = _Tp;
+ using error_type = _Err;
+ using unexpected_type = unexpected<_Err>;
+
+ template <class _Up>
+ using rebind = expected<_Up, error_type>;
+
+ // [expected.object.ctor], constructors
+ _LIBCPP_HIDE_FROM_ABI constexpr expected()
+ noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
+ requires is_default_constructible_v<_Tp>
+ : __has_val_(true) {
+ std::construct_at(std::addressof(__union_.__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>) // strengthened
+ 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(__union_.__val_), __other.__union_.__val_);
+ } else {
+ std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__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(__union_.__val_), std::move(__other.__union_.__val_));
+ } else {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
+ }
+ }
+
+private:
+ template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
+ using __can_convert =
+ _And< is_constructible<_Tp, _UfQual>,
+ is_constructible<_Err, _OtherErrQual>,
+ _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
+ _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
+ _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>,
+ _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>,
+ _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>,
+ _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>,
+ _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
+ _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >;
+
+
+public:
+ template <class _Up, class _OtherErr>
+ requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> ||
+ !is_convertible_v<const _OtherErr&, _Err>)
+ expected(const expected<_Up, _OtherErr>& __other)
+ noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
+ is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
+ : __has_val_(__other.__has_val_) {
+ if (__has_val_) {
+ std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
+ } else {
+ std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
+ }
+ }
+
+ template <class _Up, class _OtherErr>
+ requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
+ expected(expected<_Up, _OtherErr>&& __other)
+ noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
+ : __has_val_(__other.__has_val_) {
+ if (__has_val_) {
+ std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
+ } else {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
+ }
+ }
+
+ template <class _Up = _Tp>
+ requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
+ !__unexpected::__is_unexpected<remove_cvref_t<_Up>>::value && 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>) // strengthened
+ : __has_val_(true) {
+ std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u));
+ }
+
+
+ template <class _OtherErr>
+ requires is_constructible_v<_Err, const _OtherErr&>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
+ expected(const unexpected<_OtherErr>& __unex)
+ noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), __unex.error());
+ }
+
+ template <class _OtherErr>
+ requires is_constructible_v<_Err, _OtherErr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
+ expected(unexpected<_OtherErr>&& __unex)
+ noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
+ }
+
+ template <class... _Args>
+ 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...>) // strengthened
+ : __has_val_(true) {
+ std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
+ }
+
+ template <class _Up, class... _Args>
+ 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...>) // strengthened
+ : __has_val_(true) {
+ std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
+ }
+
+ template <class... _Args>
+ requires is_constructible_v<_Err, _Args...>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
+ noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
+ }
+
+ template <class _Up, class... _Args>
+ 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...>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__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(__union_.__val_));
+ } else {
+ std::destroy_at(std::addressof(__union_.__unex_));
+ }
+ }
+
+private:
+ template <class _T1, class _T2, class... _Args>
+ _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 {
+ static_assert(
+ is_nothrow_move_constructible_v<_T2>,
+ "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
+ "be reverted to the previous state in case an exception is thrown during the assignment.");
+ _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();
+ }
+ }
+
+public:
+ // [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>) // strengthened
+ 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_) {
+ __union_.__val_ = __rhs.__union_.__val_;
+ } else if (__has_val_) {
+ __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_);
+ } else if (__rhs.__has_val_) {
+ __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_);
+ } else {
+ __union_.__unex_ = __rhs.__union_.__unex_;
+ }
+ // note: only reached if no exception+rollback was done inside __reinit_expected
+ __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_) {
+ __union_.__val_ = std::move(__rhs.__union_.__val_);
+ } else if (__has_val_) {
+ __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_));
+ } else if (__rhs.__has_val_) {
+ __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_));
+ } else {
+ __union_.__unex_ = std::move(__rhs.__union_.__unex_);
+ }
+ // note: only reached if no exception+rollback was done inside __reinit_expected
+ __has_val_ = __rhs.__has_val_;
+ return *this;
+ }
+
+ template <class _Up = _Tp>
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v)
+ requires(!is_same_v<expected, remove_cvref_t<_Up>> &&
+ !__unexpected::__is_unexpected<remove_cvref_t<_Up>>::value &&
+ 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_val_) {
+ __union_.__val_ = std::forward<_Up>(__v);
+ } else {
+ __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v));
+ __has_val_ = true;
+ }
+ return *this;
+ }
+
+private:
+ template <class _OtherErrQual>
+ static constexpr bool __can_assign_from_unexpected =
+ _And< is_constructible<_Err, _OtherErrQual>,
+ is_assignable<_Err&, _OtherErrQual>,
+ _Lazy<_Or,
+ is_nothrow_constructible<_Err, _OtherErrQual>,
+ is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_constructible<_Err>> >::value;
+
+public:
+ template <class _OtherErr>
+ requires(__can_assign_from_unexpected<const _OtherErr&>)
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
+ if (__has_val_) {
+ __reinit_expected(__union_.__unex_, __union_.__val_, __un.error());
+ __has_val_ = false;
+ } else {
+ __union_.__unex_ = __un.error();
+ }
+ return *this;
+ }
+
+ template <class _OtherErr>
+ requires(__can_assign_from_unexpected<_OtherErr>)
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
+ if (__has_val_) {
+ __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error()));
+ __has_val_ = false;
+ } else {
+ __union_.__unex_ = std::move(__un.error());
+ }
+ return *this;
+ }
+
+ template <class... _Args>
+ 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(__union_.__val_));
+ } else {
+ std::destroy_at(std::addressof(__union_.__unex_));
+ __has_val_ = true;
+ }
+ return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
+ }
+
+ template <class _Up, class... _Args>
+ 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(__union_.__val_));
+ } else {
+ std::destroy_at(std::addressof(__union_.__unex_));
+ __has_val_ = true;
+ }
+ return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
+ }
+
+
+public:
+ // [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>))
+ {
+ auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
+ if constexpr (is_nothrow_move_constructible_v<_Err>) {
+ _Err __tmp(std::move(__with_err.__union_.__unex_));
+ std::destroy_at(std::addressof(__with_err.__union_.__unex_));
+ __transaction __trans([&] {
+ std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
+ });
+ std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
+ __trans.__complete();
+ std::destroy_at(std::addressof(__with_val.__union_.__val_));
+ std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp));
+ } else {
+ static_assert(is_nothrow_move_constructible_v<_Tp>,
+ "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
+ "that it can be reverted to the previous state in case an exception is thrown during swap.");
+ _Tp __tmp(std::move(__with_val.__union_.__val_));
+ std::destroy_at(std::addressof(__with_val.__union_.__val_));
+ __transaction __trans([&] { std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); });
+ std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
+ __trans.__complete();
+ std::destroy_at(std::addressof(__with_err.__union_.__unex_));
+ std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp));
+ }
+ __with_val.__has_val_ = false;
+ __with_err.__has_val_ = true;
+ };
+
+ if (__has_val_) {
+ if (__rhs.__has_val_) {
+ using std::swap;
+ swap(__union_.__val_, __rhs.__union_.__val_);
+ } else {
+ __swap_val_unex_impl(*this, __rhs);
+ }
+ } else {
+ if (__rhs.__has_val_) {
+ __swap_val_unex_impl(__rhs, *this);
+ } else {
+ using std::swap;
+ swap(__union_.__unex_, __rhs.__union_.__unex_);
+ }
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
+ noexcept(noexcept(__x.swap(__y)))
+ requires requires { __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::operator-> requires the expected to contain a value");
+ return std::addressof(__union_.__val_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
+ _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value");
+ return std::addressof(__union_.__val_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
+ _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
+ return __union_.__val_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
+ _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
+ return __union_.__val_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
+ _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
+ return std::move(__union_.__val_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
+ _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
+ return std::move(__union_.__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_) {
+ __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
+ }
+ return __union_.__val_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
+ if (!__has_val_) {
+ __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
+ }
+ return __union_.__val_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
+ if (!__has_val_) {
+ __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
+ }
+ return std::move(__union_.__val_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
+ if (!__has_val_) {
+ __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
+ }
+ return std::move(__union_.__val_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return __union_.__unex_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return __union_.__unex_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return std::move(__union_.__unex_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return std::move(__union_.__unex_);
+ }
+
+ template <class _Up>
+ _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_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
+ }
+
+ template <class _Up>
+ _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_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
+ }
+
+ // [expected.object.eq], equality operators
+ template <class _T2, class _E2>
+ requires(!is_void_v<_T2>)
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
+ if (__x.__has_val_ != __y.__has_val_) {
+ return false;
+ } else {
+ if (__x.__has_val_) {
+ return __x.__union_.__val_ == __y.__union_.__val_;
+ } else {
+ return __x.__union_.__unex_ == __y.__union_.__unex_;
+ }
+ }
+ }
+
+ template <class _T2>
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
+ return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
+ }
+
+ template <class _E2>
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
+ return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
+ }
+
+private:
+ struct __empty_t {};
+ // use named union because [[no_unique_address]] cannot be applied to an unnamed union
+ _LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
+ _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
+
+ _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+ requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+ = default;
+
+ // the expected's destructor handles this
+ _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+ requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+ {}
+
+ _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
+ } __union_;
+
+ bool __has_val_;
+};
+
+template <class _Tp, class _Err>
+ requires is_void_v<_Tp>
+class expected<_Tp, _Err> {
+ static_assert(__unexpected::__valid_unexpected<_Err>::value,
+ "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
+ "valid argument for unexpected<E> is ill-formed");
+
+ template <class, class>
+ friend class expected;
+
+ template <class _Up, class _OtherErr, class _OtherErrQual>
+ using __can_convert =
+ _And< is_void<_Up>,
+ is_constructible<_Err, _OtherErrQual>,
+ _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
+ _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
+ _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
+
+public:
+ using value_type = _Tp;
+ using error_type = _Err;
+ using unexpected_type = unexpected<_Err>;
+
+ template <class _Up>
+ 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>) // strengthened
+ 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(__union_.__unex_), __rhs.__union_.__unex_);
+ }
+ }
+
+ _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(__union_.__unex_), std::move(__rhs.__union_.__unex_));
+ }
+ }
+
+ template <class _Up, class _OtherErr>
+ requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
+ expected(const expected<_Up, _OtherErr>& __rhs)
+ noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
+ : __has_val_(__rhs.__has_val_) {
+ if (!__rhs.__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
+ }
+ }
+
+ template <class _Up, class _OtherErr>
+ requires __can_convert<_Up, _OtherErr, _OtherErr>::value
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
+ expected(expected<_Up, _OtherErr>&& __rhs)
+ noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
+ : __has_val_(__rhs.__has_val_) {
+ if (!__rhs.__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
+ }
+ }
+
+ template <class _OtherErr>
+ requires is_constructible_v<_Err, const _OtherErr&>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
+ expected(const unexpected<_OtherErr>& __unex)
+ noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), __unex.error());
+ }
+
+ template <class _OtherErr>
+ requires is_constructible_v<_Err, _OtherErr>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
+ expected(unexpected<_OtherErr>&& __unex)
+ noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
+
+ template <class... _Args>
+ requires is_constructible_v<_Err, _Args...>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
+ noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
+ }
+
+ template <class _Up, class... _Args>
+ 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...>) // strengthened
+ : __has_val_(false) {
+ std::construct_at(std::addressof(__union_.__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(__union_.__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>) // strengthened
+ requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
+ {
+ if (__has_val_) {
+ if (!__rhs.__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
+ __has_val_ = false;
+ }
+ } else {
+ if (__rhs.__has_val_) {
+ std::destroy_at(std::addressof(__union_.__unex_));
+ __has_val_ = true;
+ } else {
+ __union_.__unex_ = __rhs.__union_.__unex_;
+ }
+ }
+ 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_val_) {
+ if (!__rhs.__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
+ __has_val_ = false;
+ }
+ } else {
+ if (__rhs.__has_val_) {
+ std::destroy_at(std::addressof(__union_.__unex_));
+ __has_val_ = true;
+ } else {
+ __union_.__unex_ = std::move(__rhs.__union_.__unex_);
+ }
+ }
+ return *this;
+ }
+
+ template <class _OtherErr>
+ requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
+ if (__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), __un.error());
+ __has_val_ = false;
+ } else {
+ __union_.__unex_ = __un.error();
+ }
+ return *this;
+ }
+
+ template <class _OtherErr>
+ requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
+ if (__has_val_) {
+ std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error()));
+ __has_val_ = false;
+ } else {
+ __union_.__unex_ = std::move(__un.error());
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
+ if (!__has_val_) {
+ std::destroy_at(std::addressof(__union_.__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>)
+ {
+ auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
+ std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
+ std::destroy_at(std::addressof(__with_err.__union_.__unex_));
+ __with_val.__has_val_ = false;
+ __with_err.__has_val_ = true;
+ };
+
+ if (__has_val_) {
+ if (!__rhs.__has_val_) {
+ __swap_val_unex_impl(*this, __rhs);
+ }
+ } else {
+ if (__rhs.__has_val_) {
+ __swap_val_unex_impl(__rhs, *this);
+ } else {
+ using std::swap;
+ swap(__union_.__unex_, __rhs.__union_.__unex_);
+ }
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
+ noexcept(noexcept(__x.swap(__y)))
+ requires requires { __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::operator* requires the expected to contain a value");
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
+ if (!__has_val_) {
+ __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
+ if (!__has_val_) {
+ __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
+ }
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return __union_.__unex_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return __union_.__unex_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return std::move(__union_.__unex_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
+ _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
+ return std::move(__union_.__unex_);
+ }
+
+ // [expected.void.eq], equality operators
+ template <class _T2, class _E2>
+ requires is_void_v<_T2>
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
+ if (__x.__has_val_ != __y.__has_val_) {
+ return false;
+ } else {
+ return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
+ }
+ }
+
+ template <class _E2>
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
+ return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
+ }
+
+private:
+ struct __empty_t {};
+ // use named union because [[no_unique_address]] cannot be applied to an unnamed union
+ _LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
+ _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
+
+ _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+ requires(is_trivially_destructible_v<_Err>)
+ = default;
+
+ // the expected's destructor handles this
+ _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+ requires(!is_trivially_destructible_v<_Err>)
+ {}
+
+ _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
+ } __union_;
+
+ bool __has_val_;
+};
+
+_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
index 0000000000000..20bafc1107c0d
--- /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
index 0000000000000..22c307da82369
--- /dev/null
+++ b/libcxx/include/__expected/unexpected.h
@@ -0,0 +1,126 @@
+// -*- 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/conjunction.h>
+#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/negation.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 <initializer_list>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Err>
+class unexpected;
+
+namespace __unexpected {
+
+template <class _Tp>
+struct __is_unexpected : false_type {};
+
+template <class _Err>
+struct __is_unexpected<unexpected<_Err>> : true_type {};
+
+template <class _Tp>
+using __valid_unexpected = _BoolConstant< //
+ is_object_v<_Tp> && //
+ !is_array_v<_Tp> && //
+ !__is_unexpected<_Tp>::value && //
+ !is_const_v<_Tp> && //
+ !is_volatile_v<_Tp> //
+ >;
+
+} // namespace __unexpected
+
+template <class _Err>
+class unexpected {
+ static_assert(__unexpected::__valid_unexpected<_Err>::value,
+ "[expected.un.general] states a program that instantiates std::unexpected for a non-object type, an "
+ "array type, a specialization of unexpected, or a cv-qualified type is ill-formed.");
+
+public:
+ _LIBCPP_HIDE_FROM_ABI constexpr unexpected(const unexpected&) = default;
+ _LIBCPP_HIDE_FROM_ABI constexpr unexpected(unexpected&&) = default;
+
+ template <class _Error = _Err>
+ requires(!is_same_v<remove_cvref_t<_Error>, unexpected> && //
+ !is_same_v<remove_cvref_t<_Error>, in_place_t> && //
+ is_constructible_v<_Err, _Error>)
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(_Error&& __error) //
+ noexcept(is_nothrow_constructible_v<_Err, _Error>) // strengthened
+ : __unex_(std::forward<_Error>(__error)) {}
+
+ template <class... _Args>
+ 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...>) // strengthened
+ : __unex_(std::forward<_Args>(__args)...) {}
+
+ template <class _Up, class... _Args>
+ 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...>) // strengthened
+ : __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>, "unexpected::swap requires is_swappable_v<E> to be true");
+ using std::swap;
+ swap(__unex_, __other.__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);
+ }
+
+ template <class _Err2>
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) {
+ return __x.__unex_ == __y.__unex_;
+ }
+
+private:
+ _Err __unex_;
+};
+
+template <class _Err>
+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
index 8b4aff8563e9e..904d845f3327c 100644
--- a/libcxx/include/__type_traits/is_member_pointer.h
+++ b/libcxx/include/__type_traits/is_member_pointer.h
@@ -11,6 +11,7 @@
#include <__config>
#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_member_function_pointer.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
diff --git a/libcxx/include/__type_traits/is_scalar.h b/libcxx/include/__type_traits/is_scalar.h
index ee856dbbfec77..b4dc70b5d8357 100644
--- a/libcxx/include/__type_traits/is_scalar.h
+++ b/libcxx/include/__type_traits/is_scalar.h
@@ -14,6 +14,7 @@
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_enum.h>
#include <__type_traits/is_member_pointer.h>
+#include <__type_traits/is_null_pointer.h>
#include <__type_traits/is_pointer.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/__type_traits/is_void.h b/libcxx/include/__type_traits/is_void.h
index 1c7ad83f939df..d8ffdbd824461 100644
--- a/libcxx/include/__type_traits/is_void.h
+++ b/libcxx/include/__type_traits/is_void.h
@@ -11,6 +11,8 @@
#include <__config>
#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_cv.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
diff --git a/libcxx/include/expected b/libcxx/include/expected
new file mode 100644
index 0000000000000..486d0a21d0873
--- /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_EXPECTED
+#define _LIBCPP_EXPECTED
+
+/*
+ Header <expected> synopsis
+
+namespace std {
+ // [expected.unexpected], class template unexpected
+ template<class E> class unexpected;
+
+ // [expected.bad], class template bad_expected_access
+ template<class E> class bad_expected_access;
+
+ // [expected.bad.void], specialization for void
+ template<> class bad_expected_access<void>;
+
+ // 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 T, class E> class expected;
+
+ // [expected.void], partial specialization of expected for void types
+ template<class T, class E> requires is_void_v<T> class expected<T, E>;
+}
+
+*/
+
+#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 <version>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#endif // _LIBCPP_EXPECTED
+
diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp
index 07fc9985c7003..b2a018e30b2f9 100644
--- a/libcxx/include/libcxx.imp
+++ b/libcxx/include/libcxx.imp
@@ -24,6 +24,7 @@
{ include: [ "@<__concepts/.*>", "private", "<concepts>", "public" ] },
{ include: [ "@<__coroutine/.*>", "private", "<coroutine>", "public" ] },
{ include: [ "@<__debug_utils/.*>", "private", "<debug_utils>", "public" ] },
+ { include: [ "@<__expected/.*>", "private", "<expected>", "public" ] },
{ include: [ "@<__filesystem/.*>", "private", "<filesystem>", "public" ] },
{ include: [ "@<__format/.*>", "private", "<format>", "public" ] },
{ include: [ "@<__functional/.*>", "private", "<functional>", "public" ] },
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 4033d2fe412d4..e6481a823e9b3 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -785,6 +785,17 @@ module std [system] {
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
index 9443564b0466b..1d10392964445 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -82,6 +82,7 @@ __cpp_lib_erase_if 202002L <deque> <forward
__cpp_lib_exchange_function 201304L <utility>
__cpp_lib_execution 201902L <execution>
201603L // C++17
+__cpp_lib_expected 202202L <expected>
__cpp_lib_filesystem 201703L <filesystem>
__cpp_lib_format 202106L <format>
__cpp_lib_forward_like 202207L <utility>
@@ -390,6 +391,7 @@ __cpp_lib_void_t 201411L <type_traits>
# 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
index c3179c26e50db..690c792657c34 100644
--- a/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
+++ b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
@@ -306,464 +306,470 @@ int main(int, char**) { return 0; }
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_47
-#if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
-# include <filesystem>
+// RUN: %{build} -DTEST_46
+#if defined(TEST_46)
+# include <expected>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_49
-#if defined(TEST_49)
-# include <format>
+// RUN: %{build} -DTEST_48
+#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
+# include <filesystem>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_50
#if defined(TEST_50)
-# include <forward_list>
+# include <format>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_51
-#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
-# include <fstream>
+#if defined(TEST_51)
+# include <forward_list>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_52
-#if defined(TEST_52)
-# include <functional>
+#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
+# include <fstream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_53
-#if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS)
-# include <future>
+#if defined(TEST_53)
+# include <functional>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_54
-#if defined(TEST_54)
-# include <initializer_list>
+#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS)
+# include <future>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_56
-#if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <iomanip>
+// RUN: %{build} -DTEST_55
+#if defined(TEST_55)
+# include <initializer_list>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_57
#if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <ios>
+# include <iomanip>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_58
-#if defined(TEST_58)
-# include <iosfwd>
+#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+# include <ios>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_59
-#if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <iostream>
+#if defined(TEST_59)
+# include <iosfwd>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_60
#if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <istream>
+# include <iostream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_61
-#if defined(TEST_61)
-# include <iterator>
+#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+# include <istream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_62
-#if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS)
-# include <latch>
+#if defined(TEST_62)
+# include <iterator>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_63
-#if defined(TEST_63)
-# include <limits>
+#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS)
+# include <latch>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_65
-#if defined(TEST_65)
-# include <list>
+// RUN: %{build} -DTEST_64
+#if defined(TEST_64)
+# include <limits>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_66
-#if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <locale>
+#if defined(TEST_66)
+# include <list>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_68
-#if defined(TEST_68)
-# include <map>
+// RUN: %{build} -DTEST_67
+#if defined(TEST_67) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+# include <locale>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_70
-#if defined(TEST_70)
-# include <memory>
+// RUN: %{build} -DTEST_69
+#if defined(TEST_69)
+# include <map>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_71
#if defined(TEST_71)
-# include <memory_resource>
+# include <memory>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_72
-#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS)
-# include <mutex>
+#if defined(TEST_72)
+# include <memory_resource>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_73
-#if defined(TEST_73)
-# include <new>
+#if defined(TEST_73) && !defined(_LIBCPP_HAS_NO_THREADS)
+# include <mutex>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_74
#if defined(TEST_74)
-# include <numbers>
+# include <new>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_75
#if defined(TEST_75)
-# include <numeric>
+# include <numbers>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_76
#if defined(TEST_76)
-# include <optional>
+# include <numeric>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_77
-#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <ostream>
+#if defined(TEST_77)
+# include <optional>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_78
-#if defined(TEST_78)
-# include <queue>
+#if defined(TEST_78) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+# include <ostream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_79
#if defined(TEST_79)
-# include <random>
+# include <queue>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_80
#if defined(TEST_80)
-# include <ranges>
+# include <random>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_81
#if defined(TEST_81)
-# include <ratio>
+# include <ranges>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_82
-#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-# include <regex>
+#if defined(TEST_82)
+# include <ratio>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_83
-#if defined(TEST_83)
-# include <scoped_allocator>
+#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+# include <regex>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_84
-#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS)
-# include <semaphore>
+#if defined(TEST_84)
+# include <scoped_allocator>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_85
-#if defined(TEST_85)
+#if defined(TEST_85) && !defined(_LIBCPP_HAS_NO_THREADS)
+# include <semaphore>
+ using HandlerType = decltype(std::__libcpp_verbose_abort);
+#endif
+
+// RUN: %{build} -DTEST_86
+#if defined(TEST_86)
# include <set>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_87
-#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS)
+// RUN: %{build} -DTEST_88
+#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_THREADS)
# include <shared_mutex>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_88
-#if defined(TEST_88)
+// RUN: %{build} -DTEST_89
+#if defined(TEST_89)
# include <span>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_89
-#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+// RUN: %{build} -DTEST_90
+#if defined(TEST_90) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <sstream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_90
-#if defined(TEST_90)
+// RUN: %{build} -DTEST_91
+#if defined(TEST_91)
# include <stack>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_94
-#if defined(TEST_94)
+// RUN: %{build} -DTEST_95
+#if defined(TEST_95)
# include <stdexcept>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_98
-#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+// RUN: %{build} -DTEST_99
+#if defined(TEST_99) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <streambuf>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_99
-#if defined(TEST_99)
+// RUN: %{build} -DTEST_100
+#if defined(TEST_100)
# include <string>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_101
-#if defined(TEST_101)
+// RUN: %{build} -DTEST_102
+#if defined(TEST_102)
# include <string_view>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_102
-#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+// RUN: %{build} -DTEST_103
+#if defined(TEST_103) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <strstream>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_103
-#if defined(TEST_103)
+// RUN: %{build} -DTEST_104
+#if defined(TEST_104)
# include <system_error>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_105
-#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS)
-# include <thread>
- using HandlerType = decltype(std::__libcpp_verbose_abort);
-#endif
-
// RUN: %{build} -DTEST_106
-#if defined(TEST_106)
-# include <tuple>
+#if defined(TEST_106) && !defined(_LIBCPP_HAS_NO_THREADS)
+# include <thread>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_107
#if defined(TEST_107)
-# include <type_traits>
+# include <tuple>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_108
#if defined(TEST_108)
-# include <typeindex>
+# include <type_traits>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_109
#if defined(TEST_109)
-# include <typeinfo>
+# include <typeindex>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_111
-#if defined(TEST_111)
-# include <unordered_map>
+// RUN: %{build} -DTEST_110
+#if defined(TEST_110)
+# include <typeinfo>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_112
#if defined(TEST_112)
-# include <unordered_set>
+# include <unordered_map>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_113
#if defined(TEST_113)
-# include <utility>
+# include <unordered_set>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_114
#if defined(TEST_114)
-# include <valarray>
+# include <utility>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_115
#if defined(TEST_115)
-# include <variant>
+# include <valarray>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_116
#if defined(TEST_116)
-# include <vector>
+# include <variant>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_117
#if defined(TEST_117)
-# include <version>
+# include <vector>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
-// RUN: %{build} -DTEST_120
-#if defined(TEST_120) && __cplusplus >= 201103L
-# include <experimental/algorithm>
+// RUN: %{build} -DTEST_118
+#if defined(TEST_118)
+# include <version>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_121
-#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
-# include <experimental/coroutine>
+#if defined(TEST_121) && __cplusplus >= 201103L
+# include <experimental/algorithm>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_122
-#if defined(TEST_122) && __cplusplus >= 201103L
-# include <experimental/deque>
+#if defined(TEST_122) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
+# include <experimental/coroutine>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_123
#if defined(TEST_123) && __cplusplus >= 201103L
-# include <experimental/forward_list>
+# include <experimental/deque>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_124
#if defined(TEST_124) && __cplusplus >= 201103L
-# include <experimental/functional>
+# include <experimental/forward_list>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_125
#if defined(TEST_125) && __cplusplus >= 201103L
-# include <experimental/iterator>
+# include <experimental/functional>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_126
#if defined(TEST_126) && __cplusplus >= 201103L
-# include <experimental/list>
+# include <experimental/iterator>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_127
#if defined(TEST_127) && __cplusplus >= 201103L
-# include <experimental/map>
+# include <experimental/list>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_128
#if defined(TEST_128) && __cplusplus >= 201103L
-# include <experimental/memory_resource>
+# include <experimental/map>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_129
#if defined(TEST_129) && __cplusplus >= 201103L
-# include <experimental/propagate_const>
+# include <experimental/memory_resource>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_130
-#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
-# include <experimental/regex>
+#if defined(TEST_130) && __cplusplus >= 201103L
+# include <experimental/propagate_const>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_131
-#if defined(TEST_131) && __cplusplus >= 201103L
-# include <experimental/set>
+#if defined(TEST_131) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
+# include <experimental/regex>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_132
#if defined(TEST_132) && __cplusplus >= 201103L
-# include <experimental/simd>
+# include <experimental/set>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_133
#if defined(TEST_133) && __cplusplus >= 201103L
-# include <experimental/string>
+# include <experimental/simd>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_134
#if defined(TEST_134) && __cplusplus >= 201103L
-# include <experimental/type_traits>
+# include <experimental/string>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_135
#if defined(TEST_135) && __cplusplus >= 201103L
-# include <experimental/unordered_map>
+# include <experimental/type_traits>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_136
#if defined(TEST_136) && __cplusplus >= 201103L
-# include <experimental/unordered_set>
+# include <experimental/unordered_map>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_137
#if defined(TEST_137) && __cplusplus >= 201103L
-# include <experimental/utility>
+# include <experimental/unordered_set>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_138
#if defined(TEST_138) && __cplusplus >= 201103L
-# include <experimental/vector>
+# include <experimental/utility>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_139
-#if defined(TEST_139)
-# include <ext/hash_map>
+#if defined(TEST_139) && __cplusplus >= 201103L
+# include <experimental/vector>
using HandlerType = decltype(std::__libcpp_verbose_abort);
#endif
// RUN: %{build} -DTEST_140
#if defined(TEST_140)
+# include <ext/hash_map>
+ using HandlerType = decltype(std::__libcpp_verbose_abort);
+#endif
+
+// RUN: %{build} -DTEST_141
+#if defined(TEST_141)
# include <ext/hash_set>
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
index a3dcc57567b06..23c523ffc70d4 100644
--- a/libcxx/test/libcxx/clang_tidy.sh.cpp
+++ b/libcxx/test/libcxx/clang_tidy.sh.cpp
@@ -91,6 +91,7 @@ END-SCRIPT
#include <errno.h>
#include <exception>
#include <execution>
+#include <expected>
#include <fenv.h>
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
# include <filesystem>
diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp
index 4a55dcaeb777a..0bb3c9c0e5c0a 100644
--- a/libcxx/test/libcxx/double_include.sh.cpp
+++ b/libcxx/test/libcxx/double_include.sh.cpp
@@ -93,6 +93,7 @@ END-SCRIPT
#include <errno.h>
#include <exception>
#include <execution>
+#include <expected>
#include <fenv.h>
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
# include <filesystem>
diff --git a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp
index a21524bb133a2..f9a151dae5ddb 100644
--- 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();
TEST_MACROS();
#include <execution>
TEST_MACROS();
+#include <expected>
+TEST_MACROS();
#include <fenv.h>
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
index 7e80eed2da827..dfec3792e25df 100644
--- a/libcxx/test/libcxx/modules_include.sh.cpp
+++ b/libcxx/test/libcxx/modules_include.sh.cpp
@@ -235,382 +235,386 @@ END-SCRIPT
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_46
#if defined(TEST_46)
-#include <fenv.h>
+#include <expected>
#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 <filesystem>
+#if defined(TEST_47)
+#include <fenv.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_48
-#if defined(TEST_48)
-#include <float.h>
+#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
+#include <filesystem>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_49
#if defined(TEST_49)
-#include <format>
+#include <float.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_50
#if defined(TEST_50)
-#include <forward_list>
+#include <format>
#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) && !defined(_LIBCPP_HAS_NO_FSTREAM)
-#include <fstream>
+#if defined(TEST_51)
+#include <forward_list>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_52
-#if defined(TEST_52)
-#include <functional>
+#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
+#include <fstream>
#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 <future>
+#if defined(TEST_53)
+#include <functional>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_54
-#if defined(TEST_54)
-#include <initializer_list>
+#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <future>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_55
#if defined(TEST_55)
-#include <inttypes.h>
+#include <initializer_list>
#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 <iomanip>
+#if defined(TEST_56)
+#include <inttypes.h>
#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 <ios>
+#include <iomanip>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_58
-#if defined(TEST_58)
-#include <iosfwd>
+#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <ios>
#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 <iostream>
+#if defined(TEST_59)
+#include <iosfwd>
#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 <istream>
+#include <iostream>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_61
-#if defined(TEST_61)
-#include <iterator>
+#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <istream>
#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 <latch>
+#if defined(TEST_62)
+#include <iterator>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_63
-#if defined(TEST_63)
-#include <limits>
+#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <latch>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_64
#if defined(TEST_64)
-#include <limits.h>
+#include <limits>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_65
#if defined(TEST_65)
-#include <list>
+#include <limits.h>
#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 <locale>
+#if defined(TEST_66)
+#include <list>
#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 <locale.h>
+#include <locale>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_68
-#if defined(TEST_68)
-#include <map>
+#if defined(TEST_68) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <locale.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_69
#if defined(TEST_69)
-#include <math.h>
+#include <map>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_70
#if defined(TEST_70)
-#include <memory>
+#include <math.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_71
#if defined(TEST_71)
-#include <memory_resource>
+#include <memory>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_72
-#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS)
-#include <mutex>
+#if defined(TEST_72)
+#include <memory_resource>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_73
-#if defined(TEST_73)
-#include <new>
+#if defined(TEST_73) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <mutex>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_74
#if defined(TEST_74)
-#include <numbers>
+#include <new>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_75
#if defined(TEST_75)
-#include <numeric>
+#include <numbers>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_76
#if defined(TEST_76)
-#include <optional>
+#include <numeric>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_77
-#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#include <ostream>
+#if defined(TEST_77)
+#include <optional>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_78
-#if defined(TEST_78)
-#include <queue>
+#if defined(TEST_78) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <ostream>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_79
#if defined(TEST_79)
-#include <random>
+#include <queue>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_80
#if defined(TEST_80)
-#include <ranges>
+#include <random>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_81
#if defined(TEST_81)
-#include <ratio>
+#include <ranges>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_82
-#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#include <regex>
+#if defined(TEST_82)
+#include <ratio>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_83
-#if defined(TEST_83)
-#include <scoped_allocator>
+#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <regex>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_84
-#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS)
-#include <semaphore>
+#if defined(TEST_84)
+#include <scoped_allocator>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_85
-#if defined(TEST_85)
-#include <set>
+#if defined(TEST_85) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <semaphore>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_86
#if defined(TEST_86)
-#include <setjmp.h>
+#include <set>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_87
-#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS)
-#include <shared_mutex>
+#if defined(TEST_87)
+#include <setjmp.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_88
-#if defined(TEST_88)
-#include <span>
+#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <shared_mutex>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_89
-#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#include <sstream>
+#if defined(TEST_89)
+#include <span>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_90
-#if defined(TEST_90)
-#include <stack>
+#if defined(TEST_90) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <sstream>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_91
-#if defined(TEST_91) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)
-#include <stdatomic.h>
+#if defined(TEST_91)
+#include <stack>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_92
-#if defined(TEST_92)
-#include <stdbool.h>
+#if defined(TEST_92) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <stdatomic.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_93
#if defined(TEST_93)
-#include <stddef.h>
+#include <stdbool.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_94
#if defined(TEST_94)
-#include <stdexcept>
+#include <stddef.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_95
#if defined(TEST_95)
-#include <stdint.h>
+#include <stdexcept>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_96
#if defined(TEST_96)
-#include <stdio.h>
+#include <stdint.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_97
#if defined(TEST_97)
-#include <stdlib.h>
+#include <stdio.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_98
-#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#include <streambuf>
+#if defined(TEST_98)
+#include <stdlib.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_99
-#if defined(TEST_99)
-#include <string>
+#if defined(TEST_99) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <streambuf>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_100
#if defined(TEST_100)
-#include <string.h>
+#include <string>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_101
#if defined(TEST_101)
-#include <string_view>
+#include <string.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_102
-#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#include <strstream>
+#if defined(TEST_102)
+#include <string_view>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_103
-#if defined(TEST_103)
-#include <system_error>
+#if defined(TEST_103) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#include <strstream>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_104
#if defined(TEST_104)
-#include <tgmath.h>
+#include <system_error>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_105
-#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS)
-#include <thread>
+#if defined(TEST_105)
+#include <tgmath.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_106
-#if defined(TEST_106)
-#include <tuple>
+#if defined(TEST_106) && !defined(_LIBCPP_HAS_NO_THREADS)
+#include <thread>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_107
#if defined(TEST_107)
-#include <type_traits>
+#include <tuple>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_108
#if defined(TEST_108)
-#include <typeindex>
+#include <type_traits>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_109
#if defined(TEST_109)
-#include <typeinfo>
+#include <typeindex>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_110
#if defined(TEST_110)
-#include <uchar.h>
+#include <typeinfo>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_111
#if defined(TEST_111)
-#include <unordered_map>
+#include <uchar.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_112
#if defined(TEST_112)
-#include <unordered_set>
+#include <unordered_map>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_113
#if defined(TEST_113)
-#include <utility>
+#include <unordered_set>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_114
#if defined(TEST_114)
-#include <valarray>
+#include <utility>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_115
#if defined(TEST_115)
-#include <variant>
+#include <valarray>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_116
#if defined(TEST_116)
-#include <vector>
+#include <variant>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_117
#if defined(TEST_117)
-#include <version>
+#include <vector>
#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 <wchar.h>
+#if defined(TEST_118)
+#include <version>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_119
#if defined(TEST_119) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
-#include <wctype.h>
+#include <wchar.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_120
-#if defined(TEST_120) && __cplusplus >= 201103L
-#include <experimental/algorithm>
+#if defined(TEST_120) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
+#include <wctype.h>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_121
-#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
-#include <experimental/coroutine>
+#if defined(TEST_121) && __cplusplus >= 201103L
+#include <experimental/algorithm>
#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 <experimental/deque>
+#if defined(TEST_122) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
+#include <experimental/coroutine>
#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 <experimental/forward_list>
+#include <experimental/deque>
#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 <experimental/functional>
+#include <experimental/forward_list>
#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 <experimental/iterator>
+#include <experimental/functional>
#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 <experimental/list>
+#include <experimental/iterator>
#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 <experimental/map>
+#include <experimental/list>
#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 <experimental/memory_resource>
+#include <experimental/map>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_129
#if defined(TEST_129) && __cplusplus >= 201103L
-#include <experimental/propagate_const>
+#include <experimental/memory_resource>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_130
-#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
-#include <experimental/regex>
+#if defined(TEST_130) && __cplusplus >= 201103L
+#include <experimental/propagate_const>
#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 <experimental/set>
+#if defined(TEST_131) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
+#include <experimental/regex>
#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 <experimental/simd>
+#include <experimental/set>
#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 <experimental/string>
+#include <experimental/simd>
#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 <experimental/type_traits>
+#include <experimental/string>
#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 <experimental/unordered_map>
+#include <experimental/type_traits>
#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 <experimental/unordered_set>
+#include <experimental/unordered_map>
#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 <experimental/utility>
+#include <experimental/unordered_set>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_138
#if defined(TEST_138) && __cplusplus >= 201103L
-#include <experimental/vector>
+#include <experimental/utility>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_139
-#if defined(TEST_139)
-#include <ext/hash_map>
+#if defined(TEST_139) && __cplusplus >= 201103L
+#include <experimental/vector>
#endif
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_140
#if defined(TEST_140)
+#include <ext/hash_map>
+#endif
+// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_141
+#if defined(TEST_141)
#include <ext/hash_set>
#endif
// GENERATED-MARKER
diff --git a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
index 43845ea042b43..d2d875f955b76 100644
--- a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
+++ b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
@@ -212,6 +212,7 @@ END-SCRIPT
#include <errno.h>
#include <exception>
#include <execution>
+#include <expected>
#include <fenv.h>
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
# include <filesystem>
diff --git a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
index 68e303bfbaa08..32bd4e66f8183 100644
--- a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
+++ b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
@@ -90,6 +90,7 @@ END-SCRIPT
#include <errno.h>
#include <exception>
#include <execution>
+#include <expected>
#include <fenv.h>
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
# include <filesystem>
diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp
index 075b5dde3b3c9..55a0c268a579c 100644
--- a/libcxx/test/libcxx/private_headers.verify.cpp
+++ b/libcxx/test/libcxx/private_headers.verify.cpp
@@ -301,6 +301,10 @@ END-SCRIPT
#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
index 7733a42b7459a..341debc713b2f 100644
--- a/libcxx/test/libcxx/transitive_includes.sh.cpp
+++ b/libcxx/test/libcxx/transitive_includes.sh.cpp
@@ -249,312 +249,316 @@ END-SCRIPT
#if defined(TEST_45)
#include <execution>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_47 2> %t/header.filesystem
-#if defined(TEST_47)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_46 2> %t/header.expected
+#if defined(TEST_46)
+#include <expected>
+#endif
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_48 2> %t/header.filesystem
+#if defined(TEST_48)
#include <filesystem>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_49 2> %t/header.format
-#if defined(TEST_49)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2> %t/header.format
+#if defined(TEST_50)
#include <format>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2> %t/header.forward_list
-#if defined(TEST_50)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2> %t/header.forward_list
+#if defined(TEST_51)
#include <forward_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2> %t/header.fstream
-#if defined(TEST_51)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2> %t/header.fstream
+#if defined(TEST_52)
#include <fstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2> %t/header.functional
-#if defined(TEST_52)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2> %t/header.functional
+#if defined(TEST_53)
#include <functional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2> %t/header.future
-#if defined(TEST_53)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2> %t/header.future
+#if defined(TEST_54)
#include <future>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2> %t/header.initializer_list
-#if defined(TEST_54)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_55 2> %t/header.initializer_list
+#if defined(TEST_55)
#include <initializer_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_56 2> %t/header.iomanip
-#if defined(TEST_56)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2> %t/header.iomanip
+#if defined(TEST_57)
#include <iomanip>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2> %t/header.ios
-#if defined(TEST_57)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2> %t/header.ios
+#if defined(TEST_58)
#include <ios>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2> %t/header.iosfwd
-#if defined(TEST_58)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2> %t/header.iosfwd
+#if defined(TEST_59)
#include <iosfwd>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2> %t/header.iostream
-#if defined(TEST_59)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2> %t/header.iostream
+#if defined(TEST_60)
#include <iostream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2> %t/header.istream
-#if defined(TEST_60)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2> %t/header.istream
+#if defined(TEST_61)
#include <istream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2> %t/header.iterator
-#if defined(TEST_61)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2> %t/header.iterator
+#if defined(TEST_62)
#include <iterator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2> %t/header.latch
-#if defined(TEST_62)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2> %t/header.latch
+#if defined(TEST_63)
#include <latch>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2> %t/header.limits
-#if defined(TEST_63)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_64 2> %t/header.limits
+#if defined(TEST_64)
#include <limits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_65 2> %t/header.list
-#if defined(TEST_65)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2> %t/header.list
+#if defined(TEST_66)
#include <list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2> %t/header.locale
-#if defined(TEST_66)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_67 2> %t/header.locale
+#if defined(TEST_67)
#include <locale>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_68 2> %t/header.map
-#if defined(TEST_68)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_69 2> %t/header.map
+#if defined(TEST_69)
#include <map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_70 2> %t/header.memory
-#if defined(TEST_70)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2> %t/header.memory
+#if defined(TEST_71)
#include <memory>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2> %t/header.memory_resource
-#if defined(TEST_71)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2> %t/header.memory_resource
+#if defined(TEST_72)
#include <memory_resource>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2> %t/header.mutex
-#if defined(TEST_72)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2> %t/header.mutex
+#if defined(TEST_73)
#include <mutex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2> %t/header.new
-#if defined(TEST_73)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2> %t/header.new
+#if defined(TEST_74)
#include <new>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2> %t/header.numbers
-#if defined(TEST_74)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2> %t/header.numbers
+#if defined(TEST_75)
#include <numbers>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2> %t/header.numeric
-#if defined(TEST_75)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2> %t/header.numeric
+#if defined(TEST_76)
#include <numeric>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2> %t/header.optional
-#if defined(TEST_76)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2> %t/header.optional
+#if defined(TEST_77)
#include <optional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2> %t/header.ostream
-#if defined(TEST_77)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2> %t/header.ostream
+#if defined(TEST_78)
#include <ostream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2> %t/header.queue
-#if defined(TEST_78)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2> %t/header.queue
+#if defined(TEST_79)
#include <queue>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2> %t/header.random
-#if defined(TEST_79)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2> %t/header.random
+#if defined(TEST_80)
#include <random>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2> %t/header.ranges
-#if defined(TEST_80)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2> %t/header.ranges
+#if defined(TEST_81)
#include <ranges>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2> %t/header.ratio
-#if defined(TEST_81)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2> %t/header.ratio
+#if defined(TEST_82)
#include <ratio>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2> %t/header.regex
-#if defined(TEST_82)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2> %t/header.regex
+#if defined(TEST_83)
#include <regex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2> %t/header.scoped_allocator
-#if defined(TEST_83)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2> %t/header.scoped_allocator
+#if defined(TEST_84)
#include <scoped_allocator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2> %t/header.semaphore
-#if defined(TEST_84)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_85 2> %t/header.semaphore
+#if defined(TEST_85)
#include <semaphore>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_85 2> %t/header.set
-#if defined(TEST_85)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_86 2> %t/header.set
+#if defined(TEST_86)
#include <set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_87 2> %t/header.shared_mutex
-#if defined(TEST_87)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2> %t/header.shared_mutex
+#if defined(TEST_88)
#include <shared_mutex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2> %t/header.span
-#if defined(TEST_88)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2> %t/header.span
+#if defined(TEST_89)
#include <span>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2> %t/header.sstream
-#if defined(TEST_89)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_90 2> %t/header.sstream
+#if defined(TEST_90)
#include <sstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_90 2> %t/header.stack
-#if defined(TEST_90)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_91 2> %t/header.stack
+#if defined(TEST_91)
#include <stack>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_94 2> %t/header.stdexcept
-#if defined(TEST_94)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_95 2> %t/header.stdexcept
+#if defined(TEST_95)
#include <stdexcept>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_98 2> %t/header.streambuf
-#if defined(TEST_98)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_99 2> %t/header.streambuf
+#if defined(TEST_99)
#include <streambuf>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_99 2> %t/header.string
-#if defined(TEST_99)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_100 2> %t/header.string
+#if defined(TEST_100)
#include <string>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_101 2> %t/header.string_view
-#if defined(TEST_101)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2> %t/header.string_view
+#if defined(TEST_102)
#include <string_view>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2> %t/header.strstream
-#if defined(TEST_102)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_103 2> %t/header.strstream
+#if defined(TEST_103)
#include <strstream>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_103 2> %t/header.system_error
-#if defined(TEST_103)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_104 2> %t/header.system_error
+#if defined(TEST_104)
#include <system_error>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_105 2> %t/header.thread
-#if defined(TEST_105)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2> %t/header.thread
+#if defined(TEST_106)
#include <thread>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2> %t/header.tuple
-#if defined(TEST_106)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2> %t/header.tuple
+#if defined(TEST_107)
#include <tuple>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2> %t/header.type_traits
-#if defined(TEST_107)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2> %t/header.type_traits
+#if defined(TEST_108)
#include <type_traits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2> %t/header.typeindex
-#if defined(TEST_108)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_109 2> %t/header.typeindex
+#if defined(TEST_109)
#include <typeindex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_109 2> %t/header.typeinfo
-#if defined(TEST_109)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_110 2> %t/header.typeinfo
+#if defined(TEST_110)
#include <typeinfo>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_111 2> %t/header.unordered_map
-#if defined(TEST_111)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2> %t/header.unordered_map
+#if defined(TEST_112)
#include <unordered_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2> %t/header.unordered_set
-#if defined(TEST_112)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2> %t/header.unordered_set
+#if defined(TEST_113)
#include <unordered_set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2> %t/header.utility
-#if defined(TEST_113)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2> %t/header.utility
+#if defined(TEST_114)
#include <utility>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2> %t/header.valarray
-#if defined(TEST_114)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2> %t/header.valarray
+#if defined(TEST_115)
#include <valarray>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2> %t/header.variant
-#if defined(TEST_115)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2> %t/header.variant
+#if defined(TEST_116)
#include <variant>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2> %t/header.vector
-#if defined(TEST_116)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_117 2> %t/header.vector
+#if defined(TEST_117)
#include <vector>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_117 2> %t/header.version
-#if defined(TEST_117)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_118 2> %t/header.version
+#if defined(TEST_118)
#include <version>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_120 2> %t/header.experimental_algorithm
-#if defined(TEST_120)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2> %t/header.experimental_algorithm
+#if defined(TEST_121)
#include <experimental/algorithm>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2> %t/header.experimental_coroutine
-#if defined(TEST_121)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2> %t/header.experimental_coroutine
+#if defined(TEST_122)
#include <experimental/coroutine>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2> %t/header.experimental_deque
-#if defined(TEST_122)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2> %t/header.experimental_deque
+#if defined(TEST_123)
#include <experimental/deque>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2> %t/header.experimental_forward_list
-#if defined(TEST_123)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2> %t/header.experimental_forward_list
+#if defined(TEST_124)
#include <experimental/forward_list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2> %t/header.experimental_functional
-#if defined(TEST_124)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2> %t/header.experimental_functional
+#if defined(TEST_125)
#include <experimental/functional>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2> %t/header.experimental_iterator
-#if defined(TEST_125)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2> %t/header.experimental_iterator
+#if defined(TEST_126)
#include <experimental/iterator>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2> %t/header.experimental_list
-#if defined(TEST_126)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2> %t/header.experimental_list
+#if defined(TEST_127)
#include <experimental/list>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2> %t/header.experimental_map
-#if defined(TEST_127)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2> %t/header.experimental_map
+#if defined(TEST_128)
#include <experimental/map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2> %t/header.experimental_memory_resource
-#if defined(TEST_128)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2> %t/header.experimental_memory_resource
+#if defined(TEST_129)
#include <experimental/memory_resource>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2> %t/header.experimental_propagate_const
-#if defined(TEST_129)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2> %t/header.experimental_propagate_const
+#if defined(TEST_130)
#include <experimental/propagate_const>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2> %t/header.experimental_regex
-#if defined(TEST_130)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2> %t/header.experimental_regex
+#if defined(TEST_131)
#include <experimental/regex>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2> %t/header.experimental_set
-#if defined(TEST_131)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2> %t/header.experimental_set
+#if defined(TEST_132)
#include <experimental/set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2> %t/header.experimental_simd
-#if defined(TEST_132)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2> %t/header.experimental_simd
+#if defined(TEST_133)
#include <experimental/simd>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2> %t/header.experimental_string
-#if defined(TEST_133)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2> %t/header.experimental_string
+#if defined(TEST_134)
#include <experimental/string>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2> %t/header.experimental_type_traits
-#if defined(TEST_134)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2> %t/header.experimental_type_traits
+#if defined(TEST_135)
#include <experimental/type_traits>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2> %t/header.experimental_unordered_map
-#if defined(TEST_135)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2> %t/header.experimental_unordered_map
+#if defined(TEST_136)
#include <experimental/unordered_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2> %t/header.experimental_unordered_set
-#if defined(TEST_136)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2> %t/header.experimental_unordered_set
+#if defined(TEST_137)
#include <experimental/unordered_set>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2> %t/header.experimental_utility
-#if defined(TEST_137)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2> %t/header.experimental_utility
+#if defined(TEST_138)
#include <experimental/utility>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2> %t/header.experimental_vector
-#if defined(TEST_138)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2> %t/header.experimental_vector
+#if defined(TEST_139)
#include <experimental/vector>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2> %t/header.ext_hash_map
-#if defined(TEST_139)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_140 2> %t/header.ext_hash_map
+#if defined(TEST_140)
#include <ext/hash_map>
#endif
-// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_140 2> %t/header.ext_hash_set
-#if defined(TEST_140)
+// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_141 2> %t/header.ext_hash_set
+#if defined(TEST_141)
#include <ext/hash_set>
#endif
// RUN: %{python} %S/transitive_includes_to_csv.py %t > %t/transitive_includes.csv
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index c3eff22f1fee6..4064fb77c8132 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -202,6 +202,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 0ab039f113f14..aa6fc0c95e169 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -202,6 +202,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 491b28707c291..e2ef4a2d8d8f3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -202,6 +202,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 491b28707c291..e2ef4a2d8d8f3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -202,6 +202,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 1f3798909e533..91a829ab3ed93 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -214,6 +214,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
index bcc949bc4233a..d2b83e42cb449 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -168,6 +168,13 @@ exception cstdlib
exception type_traits
exception version
execution version
+expected cstddef
+expected cstdlib
+expected exception
+expected initializer_list
+expected new
+expected type_traits
+expected version
experimental/algorithm algorithm
experimental/algorithm cstddef
experimental/algorithm type_traits
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/assert.arrow.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.arrow.pass.cpp
new file mode 100644
index 0000000000000..82fb35a022785
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.arrow.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// constexpr const T* operator->() const noexcept;
+// constexpr T* operator->() noexcept;
+//
+// Preconditions: has_value() is true.
+
+#include <expected>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::expected<int, int> e{std::unexpect, 5};
+ TEST_LIBCPP_ASSERT_FAILURE(e.operator->(), "expected::operator-> requires the expected to contain a value");
+ TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).operator->(), "expected::operator-> requires the expected to contain a value");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/assert.deref.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.deref.pass.cpp
new file mode 100644
index 0000000000000..d1ab32159d05a
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.deref.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// constexpr const T& operator*() const & noexcept;
+// constexpr T& operator*() & noexcept;
+// constexpr T&& operator*() && noexcept;
+// constexpr const T&& operator*() const && noexcept;
+//
+// Preconditions: has_value() is true.
+
+#include <expected>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::expected<int, int> e{std::unexpect, 5};
+ TEST_LIBCPP_ASSERT_FAILURE(*e, "expected::operator* requires the expected to contain a value");
+ TEST_LIBCPP_ASSERT_FAILURE(*std::as_const(e), "expected::operator* requires the expected to contain a value");
+ TEST_LIBCPP_ASSERT_FAILURE(*std::move(e), "expected::operator* requires the expected to contain a value");
+ TEST_LIBCPP_ASSERT_FAILURE(*std::move(std::as_const(e)), "expected::operator* requires the expected to contain a value");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/assert.error.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.error.pass.cpp
new file mode 100644
index 0000000000000..814b47d1c756f
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/assert.error.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// constexpr const E& error() const & noexcept;
+// constexpr E& error() & noexcept;
+// constexpr E&& error() && noexcept;
+// constexpr const E&& error() const && noexcept;
+//
+// Preconditions: has_value() is false.
+
+#include <expected>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::expected<int, int> e{std::in_place, 5};
+ TEST_LIBCPP_ASSERT_FAILURE(e.error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::move(e).error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::move(std::as_const(e)).error(), "expected::error requires the expected to contain an error");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
new file mode 100644
index 0000000000000..3fd047df7134c
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.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
+
+// clang-cl and cl currently don't support [[no_unique_address]]
+// XFAIL: msvc
+
+// test [[no_unique_address]] is applied to the union
+
+#include <expected>
+
+struct Empty {};
+
+static_assert(sizeof(std::expected<Empty, Empty>) == sizeof(bool));
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/noexcept.extension.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/noexcept.extension.compile.pass.cpp
new file mode 100644
index 0000000000000..643bf4d1f2a8f
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/noexcept.extension.compile.pass.cpp
@@ -0,0 +1,124 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// test libc++ noexcept extensions on operations of std::expected<T, E>
+
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../types.h"
+
+// expected();
+static_assert(std::is_nothrow_default_constructible_v<std::expected<int, int>>);
+static_assert(!std::is_nothrow_default_constructible_v<std::expected<DefaultMayThrow, int>>);
+
+// expected(const expected&)
+static_assert(std::is_nothrow_copy_constructible_v<std::expected<int, int>>);
+static_assert(!std::is_nothrow_copy_constructible_v<std::expected<CopyMayThrow, int>>);
+static_assert(!std::is_nothrow_copy_constructible_v<std::expected<int, CopyMayThrow>>);
+
+// expected(const expected<OtherT, OtherE>&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<long, long>,
+ const std::expected<int, int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromCopyIntMayThrow, long>,
+ const std::expected<int, int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<long, ConvertFromCopyIntMayThrow>,
+ const std::expected<int, int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromCopyIntMayThrow, ConvertFromCopyIntMayThrow>, //
+ const std::expected<int, int>&>);
+
+// expected(expected<OtherT, OtherE>&&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<long, long>,
+ std::expected<int, int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromMoveIntMayThrow, long>,
+ std::expected<int, int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<long, ConvertFromMoveIntMayThrow>,
+ std::expected<int, int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromMoveIntMayThrow, ConvertFromMoveIntMayThrow>, //
+ std::expected<int, int>&&>);
+
+// expected(U&&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, int>,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromCopyIntMayThrow, int>,
+ const int&>);
+
+// expected(const unexpected<OtherE>&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, long>,
+ const std::unexpected<int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<int, ConvertFromCopyIntMayThrow>,
+ const std::unexpected<int>&>);
+
+// expected(unexpected<OtherE>&&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, long>,
+ std::unexpected<int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<int, ConvertFromMoveIntMayThrow>,
+ std::unexpected<int>&&>);
+
+// expected(in_place_t, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, int>,
+ std::in_place_t,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromCopyIntMayThrow, int>,
+ std::in_place_t,
+ const int&>);
+
+// expected(in_place_t, initializer_list<U>, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromInitializerListNoexcept, int>,
+ std::in_place_t,
+ std::initializer_list<int>>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<ConvertFromInitializerListMayThrow, int>,
+ std::in_place_t,
+ std::initializer_list<int>>);
+
+// expected(unexpect_t, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, int>,
+ std::unexpect_t,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<int, ConvertFromCopyIntMayThrow>,
+ std::unexpect_t,
+ const int&>);
+
+// expected(unexpect_t, initializer_list<U>, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<int, ConvertFromInitializerListNoexcept>,
+ std::unexpect_t,
+ std::initializer_list<int>>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<int, ConvertFromInitializerListMayThrow>,
+ std::unexpect_t,
+ std::initializer_list<int>>);
+
+// expected& operator=(const expected&)
+static_assert(std::is_nothrow_copy_assignable_v<std::expected<int, int>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<CopyConstructMayThrow, int>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<CopyAssignMayThrow, int>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<int, CopyConstructMayThrow>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<int, CopyAssignMayThrow>>);
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/value_or.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/value_or.mandates.verify.cpp
new file mode 100644
index 0000000000000..11d52aeeea455
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/value_or.mandates.verify.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
+
+// Test the mandates
+// template<class U> constexpr T value_or(U&& v) const &;
+// Mandates: is_copy_constructible_v<T> is true and is_convertible_v<U, T> is true.
+
+// template<class U> constexpr T value_or(U&& v) &&;
+// Mandates: is_move_constructible_v<T> is true and is_convertible_v<U, T> is true.
+
+#include <expected>
+#include <utility>
+
+struct NonCopyable {
+ NonCopyable(int) {}
+ NonCopyable(const NonCopyable&) = delete;
+};
+
+struct NonMovable {
+ NonMovable(int) {}
+ NonMovable(NonMovable&&) = delete;
+};
+
+struct NotConvertibleFromInt {};
+
+void test() {
+ // const & overload
+ // !is_copy_constructible_v<T>,
+ {
+ const std::expected<NonCopyable, int> f1{5};
+ f1.value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NonCopyable, int>::value_or<int>' requested here}}
+ // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}value_type has to be copy constructible}}
+ }
+
+ // const & overload
+ // !is_convertible_v<U, T>
+ {
+ const std::expected<NotConvertibleFromInt, int> f1{std::in_place};
+ f1.value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NotConvertibleFromInt, int>::value_or<int>' requested here}}
+ //expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}argument has to be convertible to value_type}}
+ }
+
+ // && overload
+ // !is_move_constructible_v<T>,
+ {
+ std::expected<NonMovable, int> f1{5};
+ std::move(f1).value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NonMovable, int>::value_or<int>' requested here}}
+ //expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}value_type has to be move constructible}}
+ }
+
+ // && overload
+ // !is_convertible_v<U, T>
+ {
+ std::expected<NotConvertibleFromInt, int> f1{std::in_place};
+ std::move(f1).value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NotConvertibleFromInt, int>::value_or<int>' requested here}}
+ //expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}argument has to be convertible to value_type}}
+ }
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.unexpected/class.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.unexpected/class.mandates.verify.cpp
new file mode 100644
index 0000000000000..65446725ce485
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.unexpected/class.mandates.verify.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
+
+// A program that instantiates the definition of unexpected for a non-object type, an array type, a specialization of unexpected, or a cv-qualified type is ill-formed.
+
+#include <expected>
+
+
+
+template class std::unexpected<int[2]>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
+
+template class std::unexpected<const int>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
+
+template class std::unexpected<int&>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
+
+template class std::unexpected<std::unexpected<int>>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
+
+template class std::unexpected<volatile int>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.unexpected/noexcept.extension.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.unexpected/noexcept.extension.compile.pass.cpp
new file mode 100644
index 0000000000000..867b90e8bc728
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.unexpected/noexcept.extension.compile.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// test libc++ noexcept extensions on operations of std::unexpected<E>
+
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../types.h"
+
+// unexpected(Error&&);
+static_assert(std::is_nothrow_constructible_v< //
+ std::unexpected<int>,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::unexpected<ConvertFromCopyIntMayThrow>,
+ const int&>);
+
+
+// unexpected(in_place_t, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::unexpected<int>,
+ std::in_place_t,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::unexpected<ConvertFromCopyIntMayThrow>,
+ std::in_place_t,
+ const int&>);
+
+// unexpected(in_place_t, initializer_list<U>, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::unexpected<ConvertFromInitializerListNoexcept>,
+ std::in_place_t,
+ std::initializer_list<int>>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::unexpected<ConvertFromInitializerListMayThrow>,
+ std::in_place_t,
+ std::initializer_list<int>>);
diff --git a/libcxx/test/libcxx/utilities/expected/expected.unexpected/swap.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.unexpected/swap.mandates.verify.cpp
new file mode 100644
index 0000000000000..2ac0644430d05
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.unexpected/swap.mandates.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
+
+// Test the mandates
+// constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);
+// Mandates: is_swappable_v<E> is true.
+
+#include <expected>
+
+struct Foo {};
+
+void swap(Foo&, Foo&) = delete;
+
+void test() {
+ std::unexpected<Foo> f1{Foo{}};
+ f1.swap(f1); // expected-note{{in instantiation of member function 'std::unexpected<Foo>::swap' requested here}}
+ // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}unexpected::swap requires is_swappable_v<E> to be true}}
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/assert.deref.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/assert.deref.pass.cpp
new file mode 100644
index 0000000000000..d75f15d91be98
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/assert.deref.pass.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// constexpr void operator*() const noexcept;
+//
+// Preconditions: has_value() is true.
+
+#include <expected>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::expected<void, int> e{std::unexpect, 5};
+ TEST_LIBCPP_ASSERT_FAILURE(*e, "expected::operator* requires the expected to contain a value");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/assert.error.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/assert.error.pass.cpp
new file mode 100644
index 0000000000000..1e20cc54be4b3
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/assert.error.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
+
+// constexpr const E& error() const & noexcept;
+// constexpr E& error() & noexcept;
+// constexpr E&& error() && noexcept;
+// constexpr const E&& error() const && noexcept;
+//
+// Preconditions: has_value() is false.
+
+#include <expected>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::expected<void, int> e{std::in_place};
+ TEST_LIBCPP_ASSERT_FAILURE(e.error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::move(e).error(), "expected::error requires the expected to contain an error");
+ TEST_LIBCPP_ASSERT_FAILURE(std::move(std::as_const(e)).error(), "expected::error requires the expected to contain an error");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
new file mode 100644
index 0000000000000..1ad2aa125c295
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.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
+
+// clang-cl and cl currently don't support [[no_unique_address]]
+// XFAIL: msvc
+
+// test [[no_unique_address]] is applied to the union
+
+#include <expected>
+
+struct Empty {};
+
+static_assert(sizeof(std::expected<void, Empty>) == sizeof(bool));
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/noexcept.extension.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/noexcept.extension.compile.pass.cpp
new file mode 100644
index 0000000000000..3ecbc0abec059
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/noexcept.extension.compile.pass.cpp
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// test libc++ noexcept extensions on operations of std::expected<void, E>
+
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../types.h"
+
+// expected(const expected&)
+static_assert(std::is_nothrow_copy_constructible_v<std::expected<void, int>>);
+static_assert(!std::is_nothrow_copy_constructible_v<std::expected<void, CopyMayThrow>>);
+
+
+// expected(const expected<OtherT, OtherE>&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, long>,
+ const std::expected<void, int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromCopyIntMayThrow>,
+ const std::expected<void, int>&>);
+
+
+// expected(expected<OtherT, OtherE>&&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, long>,
+ std::expected<void, int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromMoveIntMayThrow>,
+ std::expected<void, int>&&>);
+
+// expected(const unexpected<OtherE>&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, long>,
+ const std::unexpected<int>&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromCopyIntMayThrow>,
+ const std::unexpected<int>&>);
+
+// expected(unexpected<OtherE>&&)
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, long>,
+ std::unexpected<int>&&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromMoveIntMayThrow>,
+ std::unexpected<int>&&>);
+
+
+// expected(unexpect_t, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, int>,
+ std::unexpect_t,
+ const int&>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromCopyIntMayThrow>,
+ std::unexpect_t,
+ const int&>);
+
+// expected(unexpect_t, initializer_list<U>, _Args&&...);
+static_assert(std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromInitializerListNoexcept>,
+ std::unexpect_t,
+ std::initializer_list<int>>);
+static_assert(!std::is_nothrow_constructible_v< //
+ std::expected<void, ConvertFromInitializerListMayThrow>,
+ std::unexpect_t,
+ std::initializer_list<int>>);
+
+// expected& operator=(const expected&)
+static_assert(std::is_nothrow_copy_assignable_v<std::expected<void, int>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<void, CopyConstructMayThrow>>);
+static_assert(!std::is_nothrow_copy_assignable_v<std::expected<void, CopyAssignMayThrow>>);
diff --git a/libcxx/test/libcxx/utilities/expected/types.h b/libcxx/test/libcxx/utilities/expected/types.h
new file mode 100644
index 0000000000000..52b4e6e6c1ba0
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/expected/types.h
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_LIBCXX_UTILITIES_EXPECTED_TYPES_H
+#define TEST_LIBCXX_UTILITIES_EXPECTED_TYPES_H
+
+#include <initializer_list>
+
+struct DefaultMayThrow {
+ DefaultMayThrow();
+};
+
+struct CopyMayThrow {
+ CopyMayThrow(const CopyMayThrow&);
+};
+
+struct ConvertFromCopyIntMayThrow {
+ ConvertFromCopyIntMayThrow(const int&);
+ ConvertFromCopyIntMayThrow(int&&) noexcept;
+};
+
+struct ConvertFromMoveIntMayThrow {
+ ConvertFromMoveIntMayThrow(const int&) noexcept;
+ ConvertFromMoveIntMayThrow(int&&);
+};
+
+struct ConvertFromInitializerListNoexcept {
+ ConvertFromInitializerListNoexcept(std::initializer_list<int>) noexcept;
+};
+
+struct ConvertFromInitializerListMayThrow {
+ ConvertFromInitializerListMayThrow(std::initializer_list<int>);
+};
+
+struct CopyConstructMayThrow {
+ CopyConstructMayThrow(const CopyConstructMayThrow&);
+ CopyConstructMayThrow& operator=(CopyConstructMayThrow const&) noexcept;
+};
+
+struct CopyAssignMayThrow {
+ CopyAssignMayThrow(const CopyAssignMayThrow&) noexcept;
+ CopyAssignMayThrow& operator=(CopyAssignMayThrow const&);
+};
+
+
+#endif // TEST_LIBCXX_UTILITIES_EXPECTED_TYPES_H
diff --git a/libcxx/test/libcxx/utilities/expected/version.pass.cpp b/libcxx/test/libcxx/utilities/expected/version.pass.cpp
new file mode 100644
index 0000000000000..d9d45fe1a0eb1
--- /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
+//
+//===----------------------------------------------------------------------===//
+
+// <expected>
+
+#include <expected>
+
+#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
index 0000000000000..4872981be89e0
--- /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
+
+// <expected>
+
+// Test the feature test macros defined by <expected>
+
+/* Constant Value
+ __cpp_lib_expected 202202L [C++2b]
+*/
+
+#include <expected>
+#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
index 50632e68e1d66..9026cd120bbd3 100644
--- 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
@@ -76,6 +76,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]
@@ -416,6 +417,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
@@ -1059,6 +1064,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
@@ -1807,6 +1816,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"
@@ -2840,6 +2853,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"
@@ -4071,6 +4088,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
index 0000000000000..67a91b99f26c1
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.bad/ctor.error.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
+
+// explicit bad_expected_access(E e);
+
+// Effects: Initializes unex with std::move(e).
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+// test explicit
+static_assert(std::convertible_to<int, int>);
+static_assert(!std::convertible_to<int, std::bad_expected_access<int>>);
+
+int main(int, char**) {
+ std::bad_expected_access<MoveOnly> 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
index 0000000000000..4e1e2ea864de2
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.bad/error.member.pass.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+template <class T>
+concept ErrorNoexcept =
+ requires(T&& t) {
+ { std::forward<T>(t).error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+static_assert(ErrorNoexcept<std::bad_expected_access<int>&>);
+static_assert(ErrorNoexcept<std::bad_expected_access<int> const&>);
+static_assert(ErrorNoexcept<std::bad_expected_access<int>&&>);
+static_assert(ErrorNoexcept<std::bad_expected_access<int> const&&>);
+
+void test() {
+ // &
+ {
+ std::bad_expected_access<int> e(5);
+ decltype(auto) i = e.error();
+ static_assert(std::same_as<decltype(i), int&>);
+ assert(i == 5);
+ }
+
+ // const &
+ {
+ const std::bad_expected_access<int> e(5);
+ decltype(auto) i = e.error();
+ static_assert(std::same_as<decltype(i), const int&>);
+ assert(i == 5);
+ }
+
+ // &&
+ {
+ std::bad_expected_access<int> e(5);
+ decltype(auto) i = std::move(e).error();
+ static_assert(std::same_as<decltype(i), int&&>);
+ assert(i == 5);
+ }
+
+ // const &&
+ {
+ const std::bad_expected_access<int> e(5);
+ decltype(auto) i = std::move(e).error();
+ static_assert(std::same_as<decltype(i), const int&&>);
+ 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
index 0000000000000..e6d050b2129d6
--- /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 <expected>
+#include <utility>
+
+template <class T>
+concept WhatNoexcept =
+ requires(const T& t) {
+ { t.what() } noexcept;
+ };
+
+struct foo{};
+
+static_assert(!WhatNoexcept<foo>);
+static_assert(WhatNoexcept<std::bad_expected_access<int>>);
+static_assert(WhatNoexcept<std::bad_expected_access<foo>>);
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
index 0000000000000..09122502268f3
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.U.pass.cpp
@@ -0,0 +1,338 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class U = T>
+// constexpr expected& operator=(U&& v);
+//
+// Constraints:
+// - is_same_v<expected, remove_cvref_t<U>> is false; and
+// - remove_cvref_t<U> is not a specialization of unexpected; and
+// - is_constructible_v<T, U> is true; and
+// - is_assignable_v<T&, U> is true; and
+// - is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||
+// is_nothrow_move_constructible_v<E> is true.
+//
+// Effects:
+// - If has_value() is true, equivalent to: val = std::forward<U>(v);
+// - Otherwise, equivalent to:
+// reinit-expected(val, unex, std::forward<U>(v));
+// has_val = true;
+// - Returns: *this.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<int, int>&, int>);
+
+// is_same_v<expected, remove_cvref_t<U>>
+// it is true because it covered by the copy assignment
+static_assert(std::is_assignable_v<std::expected<int, int>&, std::expected<int, int>>);
+
+// remove_cvref_t<U> is a specialization of unexpected
+// it is true because it covered the unepxected overload
+static_assert(std::is_assignable_v<std::expected<int, int>&, std::unexpected<int>>);
+
+// !is_constructible_v<T, U>
+struct NoCtorFromInt {
+ NoCtorFromInt(int) = delete;
+ NoCtorFromInt& operator=(int);
+};
+static_assert(!std::is_assignable_v<std::expected<NoCtorFromInt, int>&, int>);
+
+// !is_assignable_v<T&, U>
+struct NoAssignFromInt {
+ explicit NoAssignFromInt(int);
+ NoAssignFromInt& operator=(int) = delete;
+};
+static_assert(!std::is_assignable_v<std::expected<NoAssignFromInt, int>&, int>);
+
+template <bool moveNoexcept, bool convertNoexcept>
+struct MaybeNoexcept {
+ explicit MaybeNoexcept(int) noexcept(convertNoexcept);
+ MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
+ MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
+ MaybeNoexcept& operator=(int);
+};
+
+// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+// is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, int>&, int>);
+
+// is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, true>, MaybeNoexcept<false, false>>&, int>);
+
+// !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, false>, MaybeNoexcept<false, false>>&, int>);
+
+// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&, int>);
+
+constexpr bool test() {
+ // If has_value() is true, equivalent to: val = std::forward<U>(v);
+ // Copy
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<Traced, int> e1(std::in_place, oldState, 5);
+ Traced u(newState, 10);
+ decltype(auto) x = (e1 = u);
+ static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
+ 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<U>(v);
+ // Move
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<Traced, int> e1(std::in_place, oldState, 5);
+ Traced u(newState, 10);
+ decltype(auto) x = (e1 = std::move(u));
+ static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
+ assert(&x == &e1);
+
+ assert(e1.has_value());
+ assert(e1.value().data_ == 10);
+ assert(oldState.moveAssignCalled);
+ }
+
+ // Otherwise, equivalent to:
+ // reinit-expected(val, unex, std::forward<U>(v));
+ // is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+ // !is_nothrow_move_constructible_v<E>
+ // copy
+ //
+ // In this case, it should call the branch
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::forward<Args>(args)...);
+ {
+ BothMayThrow::state oldState{};
+ std::expected<MoveThrowConvNoexcept, BothMayThrow> e1(std::unexpect, oldState, 5);
+ const int i = 10;
+ decltype(auto) x = (e1 = i);
+ static_assert(std::same_as<decltype(x), std::expected<MoveThrowConvNoexcept, BothMayThrow>&>);
+ 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<U>(v));
+ // is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+ // !is_nothrow_move_constructible_v<E>
+ // move
+ //
+ // In this case, it should call the branch
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::forward<Args>(args)...);
+ {
+ BothMayThrow::state oldState{};
+ std::expected<MoveThrowConvNoexcept, BothMayThrow> e1(std::unexpect, oldState, 5);
+ decltype(auto) x = (e1 = 10);
+ static_assert(std::same_as<decltype(x), std::expected<MoveThrowConvNoexcept, BothMayThrow>&>);
+ 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<U>(v));
+ // !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
+ // !is_nothrow_move_constructible_v<E>
+ // copy
+ //
+ // In this case, it should call the branch
+ // T tmp(std::forward<Args>(args)...);
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::move(tmp));
+ {
+ BothMayThrow::state oldState{};
+ std::expected<MoveNoexceptConvThrow, BothMayThrow> e1(std::unexpect, oldState, 5);
+ const int i = 10;
+ decltype(auto) x = (e1 = i);
+ static_assert(std::same_as<decltype(x), std::expected<MoveNoexceptConvThrow, BothMayThrow>&>);
+ 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<U>(v));
+ // !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
+ // !is_nothrow_move_constructible_v<E>
+ // move
+ //
+ // In this case, it should call the branch
+ // T tmp(std::forward<Args>(args)...);
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::move(tmp));
+ {
+ BothMayThrow::state oldState{};
+ std::expected<MoveNoexceptConvThrow, BothMayThrow> e1(std::unexpect, oldState, 5);
+ decltype(auto) x = (e1 = 10);
+ static_assert(std::same_as<decltype(x), std::expected<MoveNoexceptConvThrow, BothMayThrow>&>);
+ 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<U>(v));
+ // !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+ // is_nothrow_move_constructible_v<E>
+ // 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ {
+ TracedNoexcept::state oldState{};
+ std::expected<BothMayThrow, TracedNoexcept> e1(std::unexpect, oldState, 5);
+ const int i = 10;
+ decltype(auto) x = (e1 = i);
+ static_assert(std::same_as<decltype(x), std::expected<BothMayThrow, TracedNoexcept>&>);
+ 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<U>(v));
+ // !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
+ // is_nothrow_move_constructible_v<E>
+ // 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ {
+ TracedNoexcept::state oldState{};
+ std::expected<BothMayThrow, TracedNoexcept> e1(std::unexpect, oldState, 5);
+ decltype(auto) x = (e1 = 10);
+ static_assert(std::same_as<decltype(x), std::expected<BothMayThrow, TracedNoexcept>&>);
+ 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);
+ }
+
+ // Test default template argument.
+ // Without it, the template parameter cannot be deduced from an initializer list
+ {
+ struct Bar {
+ int i;
+ int j;
+ constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
+ };
+
+ std::expected<Bar, int> e({5, 6});
+ e = {7, 8};
+ assert(e.value().i == 7);
+ assert(e.value().j == 8);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<ThrowOnConvert, int> e1(std::unexpect, 5);
+ try {
+ e1 = 10;
+ assert(false);
+ } catch (Except) {
+ assert(!e1.has_value());
+ assert(e1.error() == 5);
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..d4496bac85c86
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp
@@ -0,0 +1,291 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// 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<T> is true and
+// - is_copy_constructible_v<T> is true and
+// - is_copy_assignable_v<E> is true and
+// - is_copy_constructible_v<E> is true and
+// - is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<int, int>>);
+
+// !is_copy_assignable_v<T>
+static_assert(!std::is_copy_assignable_v<std::expected<NotCopyAssignable, int>>);
+
+// !is_copy_constructible_v<T>
+static_assert(!std::is_copy_assignable_v<std::expected<NotCopyConstructible, int>>);
+
+// !is_copy_assignable_v<E>
+static_assert(!std::is_copy_assignable_v<std::expected<int, NotCopyAssignable>>);
+
+// !is_copy_constructible_v<E>
+static_assert(!std::is_copy_assignable_v<std::expected<int, NotCopyConstructible>>);
+
+// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
+static_assert(std::is_copy_assignable_v<std::expected<MoveMayThrow, int>>);
+
+// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(std::is_copy_assignable_v<std::expected<int, MoveMayThrow>>);
+
+// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_copy_assignable_v<std::expected<MoveMayThrow, MoveMayThrow>>);
+
+constexpr bool test() {
+ // If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs.
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<Traced, int> e1(std::in_place, oldState, 5);
+ const std::expected<Traced, int> e2(std::in_place, newState, 10);
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
+ 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ //
+ {
+ TracedNoexcept::state oldState{};
+ Traced::state newState{};
+ std::expected<TracedNoexcept, Traced> e1(std::in_place, oldState, 5);
+ const std::expected<TracedNoexcept, Traced> e2(std::unexpect, newState, 10);
+
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
+ 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>(args)...);
+ //
+ {
+ Traced::state oldState{};
+ TracedNoexcept::state newState{};
+ std::expected<Traced, TracedNoexcept> e1(std::in_place, oldState, 5);
+ const std::expected<Traced, TracedNoexcept> e2(std::unexpect, newState, 10);
+
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
+ 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ //
+ {
+ TracedNoexcept::state oldState{};
+ Traced::state newState{};
+ std::expected<Traced, TracedNoexcept> e1(std::unexpect, oldState, 5);
+ const std::expected<Traced, TracedNoexcept> e2(std::in_place, newState, 10);
+
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
+ 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>(args)...);
+ //
+ {
+ Traced::state oldState{};
+ TracedNoexcept::state newState{};
+ std::expected<TracedNoexcept, Traced> e1(std::unexpect, oldState, 5);
+ const std::expected<TracedNoexcept, Traced> e2(std::in_place, newState, 10);
+
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
+ 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<int, Traced> e1(std::unexpect, oldState, 5);
+ const std::expected<int, Traced> e2(std::unexpect, newState, 10);
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
+ 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 ThrowOnCopyMoveMayThrow {
+ ThrowOnCopyMoveMayThrow() = default;
+ ThrowOnCopyMoveMayThrow(const ThrowOnCopyMoveMayThrow&) { throw Except{}; };
+ ThrowOnCopyMoveMayThrow& operator=(const ThrowOnCopyMoveMayThrow&) = default;
+ ThrowOnCopyMoveMayThrow(ThrowOnCopyMoveMayThrow&&) noexcept(false) {}
+ };
+
+ // assign value throw on copy
+ {
+ std::expected<ThrowOnCopyMoveMayThrow, int> e1(std::unexpect, 5);
+ const std::expected<ThrowOnCopyMoveMayThrow, int> 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<int, ThrowOnCopyMoveMayThrow> e1(5);
+ const std::expected<int, ThrowOnCopyMoveMayThrow> e2(std::unexpect);
+ try {
+ e1 = e2;
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(e1.value() == 5);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..b247ed36690a4
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp
@@ -0,0 +1,302 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// constexpr expected& operator=(expected&& rhs) noexcept(see below);
+//
+// Constraints:
+// - is_move_constructible_v<T> is true and
+// - is_move_assignable_v<T> is true and
+// - is_move_constructible_v<E> is true and
+// - is_move_assignable_v<E> is true and
+// - is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> 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<T> && is_nothrow_move_constructible_v<T> &&
+// is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<int, int>>);
+
+// !is_move_assignable_v<T>
+static_assert(!std::is_move_assignable_v<std::expected<NotMoveAssignable, int>>);
+
+// !is_move_constructible_v<T>
+static_assert(!std::is_move_assignable_v<std::expected<NotMoveConstructible, int>>);
+
+// !is_move_assignable_v<E>
+static_assert(!std::is_move_assignable_v<std::expected<int, NotMoveAssignable>>);
+
+// !is_move_constructible_v<E>
+static_assert(!std::is_move_assignable_v<std::expected<int, NotMoveConstructible>>);
+
+// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
+static_assert(std::is_move_assignable_v<std::expected<MoveCtorMayThrow, int>>);
+
+// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(std::is_move_assignable_v<std::expected<int, MoveCtorMayThrow>>);
+
+// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_move_assignable_v<std::expected<MoveCtorMayThrow, MoveCtorMayThrow>>);
+
+struct MoveAssignMayThrow {
+ MoveAssignMayThrow(MoveAssignMayThrow&&) noexcept = default;
+ MoveAssignMayThrow& operator=(MoveAssignMayThrow&&) noexcept(false) { return *this; }
+};
+
+// Test noexcept
+static_assert(std::is_nothrow_move_assignable_v<std::expected<int, int>>);
+
+// !is_nothrow_move_assignable_v<T>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<MoveAssignMayThrow, int>>);
+
+// !is_nothrow_move_constructible_v<T>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<MoveCtorMayThrow, int>>);
+
+// !is_nothrow_move_assignable_v<E>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveAssignMayThrow>>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveCtorMayThrow>>);
+
+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<Traced, int> e1(std::in_place, oldState, 5);
+ std::expected<Traced, int> e2(std::in_place, newState, 10);
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
+ 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ //
+ {
+ TracedNoexcept::state oldState{};
+ Traced::state newState{};
+ std::expected<TracedNoexcept, Traced> e1(std::in_place, oldState, 5);
+ std::expected<TracedNoexcept, Traced> e2(std::unexpect, newState, 10);
+
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
+ 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>(args)...);
+ //
+ {
+ Traced::state oldState{};
+ TracedNoexcept::state newState{};
+ std::expected<Traced, TracedNoexcept> e1(std::in_place, oldState, 5);
+ std::expected<Traced, TracedNoexcept> e2(std::unexpect, newState, 10);
+
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
+ 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ //
+ {
+ TracedNoexcept::state oldState{};
+ Traced::state newState{};
+ std::expected<Traced, TracedNoexcept> e1(std::unexpect, oldState, 5);
+ std::expected<Traced, TracedNoexcept> e2(std::in_place, newState, 10);
+
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
+ 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>(args)...);
+ //
+ {
+ Traced::state oldState{};
+ TracedNoexcept::state newState{};
+ std::expected<TracedNoexcept, Traced> e1(std::unexpect, oldState, 5);
+ std::expected<TracedNoexcept, Traced> e2(std::in_place, newState, 10);
+
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
+ 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<int, Traced> e1(std::unexpect, oldState, 5);
+ std::expected<int, Traced> e2(std::unexpect, newState, 10);
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
+ assert(&x == &e1);
+
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+ assert(oldState.moveAssignCalled);
+ }
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ // assign value throw on move
+ {
+ std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
+ std::expected<ThrowOnMoveConstruct, int> 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<int, ThrowOnMoveConstruct> e1(5);
+ std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
+ try {
+ e1 = std::move(e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(*e1 == 5);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..a45dd45cc963c
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.copy.pass.cpp
@@ -0,0 +1,200 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class G>
+// constexpr expected& operator=(const unexpected<G>& e);
+//
+// Let GF be const G&
+// Constraints:
+// - is_constructible_v<E, GF> is true; and
+// - is_assignable_v<E&, GF> is true; and
+// - is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
+// is_nothrow_move_constructible_v<E> is true.
+//
+// Effects:
+// - If has_value() is true, equivalent to:
+// reinit-expected(unex, val, std::forward<GF>(e.error()));
+// has_val = false;
+// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+// Returns: *this.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<int, int>&, const std::unexpected<int>&>);
+
+// !is_constructible_v<E, GF>
+static_assert(
+ !std::is_assignable_v<std::expected<int, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
+
+// !is_assignable_v<E&, GF>
+static_assert(!std::is_assignable_v<std::expected<int, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
+
+template <bool moveNoexcept, bool convertNoexcept>
+struct MaybeNoexcept {
+ explicit MaybeNoexcept(int) noexcept(convertNoexcept);
+ MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
+ MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
+ MaybeNoexcept& operator=(int);
+};
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<true, false>>&,
+ const std::unexpected<int>&>);
+
+// is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, true>>&,
+ const std::unexpected<int>&>);
+
+// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, true>, MaybeNoexcept<false, false>>&,
+ const std::unexpected<int>&>);
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&,
+ const std::unexpected<int>&>);
+
+constexpr bool test() {
+ // - If has_value() is true, equivalent to:
+ // reinit-expected(unex, val, std::forward<GF>(e.error()));
+ // is_nothrow_constructible_v<E, GF>
+ //
+ // In this case, it should call the branch
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::forward<Args>(args)...);
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothNoexcept> e(std::in_place, oldState, 5);
+ const std::unexpected<int> un(10);
+ decltype(auto) x = (e = un);
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothNoexcept>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<E>
+ //
+ // In this case, it should call the branch
+ // T tmp(std::forward<Args>(args)...);
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::move(tmp));
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, MoveNoexceptConvThrow> e(std::in_place, oldState, 5);
+ const std::unexpected<int> un(10);
+ decltype(auto) x = (e = un);
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, MoveNoexceptConvThrow>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<E>
+ // is_nothrow_move_constructible_v<T>
+ //
+ // 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothMayThrow> e(std::in_place, oldState, 5);
+ const std::unexpected<int> un(10);
+ decltype(auto) x = (e = un);
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothMayThrow>&>);
+ assert(&x == &e);
+
+ assert(oldState.moveCtorCalled);
+ assert(oldState.dtorCalled);
+ assert(e.error().copiedFromInt);
+ }
+
+ // Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<int, Traced> e1(std::unexpect, oldState, 5);
+ const std::unexpected<Traced> e(std::in_place, newState, 10);
+ decltype(auto) x = (e1 = e);
+ static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
+ assert(&x == &e1);
+
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+ assert(oldState.copyAssignCalled);
+ }
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<int, ThrowOnConvert> e1(std::in_place, 5);
+ const std::unexpected<int> un(10);
+ try {
+ e1 = un;
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(*e1 == 5);
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..cb56d30174d1a
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.unexpected.move.pass.cpp
@@ -0,0 +1,200 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class G>
+// constexpr expected& operator=(unexpected<G>&& e);
+//
+// Let GF be G
+// Constraints:
+// - is_constructible_v<E, GF> is true; and
+// - is_assignable_v<E&, GF> is true; and
+// - is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
+// is_nothrow_move_constructible_v<E> is true.
+//
+// Effects:
+// - If has_value() is true, equivalent to:
+// reinit-expected(unex, val, std::forward<GF>(e.error()));
+// has_val = false;
+// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+// Returns: *this.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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::expected<int, int>&, std::unexpected<int>&&>);
+
+// !is_constructible_v<E, GF>
+static_assert(
+ !std::is_assignable_v<std::expected<int, NotMoveConstructible>&, std::unexpected<NotMoveConstructible>&&>);
+
+// !is_assignable_v<E&, GF>
+static_assert(!std::is_assignable_v<std::expected<int, NotMoveAssignable>&, std::unexpected<NotMoveAssignable>&&>);
+
+template <bool moveNoexcept, bool convertNoexcept>
+struct MaybeNoexcept {
+ explicit MaybeNoexcept(int) noexcept(convertNoexcept);
+ MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
+ MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
+ MaybeNoexcept& operator=(int);
+};
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<true, false>>&,
+ std::unexpected<int>&&>);
+
+// is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, true>>&,
+ std::unexpected<int>&&>);
+
+// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, true>, MaybeNoexcept<false, false>>&,
+ std::unexpected<int>&&>);
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&,
+ std::unexpected<int>&&>);
+
+constexpr bool test() {
+ // - If has_value() is true, equivalent to:
+ // reinit-expected(unex, val, std::forward<GF>(e.error()));
+ // is_nothrow_constructible_v<E, GF>
+ //
+ // In this case, it should call the branch
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::forward<Args>(args)...);
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothNoexcept> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothNoexcept>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<E>
+ //
+ // In this case, it should call the branch
+ // T tmp(std::forward<Args>(args)...);
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::move(tmp));
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, MoveNoexceptConvThrow> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, MoveNoexceptConvThrow>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<E>
+ // is_nothrow_move_constructible_v<T>
+ //
+ // 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothMayThrow> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothMayThrow>&>);
+ assert(&x == &e);
+
+ assert(oldState.moveCtorCalled);
+ assert(oldState.dtorCalled);
+ assert(e.error().movedFromInt);
+ }
+
+ // Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<int, Traced> e1(std::unexpect, oldState, 5);
+ std::unexpected<Traced> e(std::in_place, newState, 10);
+ decltype(auto) x = (e1 = std::move(e));
+ static_assert(std::same_as<decltype(x), std::expected<int, Traced >&>);
+ assert(&x == &e1);
+
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+ assert(oldState.moveAssignCalled);
+ }
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<int, ThrowOnConvert> e1(std::in_place, 5);
+ std::unexpected<int> un(10);
+ try {
+ e1 = std::move(un);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(*e1 == 5);
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..3cdfcde3f4d69
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.intializer_list.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<class U, class... Args>
+// constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
+// Constraints: is_nothrow_constructible_v<T, initializer_list<U>&, 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>(args)...);
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+template <class T, class... Args>
+concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward<Args>(args)...); };
+
+static_assert(CanEmplace<std::expected<int, int>, int>);
+
+template <bool Noexcept>
+struct CtorFromInitalizerList {
+ CtorFromInitalizerList(std::initializer_list<int>&) noexcept(Noexcept);
+ CtorFromInitalizerList(std::initializer_list<int>&, int) noexcept(Noexcept);
+};
+
+static_assert(CanEmplace<std::expected<CtorFromInitalizerList<true>, int>, std::initializer_list<int>&>);
+static_assert(!CanEmplace<std::expected<CtorFromInitalizerList<false>, int>, std::initializer_list<int>&>);
+static_assert(CanEmplace<std::expected<CtorFromInitalizerList<true>, int>, std::initializer_list<int>&, int>);
+static_assert(!CanEmplace<std::expected<CtorFromInitalizerList<false>, int>, std::initializer_list<int>&, int>);
+
+struct Data {
+ std::initializer_list<int> il;
+ int i;
+
+ constexpr Data(std::initializer_list<int>& 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<Data, int> e(std::in_place, list1, 5);
+ decltype(auto) x = e.emplace(list2, 10);
+ static_assert(std::same_as<decltype(x), Data&>);
+ 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<Data, int> e(std::unexpect, 5);
+ decltype(auto) x = e.emplace(list, 10);
+ static_assert(std::same_as<decltype(x), Data&>);
+ 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
index 0000000000000..66c066db3c59f
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/emplace.pass.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class... Args>
+// constexpr T& emplace(Args&&... args) noexcept;
+// Constraints: is_nothrow_constructible_v<T, 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), std::forward<Args>(args)...);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+template <class T, class... Args>
+concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward<Args>(args)...); };
+
+static_assert(CanEmplace<std::expected<int, int>, int>);
+
+template <bool Noexcept>
+struct CtorFromInt {
+ CtorFromInt(int) noexcept(Noexcept);
+ CtorFromInt(int, int) noexcept(Noexcept);
+};
+
+static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int>);
+static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int, int>);
+static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int>);
+static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int, int>);
+
+constexpr bool test() {
+ // has_value
+ {
+ BothNoexcept::state oldState{};
+ BothNoexcept::state newState{};
+ std::expected<BothNoexcept, int> e(std::in_place, oldState, 5);
+ decltype(auto) x = e.emplace(newState, 10);
+ static_assert(std::same_as<decltype(x), BothNoexcept&>);
+ assert(&x == &(*e));
+
+ assert(oldState.dtorCalled);
+ assert(e.has_value());
+ assert(e.value().data_ == 10);
+ }
+
+ // !has_value
+ {
+ BothMayThrow::state oldState{};
+ std::expected<int, BothMayThrow> e(std::unexpect, oldState, 5);
+ decltype(auto) x = e.emplace(10);
+ static_assert(std::same_as<decltype(x), int&>);
+ 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
index 0000000000000..9274b9a2c030e
--- /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<class U, class G>
+// constexpr explicit(see below) expected(const expected<U, G>&);
+//
+// Let:
+// - UF be const U&
+// - GF be const G&
+//
+// Constraints:
+// - is_constructible_v<T, UF> is true; and
+// - is_constructible_v<E, GF> is true; and
+// - is_constructible_v<T, expected<U, G>&> is false; and
+// - is_constructible_v<T, expected<U, G>> is false; and
+// - is_constructible_v<T, const expected<U, G>&> is false; and
+// - is_constructible_v<T, const expected<U, G>> is false; and
+// - is_convertible_v<expected<U, G>&, T> is false; and
+// - is_convertible_v<expected<U, G>&&, T> is false; and
+// - is_convertible_v<const expected<U, G>&, T> is false; and
+// - is_convertible_v<const expected<U, G>&&, T> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
+//
+// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward<UF>(*rhs). Otherwise, direct-non-list-initializes unex with std::forward<GF>(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<UF, T> || !is_convertible_v<GF, E>.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Constraints:
+template <class T1, class Err1, class T2, class Err2>
+concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, const std::expected<T2, Err2>&>;
+
+struct CtorFromInt {
+ CtorFromInt(int);
+};
+
+static_assert(canCstrFromExpected<CtorFromInt, int, int, int>);
+
+struct NoCtorFromInt {};
+
+// !is_constructible_v<T, UF>
+static_assert(!canCstrFromExpected<NoCtorFromInt, int, int, int>);
+
+// !is_constructible_v<E, GF>
+static_assert(!canCstrFromExpected<int, NoCtorFromInt, int, int>);
+
+template <class T>
+struct CtorFrom {
+ explicit CtorFrom(int)
+ requires(!std::same_as<T, int>);
+ explicit CtorFrom(T);
+ explicit CtorFrom(auto&&) = delete;
+};
+
+// is_constructible_v<T, expected<U, G>&>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>&>
+// note that this is true because it is covered by the other overload
+// template<class U = T> 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<CtorFrom<std::expected<int, int> const&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&&>, int, int, int>);
+
+template <class T>
+struct ConvertFrom {
+ ConvertFrom(int)
+ requires(!std::same_as<T, int>);
+ ConvertFrom(T);
+ ConvertFrom(auto&&) = delete;
+};
+
+// is_convertible_v<expected<U, G>&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&>, int, int, int>);
+
+// is_convertible_v<expected<U, G>&&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&&>, int, int, int>);
+
+// is_convertible_v<const expected<U, G>&, T>
+// note that this is true because it is covered by the other overload
+// template<class U = T> 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<ConvertFrom<std::expected<int, int> const&>, int, int, int>);
+
+// is_convertible_v<const expected<U, G>&&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&&>, int, int, int>);
+
+// Note for below 4 tests, because their E is constructible from cvref of std::expected<int, int>,
+// unexpected<E> will be constructible from cvref of std::expected<int, int>
+// is_constructible_v<unexpected<E>, expected<U, G>&>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&>, int, int>);
+
+// is_constructible_v<unexpected<E>, expected<U, G>>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&&>, int, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&>, int, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&&>, int, int>);
+
+// test explicit
+static_assert(std::is_convertible_v<const std::expected<int, int>&, std::expected<short, long>>);
+
+// !is_convertible_v<UF, T>
+static_assert(std::is_constructible_v<std::expected<CtorFrom<int>, int>, const std::expected<int, int>&>);
+static_assert(!std::is_convertible_v<const std::expected<int, int>&, std::expected<CtorFrom<int>, int>>);
+
+// !is_convertible_v<GF, E>.
+static_assert(std::is_constructible_v<std::expected<int, CtorFrom<int>>, const std::expected<int, int>&>);
+static_assert(!std::is_convertible_v<const std::expected<int, int>&, std::expected<int, CtorFrom<int>>>);
+
+struct Data {
+ int i;
+ constexpr Data(int ii) : i(ii) {}
+};
+
+constexpr bool test() {
+ // convert the value
+ {
+ const std::expected<int, int> e1(5);
+ std::expected<Data, int> 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<int, int> e1(std::unexpect, 5);
+ std::expected<int, Data> 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<int, int> e1;
+ try {
+ [[maybe_unused]] std::expected<ThrowingInt, int> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+ // throw on converting error
+ {
+ const std::expected<int, int> e1(std::unexpect);
+ try {
+ [[maybe_unused]] std::expected<int, ThrowingInt> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..71979311bfd10
--- /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<class U, class G>
+// constexpr explicit(see below) expected(expected<U, G>&&);
+//
+// Let:
+// - UF be const U
+// - GF be const G
+//
+// Constraints:
+// - is_constructible_v<T, UF> is true; and
+// - is_constructible_v<E, GF> is true; and
+// - is_constructible_v<T, expected<U, G>&> is false; and
+// - is_constructible_v<T, expected<U, G>> is false; and
+// - is_constructible_v<T, const expected<U, G>&> is false; and
+// - is_constructible_v<T, const expected<U, G>> is false; and
+// - is_convertible_v<expected<U, G>&, T> is false; and
+// - is_convertible_v<expected<U, G>&&, T> is false; and
+// - is_convertible_v<const expected<U, G>&, T> is false; and
+// - is_convertible_v<const expected<U, G>&&, T> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
+//
+// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward<UF>(*rhs). Otherwise, direct-non-list-initializes unex with std::forward<GF>(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<UF, T> || !is_convertible_v<GF, E>.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+template <class T1, class Err1, class T2, class Err2>
+concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, std::expected<T2, Err2>&&>;
+
+struct CtorFromInt {
+ CtorFromInt(int);
+};
+
+static_assert(canCstrFromExpected<CtorFromInt, int, int, int>);
+
+struct NoCtorFromInt {};
+
+// !is_constructible_v<T, UF>
+static_assert(!canCstrFromExpected<NoCtorFromInt, int, int, int>);
+
+// !is_constructible_v<E, GF>
+static_assert(!canCstrFromExpected<int, NoCtorFromInt, int, int>);
+
+template <class T>
+struct CtorFrom {
+ explicit CtorFrom(int)
+ requires(!std::same_as<T, int>);
+ explicit CtorFrom(T);
+ explicit CtorFrom(auto&&) = delete;
+};
+
+// is_constructible_v<T, expected<U, G>&>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>>
+// note that this is true because it is covered by the other overload
+// template<class U = T> 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<CtorFrom<std::expected<int, int>&&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>&>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&>, int, int, int>);
+
+// is_constructible_v<T, expected<U, G>>
+static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&&>, int, int, int>);
+
+template <class T>
+struct ConvertFrom {
+ ConvertFrom(int)
+ requires(!std::same_as<T, int>);
+ ConvertFrom(T);
+ ConvertFrom(auto&&) = delete;
+};
+
+// is_convertible_v<expected<U, G>&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&>, int, int, int>);
+
+// is_convertible_v<expected<U, G>&&, T>
+// note that this is true because it is covered by the other overload
+// template<class U = T> 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<ConvertFrom<std::expected<int, int>&&>, int, int, int>);
+
+// is_convertible_v<const expected<U, G>&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&>, int, int, int>);
+
+// is_convertible_v<const expected<U, G>&&, T>
+static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&&>, int, int, int>);
+
+// is_constructible_v<unexpected<E>, expected<U, G>&>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&>, int, int>);
+
+// is_constructible_v<unexpected<E>, expected<U, G>>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&&>, int, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&>, int, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>>
+static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&&>, int, int>);
+
+// test explicit
+static_assert(std::is_convertible_v<std::expected<int, int>&&, std::expected<short, long>>);
+
+// !is_convertible_v<UF, T>
+static_assert(std::is_constructible_v<std::expected<CtorFrom<int>, int>, std::expected<int, int>&&>);
+static_assert(!std::is_convertible_v<std::expected<int, int>&&, std::expected<CtorFrom<int>, int>>);
+
+// !is_convertible_v<GF, E>.
+static_assert(std::is_constructible_v<std::expected<int, CtorFrom<int>>, std::expected<int, int>&&>);
+static_assert(!std::is_convertible_v<std::expected<int, int>&&, std::expected<int, CtorFrom<int>>>);
+
+struct Data {
+ MoveOnly data;
+ constexpr Data(MoveOnly&& m) : data(std::move(m)) {}
+};
+
+constexpr bool test() {
+ // convert the value
+ {
+ std::expected<MoveOnly, int> e1(5);
+ std::expected<Data, int> 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<int, MoveOnly> e1(std::unexpect, 5);
+ std::expected<int, Data> 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<int, int> e1;
+ try {
+ [[maybe_unused]] std::expected<ThrowingInt, int> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+ // throw on converting error
+ {
+ const std::expected<int, int> e1(std::unexpect);
+ try {
+ [[maybe_unused]] std::expected<int, ThrowingInt> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..0b3451e3f192d
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
@@ -0,0 +1,138 @@
+//===----------------------------------------------------------------------===//
+// 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<T> is true and
+// - is_copy_constructible_v<E> is true.
+//
+// This constructor is trivial if
+// - is_trivially_copy_constructible_v<T> is true and
+// - is_trivially_copy_constructible_v<E> is true.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<T> is true and
+// - is_copy_constructible_v<E> is true.
+static_assert(std::is_copy_constructible_v<std::expected<int, int>>);
+static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, int>>);
+static_assert(std::is_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
+static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
+static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, int>>);
+static_assert(!std::is_copy_constructible_v<std::expected<int, NonCopyable>>);
+static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, NonCopyable>>);
+
+// Test: This constructor is trivial if
+// - is_trivially_copy_constructible_v<T> is true and
+// - is_trivially_copy_constructible_v<E> is true.
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_copy_constructible_v<std::expected<int, int>>);
+#endif
+static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, int>>);
+static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
+static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
+
+constexpr bool test() {
+ // copy the value non-trivial
+ {
+ const std::expected<CopyableNonTrivial, int> e1(5);
+ auto e2 = e1;
+ assert(e2.has_value());
+ assert(e2.value().i == 5);
+ }
+
+ // copy the error non-trivial
+ {
+ const std::expected<int, CopyableNonTrivial> e1(std::unexpect, 5);
+ auto e2 = e1;
+ assert(!e2.has_value());
+ assert(e2.error().i == 5);
+ }
+
+ // copy the value trivial
+ {
+ const std::expected<int, int> e1(5);
+ auto e2 = e1;
+ assert(e2.has_value());
+ assert(e2.value() == 5);
+ }
+
+ // copy the error trivial
+ {
+ const std::expected<int, int> 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<Throwing, int> e1;
+ try {
+ [[maybe_unused]] auto e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+ // throw on copying error
+ {
+ const std::expected<int, Throwing> e1(std::unexpect);
+ try {
+ [[maybe_unused]] auto e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..431e604e8b692
--- /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<T> is true.
+//
+// Effects: Value-initializes val.
+// Postconditions: has_value() is true.
+//
+// Throws: Any exception thrown by the initialization of val.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct NoDedefaultCtor {
+ NoDedefaultCtor() = delete;
+};
+
+// Test constraints
+static_assert(std::is_default_constructible_v<std::expected<int, int>>);
+static_assert(!std::is_default_constructible_v<std::expected<NoDedefaultCtor, int>>);
+
+struct MyInt {
+ int i;
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+template <class T, class E>
+constexpr void testDefaultCtor() {
+ std::expected<T, E> e;
+ assert(e.has_value());
+ assert(e.value() == T());
+}
+
+template <class T>
+constexpr void testTypes() {
+ testDefaultCtor<T, int>();
+ testDefaultCtor<T, NoDedefaultCtor>();
+}
+
+constexpr bool test() {
+ testTypes<int>();
+ testTypes<MyInt>();
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing() { throw Except{}; };
+ };
+
+ try {
+ std::expected<Throwing, int> u;
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..9a033eaeb7d6a
--- /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<class... Args>
+// constexpr explicit expected(in_place_t, Args&&... args);
+//
+// Constraints: is_constructible_v<T, Args...> is true.
+//
+// Effects: Direct-non-list-initializes val with std::forward<Args>(args)....
+//
+// Postconditions: has_value() is true.
+//
+// Throws: Any exception thrown by the initialization of val.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <tuple>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::is_constructible_v<std::expected<int, int>, std::in_place_t>);
+static_assert(std::is_constructible_v<std::expected<int, int>, std::in_place_t, int>);
+
+// !is_constructible_v<T, Args...>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<foo, int>, std::in_place_t, int>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::in_place_t>);
+static_assert(!ImplicitlyConstructible<std::expected<int, int>, 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 <class T>
+constexpr void testInt() {
+ std::expected<T, int> e(std::in_place, 5);
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+template <class T>
+constexpr void testLValue() {
+ T t(5);
+ std::expected<T, int> e(std::in_place, t);
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+template <class T>
+constexpr void testRValue() {
+ std::expected<T, int> e(std::in_place, T(5));
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<CopyOnly>();
+ testInt<MoveOnly>();
+ testLValue<int>();
+ testLValue<CopyOnly>();
+ testRValue<int>();
+ testRValue<MoveOnly>();
+
+ // no arg
+ {
+ std::expected<int, int> e(std::in_place);
+ assert(e.has_value());
+ assert(e.value() == 0);
+ }
+
+ // one arg
+ {
+ std::expected<int, int> e(std::in_place, 5);
+ assert(e.has_value());
+ assert(e.value() == 5);
+ }
+
+ // multi args
+ {
+ std::expected<std::tuple<int, short, MoveOnly>, int> e(std::in_place, 1, 2, MoveOnly(3));
+ assert(e.has_value());
+ assert((e.value() == std::tuple<int, short, MoveOnly>(1, 2, MoveOnly(3))));
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<Throwing, int> u(std::in_place, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..3e85f87b25095
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.inplace_init_list.pass.cpp
@@ -0,0 +1,120 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class U, class... Args>
+// constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);
+//
+// Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
+//
+// Effects: Direct-non-list-initializes val with il, std::forward<Args>(args)....
+//
+// Postconditions: has_value() is true.
+//
+// Throws: Any exception thrown by the initialization of val.
+
+#include <algorithm>
+#include <cassert>
+#include <expected>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(
+ std::is_constructible_v<std::expected<std::vector<int>, int>, std::in_place_t, std::initializer_list<int>>);
+
+// !is_constructible_v<T, initializer_list<U>&, Args...>
+static_assert(!std::is_constructible_v<std::expected<int, int>, std::in_place_t, std::initializer_list<int>>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(
+ !ImplicitlyConstructible<std::expected<std::vector<int>, int>, std::in_place_t, std::initializer_list<int>>);
+
+template <class... Ts>
+struct Data {
+ std::vector<int> vec_;
+ std::tuple<Ts...> tuple_;
+
+ template <class... Us>
+ requires std::is_constructible_v<std::tuple<Ts...>, Us&&...>
+ constexpr Data(std::initializer_list<int> il, Us&&... us) : vec_(il), tuple_(std::forward<Us>(us)...) {}
+};
+
+constexpr bool test() {
+ // no arg
+ {
+ std::expected<Data<>, 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<Data<MoveOnly>, 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<Data<int&, int&&, MoveOnly>, 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>, int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<Throwing, int> u(std::in_place, {1, 2}, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..4ee5edd07a484
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.move.pass.cpp
@@ -0,0 +1,157 @@
+//===----------------------------------------------------------------------===//
+// 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<T> is true and
+// - is_move_constructible_v<E> 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<T> && is_nothrow_move_constructible_v<E>.
+//
+// This constructor is trivial if
+// - is_trivially_move_constructible_v<T> is true and
+// - is_trivially_move_constructible_v<E> is true.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<T> is true and
+// - is_move_constructible_v<E> is true.
+static_assert(std::is_move_constructible_v<std::expected<int, int>>);
+static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, int>>);
+static_assert(std::is_move_constructible_v<std::expected<int, MovableNonTrivial>>);
+static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);
+static_assert(!std::is_move_constructible_v<std::expected<NonMovable, int>>);
+static_assert(!std::is_move_constructible_v<std::expected<int, NonMovable>>);
+static_assert(!std::is_move_constructible_v<std::expected<NonMovable, NonMovable>>);
+
+// Test: This constructor is trivial if
+// - is_trivially_move_constructible_v<T> is true and
+// - is_trivially_move_constructible_v<E> is true.
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_move_constructible_v<std::expected<int, int>>);
+#endif
+static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, int>>);
+static_assert(!std::is_trivially_move_constructible_v<std::expected<int, MovableNonTrivial>>);
+static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);
+
+// Test: The exception specification is equivalent to
+// is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.
+static_assert(std::is_nothrow_move_constructible_v<std::expected<int, int>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, int>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<int, MoveMayThrow>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, MoveMayThrow>>);
+
+constexpr bool test() {
+ // move the value non-trivial
+ {
+ std::expected<MovableNonTrivial, int> 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<int, MovableNonTrivial> 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<int, int> 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<int, int> 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<Throwing, int> e1;
+ try {
+ [[maybe_unused]] auto e2 = std::move(e1);
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+ // throw on moving error
+ {
+ std::expected<int, Throwing> e1(std::unexpect);
+ try {
+ [[maybe_unused]] auto e2 = std::move(e1);
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..f05c2d15f3bbe
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.u.pass.cpp
@@ -0,0 +1,151 @@
+//===----------------------------------------------------------------------===//
+// 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<class U = T>
+// constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
+//
+// Constraints:
+// - is_same_v<remove_cvref_t<U>, in_place_t> is false; and
+// - is_same_v<expected, remove_cvref_t<U>> is false; and
+// - remove_cvref_t<U> is not a specialization of unexpected; and
+// - is_constructible_v<T, U> is true.
+//
+// Effects: Direct-non-list-initializes val with std::forward<U>(v).
+//
+// Postconditions: has_value() is true.
+//
+// Throws: Any exception thrown by the initialization of val.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::is_constructible_v<std::expected<int, int>, int>);
+
+// is_same_v<remove_cvref_t<U>, in_place_t>
+struct FromJustInplace {
+ FromJustInplace(std::in_place_t);
+};
+static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t>);
+static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t const&>);
+
+// is_same_v<expected, remove_cvref_t<U>>
+// Note that result is true because it is covered by the constructors that take expected
+static_assert(std::is_constructible_v<std::expected<int, int>, std::expected<int, int>&>);
+
+// remove_cvref_t<U> 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::expected<int, int>, std::unexpected<int>&>);
+
+// !is_constructible_v<T, U>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<int, int>, foo>);
+
+// test explicit(!is_convertible_v<U, T>)
+struct NotConvertible {
+ explicit NotConvertible(int);
+};
+static_assert(std::is_convertible_v<int, std::expected<int, int>>);
+static_assert(!std::is_convertible_v<int, std::expected<NotConvertible, 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 <class T>
+constexpr void testInt() {
+ std::expected<T, int> e(5);
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+template <class T>
+constexpr void testLValue() {
+ T t(5);
+ std::expected<T, int> e(t);
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+template <class T>
+constexpr void testRValue() {
+ std::expected<T, int> e(T(5));
+ assert(e.has_value());
+ assert(e.value() == 5);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<CopyOnly>();
+ testInt<MoveOnly>();
+ testLValue<int>();
+ testLValue<CopyOnly>();
+ testRValue<int>();
+ testRValue<MoveOnly>();
+
+ // Test default template argument.
+ // Without it, the template parameter cannot be deduced from an initializer list
+ {
+ struct Bar {
+ int i;
+ int j;
+ constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
+ };
+
+ std::expected<Bar, int> e({5, 6});
+ assert(e.value().i == 5);
+ assert(e.value().j == 6);
+ }
+
+ // this is a confusing example, but the behaviour
+ // is exactly what is specified in the spec
+ // see https://cplusplus.github.io/LWG/issue3836
+ {
+ struct BaseError {};
+ struct DerivedError : BaseError {};
+
+ std::expected<bool, DerivedError> e1(false);
+ std::expected<bool, BaseError> 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<Throwing, int> u(5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..ed705d35ee019
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.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<class... Args>
+// constexpr explicit expected(unexpect_t, Args&&... args);
+//
+// Constraints: is_constructible_v<E, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t>);
+static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t, int>);
+
+// !is_constructible_v<T, Args...>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<int, foo>, std::unexpect_t, int>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::unexpect_t>);
+static_assert(!ImplicitlyConstructible<std::expected<int, int>, 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 <class T>
+constexpr void testInt() {
+ std::expected<int, T> e(std::unexpect, 5);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+template <class T>
+constexpr void testLValue() {
+ T t(5);
+ std::expected<int, T> e(std::unexpect, t);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+template <class T>
+constexpr void testRValue() {
+ std::expected<int, T> e(std::unexpect, T(5));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<CopyOnly>();
+ testInt<MoveOnly>();
+ testLValue<int>();
+ testLValue<CopyOnly>();
+ testRValue<int>();
+ testRValue<MoveOnly>();
+
+ // no arg
+ {
+ std::expected<int, int> e(std::unexpect);
+ assert(!e.has_value());
+ assert(e.error() == 0);
+ }
+
+ // one arg
+ {
+ std::expected<int, int> e(std::unexpect, 5);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+ }
+
+ // multi args
+ {
+ std::expected<int, std::tuple<int, short, MoveOnly>> e(std::unexpect, 1, 2, MoveOnly(3));
+ assert(!e.has_value());
+ assert((e.error() == std::tuple<int, short, MoveOnly>(1, 2, MoveOnly(3))));
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<int, Throwing> u(std::unexpect, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..20ab1145b767d
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect_init_list.pass.cpp
@@ -0,0 +1,120 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class U, class... Args>
+// constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
+//
+// Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with il, std::forward<Args>(args)....
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <algorithm>
+#include <cassert>
+#include <expected>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(
+ std::is_constructible_v<std::expected<int, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
+
+// !is_constructible_v<T, initializer_list<U>&, Args...>
+static_assert(!std::is_constructible_v<std::expected<int, int>, std::unexpect_t, std::initializer_list<int>>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(
+ !ImplicitlyConstructible<std::expected<int, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
+
+template <class... Ts>
+struct Data {
+ std::vector<int> vec_;
+ std::tuple<Ts...> tuple_;
+
+ template <class... Us>
+ requires std::is_constructible_v<std::tuple<Ts...>, Us&&...>
+ constexpr Data(std::initializer_list<int> il, Us&&... us) : vec_(il), tuple_(std::forward<Us>(us)...) {}
+};
+
+constexpr bool test() {
+ // no arg
+ {
+ std::expected<int, Data<>> 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<int, Data<MoveOnly>> 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<int, Data<int&, int&&, MoveOnly>> 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>, int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<int, Throwing> u(std::unexpect, {1, 2}, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..09ac91182b3b8
--- /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<class G>
+// constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
+//
+// Let GF be const G&
+//
+// Constraints: is_constructible_v<E, GF> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints
+static_assert(std::is_constructible_v<std::expected<int, int>, const std::unexpected<int>&>);
+
+// !is_constructible_v<E, GF>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<int, int>, const std::unexpected<foo>&>);
+static_assert(!std::is_constructible_v<std::expected<int, MoveOnly>, const std::unexpected<MoveOnly>&>);
+
+// explicit(!is_convertible_v<const G&, E>)
+struct NotConvertible {
+ explicit NotConvertible(int);
+};
+static_assert(std::is_convertible_v<const std::unexpected<int>&, std::expected<int, int>>);
+static_assert(!std::is_convertible_v<const std::unexpected<int>&, std::expected<int, NotConvertible>>);
+
+struct MyInt {
+ int i;
+ constexpr MyInt(int ii) : i(ii) {}
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+template <class T>
+constexpr void testUnexpected() {
+ const std::unexpected<int> u(5);
+ std::expected<int, T> e(u);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr bool test() {
+ testUnexpected<int>();
+ testUnexpected<MyInt>();
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; }
+ };
+
+ {
+ const std::unexpected<int> u(5);
+ try {
+ [[maybe_unused]] std::expected<int, Throwing> e(u);
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..9aaaa3fe1a448
--- /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<class G>
+// constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
+//
+// Let GF be G
+//
+// Constraints: is_constructible_v<E, GF> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints
+static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>>);
+static_assert(std::is_constructible_v<std::expected<int, MoveOnly>, std::unexpected<MoveOnly>>);
+
+// !is_constructible_v<E, GF>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<int, int>, std::unexpected<foo>>);
+
+// explicit(!is_convertible_v<G, E>)
+struct NotConvertible {
+ explicit NotConvertible(int);
+};
+static_assert(std::is_convertible_v<std::unexpected<int>&&, std::expected<int, int>>);
+static_assert(!std::is_convertible_v<std::unexpected<int>&&, std::expected<int, NotConvertible>>);
+
+struct MyInt {
+ int i;
+ constexpr MyInt(int ii) : i(ii) {}
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+template <class Err>
+constexpr void testInt() {
+ std::unexpected<int> u(5);
+ std::expected<int, Err> e(std::move(u));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr void testMoveOnly() {
+ std::unexpected<MoveOnly> u(MoveOnly(5));
+ std::expected<int, MoveOnly> e(std::move(u));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+ assert(u.error() == 0);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<MyInt>();
+ testInt<MoveOnly>();
+ testMoveOnly();
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; }
+ };
+
+ {
+ std::unexpected<int> u(5);
+ try {
+ [[maybe_unused]] std::expected<int, Throwing> e(std::move(u));
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..b758fe0b2bcb4
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/dtor.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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// constexpr ~expected();
+//
+// Effects: If has_value() is true, destroys val, otherwise destroys unex.
+//
+// Remarks: If is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true,
+// then this destructor is a trivial destructor.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Remarks: If is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true,
+// then this destructor is a trivial destructor.
+struct NonTrivial {
+ ~NonTrivial() {}
+};
+
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_destructible_v<std::expected<int, int>>);
+#endif
+static_assert(!std::is_trivially_destructible_v<std::expected<NonTrivial, int>>);
+static_assert(!std::is_trivially_destructible_v<std::expected<int, NonTrivial>>);
+static_assert(!std::is_trivially_destructible_v<std::expected<NonTrivial, NonTrivial>>);
+
+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<TrackedDestroy, TrackedDestroy> e(std::in_place, valueDestroyed); }
+ assert(valueDestroyed);
+ }
+
+ // has error
+ {
+ bool errorDestroyed = false;
+ { [[maybe_unused]] std::expected<TrackedDestroy, TrackedDestroy> 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
index 0000000000000..29945d24ef7a0
--- /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<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<Data, int> e1(std::in_place, 5);
+ int i2 = 10;
+ int i3 = 5;
+ assert(e1 != i2);
+ assert(e1 == i3);
+ }
+
+ // !x.has_value()
+ {
+ const std::expected<Data, int> 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
index 0000000000000..62f0d6fe57ea9
--- /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<class T2, class E2> requires (!is_void_v<T2>)
+// friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test constraint
+template <class T1, class T2>
+concept CanCompare = requires(T1 t1, T2 t2) { t1 == t2; };
+
+struct Foo{};
+static_assert(!CanCompare<Foo, Foo>);
+
+static_assert(CanCompare<std::expected<int, int>, std::expected<int, int>>);
+static_assert(CanCompare<std::expected<int, int>, std::expected<short, short>>);
+
+// Note this is true because other overloads are unconstrained
+static_assert(CanCompare<std::expected<int, int>, std::expected<void, int>>);
+
+constexpr bool test() {
+ // x.has_value() && y.has_value()
+ {
+ const std::expected<int, int> e1(5);
+ const std::expected<int, int> e2(10);
+ const std::expected<int, int> e3(5);
+ assert(e1 != e2);
+ assert(e1 == e3);
+ }
+
+ // !x.has_value() && y.has_value()
+ {
+ const std::expected<int, int> e1(std::unexpect, 5);
+ const std::expected<int, int> e2(10);
+ const std::expected<int, int> e3(5);
+ assert(e1 != e2);
+ assert(e1 != e3);
+ }
+
+ // x.has_value() && !y.has_value()
+ {
+ const std::expected<int, int> e1(5);
+ const std::expected<int, int> e2(std::unexpect, 10);
+ const std::expected<int, int> e3(std::unexpect, 5);
+ assert(e1 != e2);
+ assert(e1 != e3);
+ }
+
+ // !x.has_value() && !y.has_value()
+ {
+ const std::expected<int, int> e1(std::unexpect, 5);
+ const std::expected<int, int> e2(std::unexpect, 10);
+ const std::expected<int, int> 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
index 0000000000000..963f39b1cbc2c
--- /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<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<Data, Data> e1(std::in_place, 5);
+ std::unexpected<int> un2(10);
+ std::unexpected<int> un3(5);
+ assert(e1 != un2);
+ assert(e1 != un3);
+ }
+
+ // !x.has_value()
+ {
+ const std::expected<Data, Data> e1(std::unexpect, 5);
+ std::unexpected<int> un2(10);
+ std::unexpected<int> 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
index 0000000000000..72fb16609bf96
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept ArrowNoexcept =
+ requires(T t) {
+ { t.operator->() } noexcept;
+ };
+
+static_assert(!ArrowNoexcept<int>);
+
+static_assert(ArrowNoexcept<std::expected<int, int>>);
+static_assert(ArrowNoexcept<const std::expected<int, int>>);
+
+constexpr bool test() {
+ // const
+ {
+ const std::expected<int, int> e(5);
+ std::same_as<const int*> decltype(auto) x = e.operator->();
+ assert(x == &(e.value()));
+ assert(*x == 5);
+ }
+
+ // non-const
+ {
+ std::expected<int, int> e(5);
+ std::same_as<int*> 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
index 0000000000000..8daecf3950ec0
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept OpBoolNoexcept =
+ requires(T t) {
+ { static_cast<bool>(t) } noexcept;
+ };
+
+struct Foo {};
+static_assert(!OpBoolNoexcept<Foo>);
+
+static_assert(OpBoolNoexcept<std::expected<int, int>>);
+static_assert(OpBoolNoexcept<const std::expected<int, int>>);
+
+// Test explicit
+static_assert(!std::is_convertible_v<std::expected<int, int>, bool>);
+
+constexpr bool test() {
+ // has_value
+ {
+ const std::expected<int, int> e(5);
+ assert(static_cast<bool>(e));
+ }
+
+ // !has_value
+ {
+ const std::expected<int, int> e(std::unexpect, 5);
+ assert(!static_cast<bool>(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
index 0000000000000..80bc243fcaefd
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/observers/deref.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
+
+// constexpr const T& operator*() const & noexcept;
+// constexpr T& operator*() & noexcept;
+// constexpr T&& operator*() && noexcept;
+// constexpr const T&& operator*() const && noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept DerefNoexcept =
+ requires(T t) {
+ { std::forward<T>(t).operator*() } noexcept;
+ };
+
+static_assert(!DerefNoexcept<int>);
+
+static_assert(DerefNoexcept<std::expected<int, int>&>);
+static_assert(DerefNoexcept<const std::expected<int, int>&>);
+static_assert(DerefNoexcept<std::expected<int, int>&&>);
+static_assert(DerefNoexcept<const std::expected<int, int>&&>);
+
+constexpr bool test() {
+ // non-const &
+ {
+ std::expected<int, int> e(5);
+ decltype(auto) x = *e;
+ static_assert(std::same_as<decltype(x), int&>);
+ assert(&x == &(e.value()));
+ assert(x == 5);
+ }
+
+ // const &
+ {
+ const std::expected<int, int> e(5);
+ decltype(auto) x = *e;
+ static_assert(std::same_as<decltype(x), const int&>);
+ assert(&x == &(e.value()));
+ assert(x == 5);
+ }
+
+ // non-const &&
+ {
+ std::expected<int, int> e(5);
+ decltype(auto) x = *std::move(e);
+ static_assert(std::same_as<decltype(x), int&&>);
+ assert(&x == &(e.value()));
+ assert(x == 5);
+ }
+
+ // const &&
+ {
+ const std::expected<int, int> e(5);
+ decltype(auto) x = *std::move(e);
+ static_assert(std::same_as<decltype(x), const int&&>);
+ 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
index 0000000000000..491e5e6b96b9a
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/observers/error.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 E& error() const & noexcept;
+// constexpr E& error() & noexcept;
+// constexpr E&& error() && noexcept;
+// constexpr const E&& error() const && noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept ErrorNoexcept =
+ requires(T t) {
+ { std::forward<T>(t).error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+
+static_assert(ErrorNoexcept<std::expected<int, int>&>);
+static_assert(ErrorNoexcept<const std::expected<int, int>&>);
+static_assert(ErrorNoexcept<std::expected<int, int>&&>);
+static_assert(ErrorNoexcept<const std::expected<int, int>&&>);
+
+constexpr bool test() {
+ // non-const &
+ {
+ std::expected<int, int> e(std::unexpect, 5);
+ decltype(auto) x = e.error();
+ static_assert(std::same_as<decltype(x), int&>);
+ assert(x == 5);
+ }
+
+ // const &
+ {
+ const std::expected<int, int> e(std::unexpect, 5);
+ decltype(auto) x = e.error();
+ static_assert(std::same_as<decltype(x), const int&>);
+ assert(x == 5);
+ }
+
+ // non-const &&
+ {
+ std::expected<int, int> e(std::unexpect, 5);
+ decltype(auto) x = std::move(e).error();
+ static_assert(std::same_as<decltype(x), int&&>);
+ assert(x == 5);
+ }
+
+ // const &&
+ {
+ const std::expected<int, int> e(std::unexpect, 5);
+ decltype(auto) x = std::move(e).error();
+ static_assert(std::same_as<decltype(x), const int&&>);
+ 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
index 0000000000000..27d657a065699
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept HasValueNoexcept =
+ requires(T t) {
+ { t.has_value() } noexcept;
+ };
+
+struct Foo {};
+static_assert(!HasValueNoexcept<Foo>);
+
+static_assert(HasValueNoexcept<std::expected<int, int>>);
+static_assert(HasValueNoexcept<const std::expected<int, int>>);
+
+constexpr bool test() {
+ // has_value
+ {
+ const std::expected<int, int> e(5);
+ assert(e.has_value());
+ }
+
+ // !has_value
+ {
+ const std::expected<int, int> 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
index 0000000000000..87d74486f280e
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ // non-const &
+ {
+ std::expected<int, int> e(5);
+ decltype(auto) x = e.value();
+ static_assert(std::same_as<decltype(x), int&>);
+ assert(&x == &(*e));
+ assert(x == 5);
+ }
+
+ // const &
+ {
+ const std::expected<int, int> e(5);
+ decltype(auto) x = e.value();
+ static_assert(std::same_as<decltype(x), const int&>);
+ assert(&x == &(*e));
+ assert(x == 5);
+ }
+
+ // non-const &&
+ {
+ std::expected<int, int> e(5);
+ decltype(auto) x = std::move(e).value();
+ static_assert(std::same_as<decltype(x), int&&>);
+ assert(&x == &(*e));
+ assert(x == 5);
+ }
+
+ // const &&
+ {
+ const std::expected<int, int> e(5);
+ decltype(auto) x = std::move(e).value();
+ static_assert(std::same_as<decltype(x), const int&&>);
+ assert(&x == &(*e));
+ assert(x == 5);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+
+ // int
+ {
+ const std::expected<int, int> e(std::unexpect, 5);
+ try {
+ e.value();
+ assert(false);
+ } catch (const std::bad_expected_access<int>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+ // MoveOnly
+ {
+ std::expected<int, MoveOnly> e(std::unexpect, 5);
+ try {
+ std::move(e).value();
+ assert(false);
+ } catch (const std::bad_expected_access<MoveOnly>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..b79b507e52550
--- /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<class U> constexpr T value_or(U&& v) const &;
+// template<class U> constexpr T value_or(U&& v) &&;
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ // const &, has_value()
+ {
+ const std::expected<int, int> e(5);
+ std::same_as<int> decltype(auto) x = e.value_or(10);
+ assert(x == 5);
+ }
+
+ // const &, !has_value()
+ {
+ const std::expected<int, int> e(std::unexpect, 5);
+ std::same_as<int> decltype(auto) x = e.value_or(10);
+ assert(x == 10);
+ }
+
+ // &&, has_value()
+ {
+ std::expected<MoveOnly, int> e(std::in_place, 5);
+ std::same_as<MoveOnly> decltype(auto) x = std::move(e).value_or(10);
+ assert(x == 5);
+ }
+
+ // &&, !has_value()
+ {
+ std::expected<MoveOnly, int> e(std::unexpect, 5);
+ std::same_as<MoveOnly> 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<int, int> e(std::unexpect, 5);
+ try {
+ e.value();
+ assert(false);
+ } catch (const std::bad_expected_access<int>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+ // MoveOnly
+ {
+ std::expected<int, MoveOnly> e(std::unexpect, 5);
+ try {
+ std::move(e).value();
+ assert(false);
+ } catch (const std::bad_expected_access<MoveOnly>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..3ea128a9f19e0
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/swap/free.swap.pass.cpp
@@ -0,0 +1,223 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, clang-15, apple-clang-14
+
+// friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+// Test Constraints:
+struct NotSwappable {
+ NotSwappable operator=(const NotSwappable&) = delete;
+};
+void swap(NotSwappable&, NotSwappable&) = delete;
+
+static_assert(std::is_swappable_v<std::expected<int, int>>);
+
+// !is_swappable_v<T>
+static_assert(!std::is_swappable_v<std::expected<NotSwappable, int>>);
+
+// !is_swappable_v<E>
+static_assert(!std::is_swappable_v<std::expected<int, NotSwappable>>);
+
+struct NotMoveContructible {
+ NotMoveContructible(NotMoveContructible&&) = delete;
+ friend void swap(NotMoveContructible&, NotMoveContructible&) {}
+};
+
+// !is_move_constructible_v<T>
+static_assert(!std::is_swappable_v<std::expected<NotMoveContructible, int>>);
+
+// !is_move_constructible_v<E>
+static_assert(!std::is_swappable_v<std::expected<int, NotMoveContructible>>);
+
+struct MoveMayThrow {
+ MoveMayThrow(MoveMayThrow&&) noexcept(false);
+ friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
+};
+
+// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
+static_assert(std::is_swappable_v<std::expected<MoveMayThrow, int>>);
+
+// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(std::is_swappable_v<std::expected<int, MoveMayThrow>>);
+
+// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_swappable_v<std::expected<MoveMayThrow, MoveMayThrow>>);
+
+// Test noexcept
+static_assert(std::is_nothrow_swappable_v<std::expected<int, int>>);
+
+// !is_nothrow_move_constructible_v<T>
+static_assert(!std::is_nothrow_swappable_v<std::expected<MoveMayThrow, int>>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_nothrow_swappable_v<std::expected<int, MoveMayThrow>>);
+
+struct SwapMayThrow {
+ friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
+};
+
+// !is_nothrow_swappable_v<T>
+static_assert(!std::is_nothrow_swappable_v<std::expected<SwapMayThrow, int>>);
+
+// !is_nothrow_swappable_v<E>
+static_assert(!std::is_nothrow_swappable_v<std::expected<int, SwapMayThrow>>);
+
+constexpr bool test() {
+ // this->has_value() && rhs.has_value()
+ {
+ std::expected<ADLSwap, int> x(std::in_place, 5);
+ std::expected<ADLSwap, int> 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<int, ADLSwap> x(std::unexpect, 5);
+ std::expected<int, ADLSwap> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::in_place, 5);
+ std::expected<TrackedMove<true>, TrackedMove<true>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::in_place, 5);
+ std::expected<TrackedMove<true>, TrackedMove<false>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::unexpect, 10);
+ std::expected<TrackedMove<true>, TrackedMove<true>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::unexpect, 10);
+ std::expected<TrackedMove<true>, TrackedMove<false>> 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
+ // !e1.has_value() && e2.has_value()
+ {
+ std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
+ std::expected<ThrowOnMoveConstruct, int> 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<int, ThrowOnMoveConstruct> e1(5);
+ std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
+ try {
+ swap(e1, e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(*e1 == 5);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..d2d4a09922092
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp
@@ -0,0 +1,239 @@
+//===----------------------------------------------------------------------===//
+// 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<T> is true and
+// is_swappable_v<E> is true and
+// is_move_constructible_v<T> && is_move_constructible_v<E> is true, and
+// is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
+//
+// Throws: Any exception thrown by the expressions in the Effects.
+// Remarks: The exception specification is equivalent to:
+// is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> &&
+// is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+// Test Constraints:
+template <class T, class E>
+concept HasMemberSwap = requires(std::expected<T, E> x, std::expected<T, E> y) { x.swap(y); };
+
+static_assert(HasMemberSwap<int, int>);
+
+struct NotSwappable {};
+void swap(NotSwappable&, NotSwappable&) = delete;
+
+// !is_swappable_v<T>
+static_assert(!HasMemberSwap<NotSwappable, int>);
+
+// !is_swappable_v<E>
+static_assert(!HasMemberSwap<int, NotSwappable>);
+
+struct NotMoveContructible {
+ NotMoveContructible(NotMoveContructible&&) = delete;
+ friend void swap(NotMoveContructible&, NotMoveContructible&) {}
+};
+
+// !is_move_constructible_v<T>
+static_assert(!HasMemberSwap<NotMoveContructible, int>);
+
+// !is_move_constructible_v<E>
+static_assert(!HasMemberSwap<int, NotMoveContructible>);
+
+struct MoveMayThrow {
+ MoveMayThrow(MoveMayThrow&&) noexcept(false);
+ friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
+};
+
+// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
+static_assert(HasMemberSwap<MoveMayThrow, int>);
+
+// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(HasMemberSwap<int, MoveMayThrow>);
+
+// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
+static_assert(!HasMemberSwap<MoveMayThrow, MoveMayThrow>);
+
+// Test noexcept
+template <class T, class E>
+concept MemberSwapNoexcept =
+ requires(std::expected<T, E> x, std::expected<T, E> y) {
+ { x.swap(y) } noexcept;
+ };
+
+static_assert(MemberSwapNoexcept<int, int>);
+
+// !is_nothrow_move_constructible_v<T>
+static_assert(!MemberSwapNoexcept<MoveMayThrow, int>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!MemberSwapNoexcept<int, MoveMayThrow>);
+
+struct SwapMayThrow {
+ friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
+};
+
+// !is_nothrow_swappable_v<T>
+static_assert(!MemberSwapNoexcept<SwapMayThrow, int>);
+
+// !is_nothrow_swappable_v<E>
+static_assert(!MemberSwapNoexcept<int, SwapMayThrow>);
+
+constexpr bool test() {
+ // this->has_value() && rhs.has_value()
+ {
+ std::expected<ADLSwap, int> x(std::in_place, 5);
+ std::expected<ADLSwap, int> 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<int, ADLSwap> x(std::unexpect, 5);
+ std::expected<int, ADLSwap> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::in_place, 5);
+ std::expected<TrackedMove<true>, TrackedMove<true>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::in_place, 5);
+ std::expected<TrackedMove<true>, TrackedMove<false>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::unexpect, 10);
+ std::expected<TrackedMove<true>, TrackedMove<true>> 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<E>
+ {
+ std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::unexpect, 10);
+ std::expected<TrackedMove<true>, TrackedMove<false>> 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
+ // !e1.has_value() && e2.has_value()
+ {
+ std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
+ std::expected<ThrowOnMoveConstruct, int> 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<int, ThrowOnMoveConstruct> e1(5);
+ std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
+ try {
+ e1.swap(e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(*e1 == 5);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..74f46f0ad9bc4
--- /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 <cassert>
+#include <expected>
+
+struct Error {
+ int i;
+ constexpr Error(int ii) : i(ii) {}
+};
+
+constexpr bool test() {
+ std::unexpected<Error> unex1(4);
+ const std::unexpected<Error> 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
index 0000000000000..31573be894d37
--- /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 <cassert>
+#include <expected>
+#include <utility>
+
+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<Error> unex1(4);
+ std::unexpected<Error> 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/ctad.compile.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp
new file mode 100644
index 0000000000000..eb23a2f981476
--- /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<class E> unexpected(E) -> unexpected<E>;
+
+#include <concepts>
+#include <expected>
+
+struct Foo{};
+
+static_assert(std::same_as<decltype(std::unexpected(5)), std::unexpected<int>>);
+static_assert(std::same_as<decltype(std::unexpected(Foo{})), std::unexpected<Foo>>);
+static_assert(std::same_as<decltype(std::unexpected(std::unexpected<int>(5))), std::unexpected<int>>);
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
index 0000000000000..9a6600232d96b
--- /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 <cassert>
+#include <expected>
+
+struct Error {
+ int i;
+ constexpr Error(int ii) : i(ii) {}
+};
+
+constexpr bool test() {
+ const std::unexpected<Error> 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
index 0000000000000..86e903aaf6320
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp
@@ -0,0 +1,122 @@
+//===----------------------------------------------------------------------===//
+// 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<class Err = E>
+// constexpr explicit unexpected(Err&& e);
+//
+// Constraints:
+// - is_same_v<remove_cvref_t<Err>, unexpected> is false; and
+// - is_same_v<remove_cvref_t<Err>, in_place_t> is false; and
+// - is_constructible_v<E, Err> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<Err>(e).
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::constructible_from<std::unexpected<int>, int>);
+
+// is_same_v<remove_cvref_t<Err>, unexpected>
+struct CstrFromUnexpected {
+ CstrFromUnexpected(CstrFromUnexpected const&) = delete;
+ CstrFromUnexpected(std::unexpected<CstrFromUnexpected> const&);
+};
+static_assert(!std::constructible_from<std::unexpected<CstrFromUnexpected>, std::unexpected<CstrFromUnexpected>>);
+
+// is_same_v<remove_cvref_t<Err>, in_place_t>
+struct CstrFromInplace {
+ CstrFromInplace(std::in_place_t);
+};
+static_assert(!std::constructible_from<std::unexpected<CstrFromInplace>, std::in_place_t>);
+
+// !is_constructible_v<E, Err>
+struct Foo {};
+static_assert(!std::constructible_from<std::unexpected<Foo>, int>);
+
+// test explicit
+static_assert(std::convertible_to<int, int>);
+static_assert(!std::convertible_to<int, std::unexpected<int>>);
+
+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<Error>) { assert(false); }
+};
+
+constexpr bool test() {
+ // lvalue
+ {
+ Error e(5);
+ std::unexpected<Error> unex(e);
+ assert(unex.error().i == 5);
+ assert(e.i == 5);
+ }
+
+ // rvalue
+ {
+ Error e(5);
+ std::unexpected<Error> 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<Error> unex(e);
+ }
+
+ // Test default template argument.
+ // Without it, the template parameter cannot be deduced from an initializer list
+ {
+ struct Bar {
+ int i;
+ int j;
+ constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
+ };
+ std::unexpected<Bar> ue({5, 6});
+ assert(ue.error().i == 5);
+ assert(ue.error().j == 6);
+ }
+
+ 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<Throwing> u(t);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..5cad5c77cef20
--- /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<class... Args>
+// constexpr explicit unexpected(in_place_t, Args&&... args);
+//
+// Constraints: is_constructible_v<E, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::constructible_from<std::unexpected<int>, std::in_place_t, int>);
+
+// !is_constructible_v<E, Args...>
+struct Foo {};
+static_assert(!std::constructible_from<std::unexpected<Foo>, std::in_place_t, int>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+
+static_assert(ImplicitlyConstructible<int, int>);
+static_assert(!ImplicitlyConstructible<std::unexpected<int>, 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<Error>) :arg(0){ assert(false); }
+};
+
+constexpr bool test() {
+ // lvalue
+ {
+ Arg a{5};
+ std::unexpected<Error> unex(std::in_place, a);
+ assert(unex.error().arg.i == 5);
+ assert(a.i == 5);
+ }
+
+ // rvalue
+ {
+ Arg a{5};
+ std::unexpected<Error> 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<Error> 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<Throwing> u(std::in_place, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..ee9a228cdcfd7
--- /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<class U, class... Args>
+// constexpr explicit unexpected(in_place_t, initializer_list<U> il, Args&&... args);
+//
+// Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with il, std::forward<Args>(args)....
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+#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<int> list;
+ Arg arg;
+ constexpr explicit Error(std::initializer_list<int> l, const Arg& a) : list(l), arg(a) {}
+ constexpr explicit Error(std::initializer_list<int> l, Arg&& a) : list(l), arg(std::move(a)) {}
+};
+
+// Test Constraints:
+static_assert(std::constructible_from<std::unexpected<Error>, std::in_place_t, std::initializer_list<int>, Arg>);
+
+// !is_constructible_v<E, initializer_list<U>&, Args...>
+struct Foo {};
+static_assert(!std::constructible_from<std::unexpected<Error>, std::in_place_t, std::initializer_list<double>, Arg>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+
+static_assert(ImplicitlyConstructible<int, int>);
+static_assert(!ImplicitlyConstructible<std::unexpected<Error>, std::in_place_t, std::initializer_list<int>, Arg>);
+
+constexpr bool test() {
+ // lvalue
+ {
+ Arg a{5};
+ auto l = {1, 2, 3};
+ std::unexpected<Error> 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<Error> 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>, int) { throw Except{}; }
+ };
+
+ try {
+ std::unexpected<Throwing> u(std::in_place, {1, 2}, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..3028dfa25756c
--- /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 <cassert>
+#include <expected>
+#include <utility>
+
+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<Error> 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
index 0000000000000..4d249df64592f
--- /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<class E2>
+// friend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y);
+//
+// Mandates: The expression x.error() == y.error() is well-formed and its result is convertible to bool.
+//
+// Returns: x.error() == y.error().
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+struct Error{
+ int i;
+ friend constexpr bool operator==(const Error&, const Error&) = default;
+};
+
+constexpr bool test() {
+ std::unexpected<Error> unex1(Error{2});
+ std::unexpected<Error> unex2(Error{3});
+ std::unexpected<Error> 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
index 0000000000000..8cfe555f70131
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+template <class T>
+concept ErrorNoexcept =
+ requires(const T& t) {
+ { t.error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+static_assert(ErrorNoexcept<std::unexpected<int>>);
+
+constexpr bool test() {
+ const std::unexpected<int> unex(5);
+ decltype(auto) i = unex.error();
+ static_assert(std::same_as<decltype(i), const int&>);
+ 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
index 0000000000000..ffd8ed8e209a0
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.const_ref_ref.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+template <class T>
+concept ErrorNoexcept =
+ requires(const T&& t) {
+ { std::move(t).error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+static_assert(ErrorNoexcept<std::unexpected<int>>);
+
+constexpr bool test() {
+ const std::unexpected<int> unex(5);
+ decltype(auto) i = std::move(unex).error();
+ static_assert(std::same_as<decltype(i), const int&&>);
+ 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
index 0000000000000..4f22eb4773e6e
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+template <class T>
+concept ErrorNoexcept =
+ requires(T& t) {
+ { t.error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+static_assert(ErrorNoexcept<std::unexpected<int>>);
+
+constexpr bool test() {
+ std::unexpected<int> unex(5);
+ decltype(auto) i = unex.error();
+ static_assert(std::same_as<decltype(i), int&>);
+ 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
index 0000000000000..415435b921185
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/observer/error.ref_ref.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+// 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 <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+template <class T>
+concept ErrorNoexcept =
+ requires(T&& t) {
+ { std::move(t).error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+static_assert(ErrorNoexcept<std::unexpected<int>>);
+
+constexpr bool test() {
+ std::unexpected<int> unex(5);
+ decltype(auto) i = std::move(unex).error();
+ static_assert(std::same_as<decltype(i), int&&>);
+ 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
index 0000000000000..b70400ae3fb43
--- /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<E> is true.
+//
+// Effects: Equivalent to x.swap(y).
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+// test noexcept
+struct NoexceptSwap {
+ friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept;
+};
+
+struct MayThrowSwap {
+ friend void swap(MayThrowSwap&, MayThrowSwap&);
+};
+
+template <class T>
+concept ADLSwapNoexcept =
+ requires(T& t1, T& t2) {
+ { swap(t1, t2) } noexcept;
+ };
+
+static_assert(ADLSwapNoexcept<std::unexpected<NoexceptSwap>>);
+static_assert(!ADLSwapNoexcept<std::unexpected<MayThrowSwap>>);
+
+// test constraint
+struct NonSwappable {
+ NonSwappable& operator=(const NonSwappable&) = delete;
+};
+
+static_assert(std::is_swappable_v<std::unexpected<int>>);
+static_assert(std::is_swappable_v<std::unexpected<MayThrowSwap>>);
+static_assert(!std::is_swappable_v<std::unexpected<NonSwappable>>);
+
+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<ADLSwap> unex1(5);
+ std::unexpected<ADLSwap> 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
index 0000000000000..d77870e648ece
--- /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<E>);
+//
+// Mandates: is_swappable_v<E> is true.
+//
+// Effects: Equivalent to: using std::swap; swap(unex, other.unex);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <utility>
+
+// test noexcept
+struct NoexceptSwap {
+ friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept;
+};
+
+struct MayThrowSwap {
+ friend void swap(MayThrowSwap&, MayThrowSwap&);
+};
+
+template <class T>
+concept MemberSwapNoexcept =
+ requires(T& t1, T& t2) {
+ { t1.swap(t2) } noexcept;
+ };
+
+static_assert(MemberSwapNoexcept<std::unexpected<NoexceptSwap>>);
+static_assert(!MemberSwapNoexcept<std::unexpected<MayThrowSwap>>);
+
+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<int> unex1(5);
+ std::unexpected<int> unex2(6);
+ unex1.swap(unex2);
+ assert(unex1.error() == 6);
+ assert(unex2.error() == 5);
+ }
+
+ // adl swap
+ {
+ std::unexpected<ADLSwap> unex1(5);
+ std::unexpected<ADLSwap> 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
index 0000000000000..00af3264532f1
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp
@@ -0,0 +1,126 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// 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<E> is true and is_copy_constructible_v<E> is true.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<void, int>>);
+
+// !is_copy_assignable_v<E>
+static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyAssignable>>);
+
+// !is_copy_constructible_v<E>
+static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyConstructible>>);
+
+constexpr bool test() {
+ // If this->has_value() && rhs.has_value() is true, no effects.
+ {
+ std::expected<void, int> e1;
+ std::expected<void, int> e2;
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<void, int>&>);
+ 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<void, Traced> e1;
+ std::expected<void, Traced> e2(std::unexpect, state, 5);
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ 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<void, Traced> e1(std::unexpect, state, 5);
+ std::expected<void, Traced> e2;
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e1);
+ assert(e1.has_value());
+
+ assert(state.dtorCalled);
+ }
+
+ // Otherwise, equivalent to unex = rhs.error().
+ {
+ Traced::state state{};
+ std::expected<void, Traced> e1(std::unexpect, state, 5);
+ std::expected<void, Traced> e2(std::unexpect, state, 10);
+ decltype(auto) x = (e1 = e2);
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e1);
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+
+ assert(state.copyAssignCalled);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
+ std::expected<void, ThrowOnCopyConstruct> e2(std::unexpect);
+ try {
+ e1 = e2;
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ testException();
+ 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
index 0000000000000..878908d8d8ec4
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.move.pass.cpp
@@ -0,0 +1,151 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// 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<E> && is_nothrow_move_assignable_v<E>.
+//
+// This operator is defined as deleted unless is_move_constructible_v<E> is true and is_move_assignable_v<E> is true.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<void, int>>);
+
+// !is_move_assignable_v<E>
+static_assert(!std::is_move_assignable_v<std::expected<void, NotMoveAssignable>>);
+
+// !is_move_constructible_v<E>
+static_assert(!std::is_move_assignable_v<std::expected<void, NotMoveConstructible>>);
+
+// 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<std::expected<void, int>>);
+
+// !is_nothrow_move_assignable_v<E>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<void, MoveAssignMayThrow>>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_nothrow_move_assignable_v<std::expected<void, MoveCtorMayThrow>>);
+
+constexpr bool test() {
+ // If this->has_value() && rhs.has_value() is true, no effects.
+ {
+ std::expected<void, int> e1;
+ std::expected<void, int> e2;
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<void, int>&>);
+ 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<void, Traced> e1;
+ std::expected<void, Traced> e2(std::unexpect, state, 5);
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ 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<void, Traced> e1(std::unexpect, state, 5);
+ std::expected<void, Traced> e2;
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e1);
+ assert(e1.has_value());
+
+ assert(state.dtorCalled);
+ }
+
+ // Otherwise, equivalent to unex = rhs.error().
+ {
+ Traced::state state{};
+ std::expected<void, Traced> e1(std::unexpect, state, 5);
+ std::expected<void, Traced> e2(std::unexpect, state, 10);
+ decltype(auto) x = (e1 = std::move(e2));
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e1);
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+
+ assert(state.moveAssignCalled);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<void, ThrowOnMoveConstruct> e1(std::in_place);
+ std::expected<void, ThrowOnMoveConstruct> e2(std::unexpect);
+ try {
+ e1 = std::move(e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ testException();
+ 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
index 0000000000000..3d8466dbc082f
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class G>
+// constexpr expected& operator=(const unexpected<G>& e);
+//
+// Let GF be const G&
+//
+// Constraints: is_constructible_v<E, GF> is true and is_assignable_v<E&, GF> is true.
+//
+// Effects:
+// - If has_value() is true, equivalent to:
+// construct_at(addressof(unex), std::forward<GF>(e.error()));
+// has_val = false;
+// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+//
+// Returns: *this.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<std::expected<void, int>&, const std::unexpected<int>&>);
+
+// !is_constructible_v<E, GF>
+static_assert(
+ !std::is_assignable_v<std::expected<void, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
+
+// !is_assignable_v<E&, GF>
+static_assert(
+ !std::is_assignable_v<std::expected<void, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
+
+constexpr bool test() {
+ // - If has_value() is true, equivalent to:
+ // construct_at(addressof(unex), std::forward<GF>(e.error()));
+ // has_val = false;
+ {
+ Traced::state state{};
+ std::expected<void, Traced> e;
+ std::unexpected<Traced> un(std::in_place, state, 5);
+ decltype(auto) x = (e = un);
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e);
+ assert(!e.has_value());
+ assert(e.error().data_ == 5);
+
+ assert(state.copyCtorCalled);
+ }
+
+ // - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+ {
+ Traced::state state1{};
+ Traced::state state2{};
+ std::expected<void, Traced> e(std::unexpect, state1, 5);
+ std::unexpected<Traced> un(std::in_place, state2, 10);
+ decltype(auto) x = (e = un);
+ static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
+ assert(&x == &e);
+ assert(!e.has_value());
+ assert(e.error().data_ == 10);
+
+ assert(state1.copyAssignCalled);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
+ std::unexpected<ThrowOnCopyConstruct> un(std::in_place);
+ try {
+ e1 = un;
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ testException();
+ 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
index 0000000000000..e07fb5c000c83
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.move.pass.cpp
@@ -0,0 +1,199 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class G>
+// constexpr expected& operator=(unexpected<G>&& e);
+//
+// Let GF be G
+// Constraints:
+// - is_constructible_v<E, GF> is true; and
+// - is_assignable_v<E&, GF> is true; and
+// - is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
+// is_nothrow_move_constructible_v<E> is true.
+//
+// Effects:
+// - If has_value() is true, equivalent to:
+// reinit-expected(unex, val, std::forward<GF>(e.error()));
+// has_val = false;
+// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+// Returns: *this.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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::expected<int, int>&, std::unexpected<int>&&>);
+
+// !is_constructible_v<E, GF>
+static_assert(
+ !std::is_assignable_v<std::expected<int, NotMoveConstructible>&, std::unexpected<NotMoveConstructible>&&>);
+
+// !is_assignable_v<E&, GF>
+static_assert(!std::is_assignable_v<std::expected<int, NotMoveAssignable>&, std::unexpected<NotMoveAssignable>&&>);
+
+template <bool moveNoexcept, bool convertNoexcept>
+struct MaybeNoexcept {
+ explicit MaybeNoexcept(int) noexcept(convertNoexcept);
+ MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
+ MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
+ MaybeNoexcept& operator=(int);
+};
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<true, false>>&,
+ std::unexpected<int>&&>);
+
+// is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, true>>&,
+ std::unexpected<int>&&>);
+
+// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, true>, MaybeNoexcept<false, false>>&,
+ std::unexpected<int>&&>);
+
+// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
+// !is_nothrow_move_constructible_v<E>
+static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&,
+ std::unexpected<int>&&>);
+
+constexpr bool test() {
+ // - If has_value() is true, equivalent to:
+ // reinit-expected(unex, val, std::forward<GF>(e.error()));
+ // is_nothrow_constructible_v<E, GF>
+ //
+ // In this case, it should call the branch
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::forward<Args>(args)...);
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothNoexcept> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothNoexcept>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<E>
+ //
+ // In this case, it should call the branch
+ // T tmp(std::forward<Args>(args)...);
+ // destroy_at(addressof(oldval));
+ // construct_at(addressof(newval), std::move(tmp));
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, MoveNoexceptConvThrow> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, MoveNoexceptConvThrow>&>);
+ 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<GF>(e.error()));
+ // !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<E>
+ // is_nothrow_move_constructible_v<T>
+ //
+ // 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>(args)...);
+ // } catch (...) {
+ // construct_at(addressof(oldval), std::move(tmp));
+ // throw;
+ // }
+ {
+ BothNoexcept::state oldState{};
+ std::expected<BothNoexcept, BothMayThrow> e(std::in_place, oldState, 5);
+ std::unexpected<int> un(10);
+ decltype(auto) x = (e = std::move(un));
+ static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothMayThrow>&>);
+ assert(&x == &e);
+
+ assert(oldState.moveCtorCalled);
+ assert(oldState.dtorCalled);
+ assert(e.error().movedFromInt);
+ }
+
+ // Otherwise, equivalent to: unex = std::forward<GF>(e.error());
+ {
+ Traced::state oldState{};
+ Traced::state newState{};
+ std::expected<int, Traced> e1(std::unexpect, oldState, 5);
+ std::unexpected<Traced> e(std::in_place, newState, 10);
+ decltype(auto) x = (e1 = std::move(e));
+ static_assert(std::same_as<decltype(x), std::expected<int, Traced >&>);
+ assert(&x == &e1);
+
+ assert(!e1.has_value());
+ assert(e1.error().data_ == 10);
+ assert(oldState.moveAssignCalled);
+ }
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::expected<void, ThrowOnMoveConstruct> e1(std::in_place);
+ std::unexpected<ThrowOnMoveConstruct> un(std::in_place);
+ try {
+ e1 = std::move(un);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..b3aa5f70f962a
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/assign/emplace.pass.cpp
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// constexpr void emplace() noexcept;
+//
+// Effects: If has_value() is false, destroys unex and sets has_val to true.
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+template <class T>
+concept EmplaceNoexcept =
+ requires(T t) {
+ { t.emplace() } noexcept;
+ };
+static_assert(!EmplaceNoexcept<int>);
+
+static_assert(EmplaceNoexcept<std::expected<void, int>>);
+
+constexpr bool test() {
+ // has_value
+ {
+ std::expected<void, int> e;
+ e.emplace();
+ assert(e.has_value());
+ }
+
+ // !has_value
+ {
+ Traced::state state{};
+ std::expected<int, Traced> 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
index 0000000000000..40f8efa5f94bf
--- /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<class U, class G>
+// constexpr explicit(!is_convertible_v<const G&, E>) expected(const expected<U, G>& rhs);
+//
+// Let GF be const G&
+//
+// Constraints:
+// - is_void_v<U> is true; and
+// - is_constructible_v<E, GF> is true; and
+// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
+//
+// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::forward<GF>(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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Constraints:
+template <class T1, class Err1, class T2, class Err2>
+concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, const std::expected<T2, Err2>&>;
+
+struct CtorFromInt {
+ CtorFromInt(int);
+};
+
+static_assert(canCstrFromExpected<void, CtorFromInt, void, int>);
+
+struct NoCtorFromInt {};
+
+// !is_void_v<E>
+static_assert(!canCstrFromExpected<void, int, int, int>);
+
+// !is_constructible_v<E, GF>
+static_assert(!canCstrFromExpected<void, NoCtorFromInt, void, int>);
+
+template <class T>
+struct CtorFrom {
+ explicit CtorFrom(int)
+ requires(!std::same_as<T, int>);
+ explicit CtorFrom(T);
+ explicit CtorFrom(auto&&) = delete;
+};
+
+// Note for below 4 tests, because their E is constructible from cvref of std::expected<void, int>,
+// unexpected<E> will be constructible from cvref of std::expected<void, int>
+// is_constructible_v<unexpected<E>, expected<U, G>&>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int>&>, void, int>);
+
+// is_constructible_v<unexpected<E>, expected<U, G>>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int>&&>, void, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int> const&>, void, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int> const&&>, void, int>);
+
+// test explicit
+static_assert(std::is_convertible_v<const std::expected<void, int>&, std::expected<void, long>>);
+
+// !is_convertible_v<GF, E>.
+static_assert(std::is_constructible_v<std::expected<void, CtorFrom<int>>, const std::expected<void, int>&>);
+static_assert(!std::is_convertible_v<const std::expected<void, int>&, std::expected<void, CtorFrom<int>>>);
+
+struct Data {
+ int i;
+ constexpr Data(int ii) : i(ii) {}
+};
+
+constexpr bool test() {
+ // convert the error
+ {
+ const std::expected<void, int> e1(std::unexpect, 5);
+ std::expected<void, Data> 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<void, int> e1(std::unexpect);
+ try {
+ [[maybe_unused]] std::expected<void, ThrowingInt> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..b28fc7a03bb34
--- /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<class U, class G>
+// constexpr explicit(!is_convertible_v<G, E>) expected(expected<U, G>&& rhs);
+//
+// Let GF be G
+//
+// Constraints:
+// - is_void_v<U> is true; and
+// - is_constructible_v<E, GF> is true; and
+// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
+// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
+//
+// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::forward<GF>(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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+template <class T1, class Err1, class T2, class Err2>
+concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, std::expected<T2, Err2>&&>;
+
+struct CtorFromInt {
+ CtorFromInt(int);
+};
+
+static_assert(canCstrFromExpected<void, CtorFromInt, void, int>);
+
+struct NoCtorFromInt {};
+
+// !is_void_v<U>
+static_assert(!canCstrFromExpected<void, int, int, int>);
+
+// !is_constructible_v<E, GF>
+static_assert(!canCstrFromExpected<void, NoCtorFromInt, void, int>);
+
+template <class T>
+struct CtorFrom {
+ explicit CtorFrom(int)
+ requires(!std::same_as<T, int>);
+ explicit CtorFrom(T);
+ explicit CtorFrom(auto&&) = delete;
+};
+
+// Note for below 4 tests, because their E is constructible from cvref of std::expected<void, int>,
+// unexpected<E> will be constructible from cvref of std::expected<void, int>
+// is_constructible_v<unexpected<E>, expected<U, G>&>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int>&>, void, int>);
+
+// is_constructible_v<unexpected<E>, expected<U, G>>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int>&&>, void, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int> const&>, void, int>);
+
+// is_constructible_v<unexpected<E>, const expected<U, G>>
+static_assert(!canCstrFromExpected<void, CtorFrom<std::expected<void, int> const&&>, void, int>);
+
+// test explicit
+static_assert(std::is_convertible_v<std::expected<void, int>&&, std::expected<void, long>>);
+
+// !is_convertible_v<GF, E>.
+static_assert(std::is_constructible_v<std::expected<void, CtorFrom<int>>, std::expected<void, int>&&>);
+static_assert(!std::is_convertible_v<std::expected<void, int>&&, std::expected<void, CtorFrom<int>>>);
+
+struct Data {
+ MoveOnly data;
+ constexpr Data(MoveOnly&& m) : data(std::move(m)) {}
+};
+
+constexpr bool test() {
+ // convert the error
+ {
+ std::expected<void, MoveOnly> e1(std::unexpect, 5);
+ std::expected<void, Data> 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<void, int> e1(std::unexpect);
+ try {
+ [[maybe_unused]] std::expected<void, ThrowingInt> e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..f11fb737aea31
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.copy.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+// 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<E> is true.
+// - This constructor is trivial if is_trivially_copy_constructible_v<E> is true.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<E> is true.
+static_assert(std::is_copy_constructible_v<std::expected<void, int>>);
+static_assert(std::is_copy_constructible_v<std::expected<void, CopyableNonTrivial>>);
+static_assert(!std::is_copy_constructible_v<std::expected<void, NonCopyable>>);
+
+// Test: This constructor is trivial if is_trivially_copy_constructible_v<E> is true.
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_copy_constructible_v<std::expected<void, int>>);
+#endif
+static_assert(!std::is_trivially_copy_constructible_v<std::expected<void, CopyableNonTrivial>>);
+
+constexpr bool test() {
+ // copy the error non-trivial
+ {
+ const std::expected<void, CopyableNonTrivial> e1(std::unexpect, 5);
+ auto e2 = e1;
+ assert(!e2.has_value());
+ assert(e2.error().i == 5);
+ }
+
+ // copy the error trivial
+ {
+ const std::expected<void, int> 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<void, Throwing> e1(std::unexpect);
+ try {
+ [[maybe_unused]] auto e2 = e1;
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..e05cf027719b7
--- /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 <cassert>
+#include <expected>
+#include <type_traits>
+
+#include "test_macros.h"
+
+// Test noexcept
+
+struct NoDefaultCtor {
+ constexpr NoDefaultCtor() = delete;
+};
+
+static_assert(std::is_nothrow_default_constructible_v<std::expected<void, int>>);
+static_assert(std::is_nothrow_default_constructible_v<std::expected<void, NoDefaultCtor>>);
+
+struct MyInt {
+ int i;
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+constexpr bool test() {
+ // default constructible
+ {
+ std::expected<void, int> e;
+ assert(e.has_value());
+ }
+
+ // non-default constructible
+ {
+ std::expected<void, NoDefaultCtor> 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
index 0000000000000..848e61dd60779
--- /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 <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+// test explicit
+static_assert(std::is_constructible_v<std::expected<void, int>, std::in_place_t>);
+static_assert(!std::is_convertible_v<std::in_place_t, std::expected<void, int>>);
+
+// test noexcept
+static_assert(std::is_nothrow_constructible_v<std::expected<void, int>, std::in_place_t>);
+
+constexpr bool test() {
+ std::expected<void, int> 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
index 0000000000000..f1c42f44528a5
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+// 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<E>);
+//
+// Constraints: is_move_constructible_v<E> 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<E> is true.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<E> is true.
+static_assert(std::is_move_constructible_v<std::expected<void, int>>);
+static_assert(std::is_move_constructible_v<std::expected<void, MovableNonTrivial>>);
+static_assert(!std::is_move_constructible_v<std::expected<void, NonMovable>>);
+
+// Test: This constructor is trivial if is_trivially_move_constructible_v<E> is true.
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_move_constructible_v<std::expected<void, int>>);
+#endif
+static_assert(!std::is_trivially_move_constructible_v<std::expected<void, MovableNonTrivial>>);
+
+// Test: noexcept(is_nothrow_move_constructible_v<E>)
+static_assert(std::is_nothrow_move_constructible_v<std::expected<int, int>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, int>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<int, MoveMayThrow>>);
+static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, MoveMayThrow>>);
+
+constexpr bool test() {
+ // move the error non-trivial
+ {
+ std::expected<void, MovableNonTrivial> 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<void, int> 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<void, Throwing> e1(std::unexpect);
+ try {
+ [[maybe_unused]] auto e2 = std::move(e1);
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..cdf32e68ceac3
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect.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<class... Args>
+// constexpr explicit expected(unexpect_t, Args&&... args);
+//
+// Constraints: is_constructible_v<E, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(std::is_constructible_v<std::expected<void, int>, std::unexpect_t>);
+static_assert(std::is_constructible_v<std::expected<void, int>, std::unexpect_t, int>);
+
+// !is_constructible_v<T, Args...>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<void, foo>, std::unexpect_t, int>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(!ImplicitlyConstructible<std::expected<void, int>, std::unexpect_t>);
+static_assert(!ImplicitlyConstructible<std::expected<void, int>, 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 <class T>
+constexpr void testInt() {
+ std::expected<void, T> e(std::unexpect, 5);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+template <class T>
+constexpr void testLValue() {
+ T t(5);
+ std::expected<void, T> e(std::unexpect, t);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+template <class T>
+constexpr void testRValue() {
+ std::expected<void, T> e(std::unexpect, T(5));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<CopyOnly>();
+ testInt<MoveOnly>();
+ testLValue<int>();
+ testLValue<CopyOnly>();
+ testRValue<int>();
+ testRValue<MoveOnly>();
+
+ // no arg
+ {
+ std::expected<void, int> e(std::unexpect);
+ assert(!e.has_value());
+ assert(e.error() == 0);
+ }
+
+ // one arg
+ {
+ std::expected<void, int> e(std::unexpect, 5);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+ }
+
+ // multi args
+ {
+ std::expected<void, std::tuple<int, short, MoveOnly>> e(std::unexpect, 1, 2, MoveOnly(3));
+ assert(!e.has_value());
+ assert((e.error() == std::tuple<int, short, MoveOnly>(1, 2, MoveOnly(3))));
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<void, Throwing> u(std::unexpect, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..4115eadc696a2
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/ctor/ctor.unexpect_init_list.pass.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// template<class U, class... Args>
+// constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
+//
+// Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
+//
+// Effects: Direct-non-list-initializes unex with il, std::forward<Args>(args)....
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <algorithm>
+#include <cassert>
+#include <expected>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints:
+static_assert(
+ std::is_constructible_v<std::expected<void, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
+
+// !is_constructible_v<T, initializer_list<U>&, Args...>
+static_assert(!std::is_constructible_v<std::expected<void, int>, std::unexpect_t, std::initializer_list<int>>);
+
+// test explicit
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+static_assert(ImplicitlyConstructible<int, int>);
+
+static_assert(
+ !ImplicitlyConstructible<std::expected<void, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
+
+template <class... Ts>
+struct Data {
+ std::vector<int> vec_;
+ std::tuple<Ts...> tuple_;
+
+ template <class... Us>
+ constexpr Data(std::initializer_list<int> il, Us&&... us) : vec_(il), tuple_(std::forward<Us>(us)...) {}
+};
+
+constexpr bool test() {
+ // no arg
+ {
+ std::expected<void, Data<>> 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<void, Data<MoveOnly>> 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<void, Data<int&, int&&, MoveOnly>> 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>, int) { throw Except{}; };
+ };
+
+ try {
+ std::expected<void, Throwing> u(std::unexpect, {1, 2}, 5);
+ assert(false);
+ } catch (Except) {
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..89e1c9275e3e0
--- /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<class G>
+// constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
+//
+// Let GF be const G&
+//
+// Constraints: is_constructible_v<E, GF> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints
+static_assert(std::is_constructible_v<std::expected<void, int>, const std::unexpected<int>&>);
+
+// !is_constructible_v<E, GF>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<void, int>, const std::unexpected<foo>&>);
+static_assert(!std::is_constructible_v<std::expected<void, MoveOnly>, const std::unexpected<MoveOnly>&>);
+
+// explicit(!is_convertible_v<const G&, E>)
+struct NotConvertible {
+ explicit NotConvertible(int);
+};
+static_assert(std::is_convertible_v<const std::unexpected<int>&, std::expected<void, int>>);
+static_assert(!std::is_convertible_v<const std::unexpected<int>&, std::expected<void, NotConvertible>>);
+
+struct MyInt {
+ int i;
+ constexpr MyInt(int ii) : i(ii) {}
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+template <class T>
+constexpr void testUnexpected() {
+ const std::unexpected<int> u(5);
+ std::expected<void, T> e(u);
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr bool test() {
+ testUnexpected<int>();
+ testUnexpected<MyInt>();
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; }
+ };
+
+ {
+ const std::unexpected<int> u(5);
+ try {
+ [[maybe_unused]] std::expected<void, Throwing> e(u);
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..2ddcb63c085f0
--- /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<class G>
+// constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
+//
+// Let GF be G
+//
+// Constraints: is_constructible_v<E, GF> is true.
+//
+// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
+//
+// Postconditions: has_value() is false.
+//
+// Throws: Any exception thrown by the initialization of unex.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+// Test Constraints
+static_assert(std::is_constructible_v<std::expected<void, int>, std::unexpected<int>>);
+static_assert(std::is_constructible_v<std::expected<void, MoveOnly>, std::unexpected<MoveOnly>>);
+
+// !is_constructible_v<E, GF>
+struct foo {};
+static_assert(!std::is_constructible_v<std::expected<void, int>, std::unexpected<foo>>);
+
+// explicit(!is_convertible_v<G, E>)
+struct NotConvertible {
+ explicit NotConvertible(int);
+};
+static_assert(std::is_convertible_v<std::unexpected<int>&&, std::expected<void, int>>);
+static_assert(!std::is_convertible_v<std::unexpected<int>&&, std::expected<void, NotConvertible>>);
+
+struct MyInt {
+ int i;
+ constexpr MyInt(int ii) : i(ii) {}
+ friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
+};
+
+template <class Err>
+constexpr void testInt() {
+ std::unexpected<int> u(5);
+ std::expected<void, Err> e(std::move(u));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+}
+
+constexpr void testMoveOnly() {
+ std::unexpected<MoveOnly> u(MoveOnly(5));
+ std::expected<void, MoveOnly> e(std::move(u));
+ assert(!e.has_value());
+ assert(e.error() == 5);
+ assert(u.error() == 0);
+}
+
+constexpr bool test() {
+ testInt<int>();
+ testInt<MyInt>();
+ testInt<MoveOnly>();
+ testMoveOnly();
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Except {};
+
+ struct Throwing {
+ Throwing(int) { throw Except{}; }
+ };
+
+ {
+ std::unexpected<int> u(5);
+ try {
+ [[maybe_unused]] std::expected<void, Throwing> e(std::move(u));
+ assert(false);
+ } catch (Except) {
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..855d585756317
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/dtor.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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// constexpr ~expected();
+//
+// Effects: If has_value() is false, destroys unex.
+//
+// Remarks: If is_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test Remarks: If is_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.
+struct NonTrivial {
+ ~NonTrivial() {}
+};
+
+#if __cpp_concepts >= 202002
+static_assert(std::is_trivially_destructible_v<std::expected<void, int>>);
+#endif
+static_assert(!std::is_trivially_destructible_v<std::expected<void, NonTrivial>>);
+
+struct TrackedDestroy {
+ bool& destroyed;
+ constexpr TrackedDestroy(bool& b) : destroyed(b) {}
+ constexpr ~TrackedDestroy() { destroyed = true; }
+};
+
+constexpr bool test() {
+ // has value
+ { [[maybe_unused]] std::expected<void, TrackedDestroy> e(std::in_place); }
+
+ // has error
+ {
+ bool errorDestroyed = false;
+ { [[maybe_unused]] std::expected<void, TrackedDestroy> 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
index 0000000000000..eb05a84643211
--- /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<class T2, class E2> requires (is_void_v<T2>)
+// friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test constraint
+template <class T1, class T2>
+concept CanCompare = requires(T1 t1, T2 t2) { t1 == t2; };
+
+struct Foo{};
+static_assert(!CanCompare<Foo, Foo>);
+
+static_assert(CanCompare<std::expected<void, int>, std::expected<void, int>>);
+static_assert(CanCompare<std::expected<void, int>, std::expected<void, short>>);
+
+// Note this is true because other overloads in expected<non-void> are unconstrained
+static_assert(CanCompare<std::expected<void, int>, std::expected<int, int>>);
+
+constexpr bool test() {
+ // x.has_value() && y.has_value()
+ {
+ const std::expected<void, int> e1;
+ const std::expected<void, int> e2;
+ assert(e1 == e2);
+ }
+
+ // !x.has_value() && y.has_value()
+ {
+ const std::expected<void, int> e1(std::unexpect, 5);
+ const std::expected<void, int> e2;
+ assert(e1 != e2);
+ }
+
+ // x.has_value() && !y.has_value()
+ {
+ const std::expected<void, int> e1;
+ const std::expected<void, int> e2(std::unexpect, 10);
+ const std::expected<void, int> e3(std::unexpect, 5);
+ assert(e1 != e2);
+ assert(e1 != e3);
+ }
+
+ // !x.has_value() && !y.has_value()
+ {
+ const std::expected<void, int> e1(std::unexpect, 5);
+ const std::expected<void, int> e2(std::unexpect, 10);
+ const std::expected<void, int> 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
index 0000000000000..ce95d162b55b1
--- /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<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#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<void, Data> e1;
+ std::unexpected<int> un2(10);
+ std::unexpected<int> un3(5);
+ assert(e1 != un2);
+ assert(e1 != un3);
+ }
+
+ // !x.has_value()
+ {
+ const std::expected<void, Data> e1(std::unexpect, 5);
+ std::unexpected<int> un2(10);
+ std::unexpected<int> 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
index 0000000000000..42e9f22969663
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept OpBoolNoexcept =
+ requires(T t) {
+ { static_cast<bool>(t) } noexcept;
+ };
+
+struct Foo {};
+static_assert(!OpBoolNoexcept<Foo>);
+
+static_assert(OpBoolNoexcept<std::expected<void, int>>);
+static_assert(OpBoolNoexcept<const std::expected<void, int>>);
+
+// Test explicit
+static_assert(!std::is_convertible_v<std::expected<void, int>, bool>);
+
+constexpr bool test() {
+ // has_value
+ {
+ const std::expected<void, int> e;
+ assert(static_cast<bool>(e));
+ }
+
+ // !has_value
+ {
+ const std::expected<void, int> e(std::unexpect, 5);
+ assert(!static_cast<bool>(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
index 0000000000000..536f8980c27a4
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept DerefNoexcept =
+ requires(T t) {
+ { std::forward<T>(t).operator*() } noexcept;
+ };
+
+static_assert(!DerefNoexcept<int>);
+
+static_assert(DerefNoexcept<std::expected<void, int>>);
+
+constexpr bool test() {
+ const std::expected<void, int> e;
+ *e;
+ static_assert(std::is_same_v<decltype(*e), void>);
+
+ 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
index 0000000000000..f7be7607aede3
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/observers/error.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 E& error() const & noexcept;
+// constexpr E& error() & noexcept;
+// constexpr E&& error() && noexcept;
+// constexpr const E&& error() const && noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept ErrorNoexcept =
+ requires(T t) {
+ { std::forward<T>(t).error() } noexcept;
+ };
+
+static_assert(!ErrorNoexcept<int>);
+
+static_assert(ErrorNoexcept<std::expected<void, int>&>);
+static_assert(ErrorNoexcept<const std::expected<void, int>&>);
+static_assert(ErrorNoexcept<std::expected<void, int>&&>);
+static_assert(ErrorNoexcept<const std::expected<void, int>&&>);
+
+constexpr bool test() {
+ // non-const &
+ {
+ std::expected<void, int> e(std::unexpect, 5);
+ decltype(auto) x = e.error();
+ static_assert(std::same_as<decltype(x), int&>);
+ assert(x == 5);
+ }
+
+ // const &
+ {
+ const std::expected<void, int> e(std::unexpect, 5);
+ decltype(auto) x = e.error();
+ static_assert(std::same_as<decltype(x), const int&>);
+ assert(x == 5);
+ }
+
+ // non-const &&
+ {
+ std::expected<void, int> e(std::unexpect, 5);
+ decltype(auto) x = std::move(e).error();
+ static_assert(std::same_as<decltype(x), int&&>);
+ assert(x == 5);
+ }
+
+ // const &&
+ {
+ const std::expected<void, int> e(std::unexpect, 5);
+ decltype(auto) x = std::move(e).error();
+ static_assert(std::same_as<decltype(x), const int&&>);
+ 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
index 0000000000000..42a173d60c898
--- /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 <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// Test noexcept
+template <class T>
+concept HasValueNoexcept =
+ requires(T t) {
+ { t.has_value() } noexcept;
+ };
+
+struct Foo {};
+static_assert(!HasValueNoexcept<Foo>);
+
+static_assert(HasValueNoexcept<std::expected<int, int>>);
+static_assert(HasValueNoexcept<const std::expected<int, int>>);
+
+constexpr bool test() {
+ // has_value
+ {
+ const std::expected<void, int> e;
+ assert(e.has_value());
+ }
+
+ // !has_value
+ {
+ const std::expected<void, int> 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
index 0000000000000..0f02db19c7b75
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.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
+
+// constexpr void value() const &;
+// constexpr void value() &&;
+
+#include <cassert>
+#include <concepts>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ // const &
+ {
+ const std::expected<void, int> e;
+ e.value();
+ static_assert(std::is_same_v<decltype(e.value()), void>);
+ }
+
+ // &
+ {
+ std::expected<void, int> e;
+ e.value();
+ static_assert(std::is_same_v<decltype(e.value()), void>);
+ }
+
+ // &&
+ {
+ std::expected<void, int> e;
+ std::move(e).value();
+ static_assert(std::is_same_v<decltype(std::move(e).value()), void>);
+ }
+
+ // const &&
+ {
+ const std::expected<void, int> e;
+ std::move(e).value();
+ static_assert(std::is_same_v<decltype(std::move(e).value()), void>);
+ }
+
+ return true;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+
+ // int
+ {
+ const std::expected<void, int> e(std::unexpect, 5);
+ try {
+ e.value();
+ assert(false);
+ } catch (const std::bad_expected_access<int>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+ // MoveOnly
+ {
+ std::expected<void, MoveOnly> e(std::unexpect, 5);
+ try {
+ std::move(e).value();
+ assert(false);
+ } catch (const std::bad_expected_access<MoveOnly>& ex) {
+ assert(ex.error() == 5);
+ }
+ }
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+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
index 0000000000000..0f5821ec4ad69
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp
@@ -0,0 +1,164 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, clang-15, apple-clang-14
+
+// friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(swap(x,y)));
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+// Test constraint
+static_assert(std::is_swappable_v<std::expected<void, int>>);
+
+struct NotSwappable {
+ NotSwappable& operator=(const NotSwappable&) = delete;
+};
+void swap(NotSwappable&, NotSwappable&) = delete;
+
+// !is_swappable_v<E>
+static_assert(!std::is_swappable_v<std::expected<void, NotSwappable>>);
+
+struct NotMoveContructible {
+ NotMoveContructible(NotMoveContructible&&) = delete;
+ friend void swap(NotMoveContructible&, NotMoveContructible&) {}
+};
+
+// !is_move_constructible_v<E>
+static_assert(!std::is_swappable_v<std::expected<void, NotMoveContructible>>);
+
+// Test noexcept
+struct MoveMayThrow {
+ MoveMayThrow(MoveMayThrow&&) noexcept(false);
+ friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
+};
+
+template <class E>
+concept FreeSwapNoexcept =
+ requires(std::expected<void, E> x, std::expected<void, E> y) {
+ { swap(x, y) } noexcept;
+ };
+
+static_assert(FreeSwapNoexcept<int>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!FreeSwapNoexcept<MoveMayThrow>);
+
+struct SwapMayThrow {
+ friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
+};
+
+// !is_nothrow_swappable_v<E>
+static_assert(!FreeSwapNoexcept<SwapMayThrow>);
+
+constexpr bool test() {
+ // this->has_value() && rhs.has_value()
+ {
+ std::expected<void, int> x;
+ std::expected<void, int> y;
+ swap(x, y);
+
+ assert(x.has_value());
+ assert(y.has_value());
+ }
+
+ // !this->has_value() && !rhs.has_value()
+ {
+ std::expected<void, ADLSwap> x(std::unexpect, 5);
+ std::expected<void, ADLSwap> 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<void, Traced> e1(std::in_place);
+ std::expected<void, Traced> 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<void, Traced> e1(std::unexpect, s, 10);
+ std::expected<void, Traced> 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;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ // !e1.has_value() && e2.has_value()
+ {
+ bool e1Destroyed = false;
+ std::expected<void, ThrowOnMove> e1(std::unexpect, e1Destroyed);
+ std::expected<void, ThrowOnMove> e2(std::in_place);
+ try {
+ swap(e1, e2);
+ assert(false);
+ } catch (Except) {
+ assert(!e1.has_value());
+ assert(e2.has_value());
+ assert(!e1Destroyed);
+ }
+ }
+
+ // e1.has_value() && !e2.has_value()
+ {
+ bool e2Destroyed = false;
+ std::expected<void, ThrowOnMove> e1(std::in_place);
+ std::expected<void, ThrowOnMove> e2(std::unexpect, e2Destroyed);
+ try {
+ swap(e1, e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(!e2.has_value());
+ assert(!e2Destroyed);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ testException();
+ 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
index 0000000000000..247d92a51dc0c
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp
@@ -0,0 +1,173 @@
+//===----------------------------------------------------------------------===//
+// 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
+// Older Clangs do not support the C++20 feature to constrain destructors
+// XFAIL: clang-14, apple-clang-14
+
+// constexpr void swap(expected& rhs) noexcept(see below);
+//
+// Constraints:
+// is_swappable_v<E> is true and is_move_constructible_v<E> is true.
+//
+// Throws: Any exception thrown by the expressions in the Effects.
+//
+// Remarks: The exception specification is equivalent to:
+// is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>.
+
+#include <cassert>
+#include <expected>
+#include <type_traits>
+#include <utility>
+
+#include "../../types.h"
+#include "test_macros.h"
+
+// Test Constraints:
+template <class E>
+concept HasMemberSwap = requires(std::expected<void, E> x, std::expected<void, E> y) { x.swap(y); };
+
+static_assert(HasMemberSwap<int>);
+
+struct NotSwappable {};
+void swap(NotSwappable&, NotSwappable&) = delete;
+
+// !is_swappable_v<E>
+static_assert(!HasMemberSwap<NotSwappable>);
+
+struct NotMoveContructible {
+ NotMoveContructible(NotMoveContructible&&) = delete;
+ friend void swap(NotMoveContructible&, NotMoveContructible&) {}
+};
+
+// !is_move_constructible_v<E>
+static_assert(!HasMemberSwap<NotMoveContructible>);
+
+// Test noexcept
+struct MoveMayThrow {
+ MoveMayThrow(MoveMayThrow&&) noexcept(false);
+ friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
+};
+
+template <class E>
+concept MemberSwapNoexcept =
+ requires(std::expected<void, E> x, std::expected<void, E> y) {
+ { x.swap(y) } noexcept;
+ };
+
+static_assert(MemberSwapNoexcept<int>);
+
+// !is_nothrow_move_constructible_v<E>
+static_assert(!MemberSwapNoexcept<MoveMayThrow>);
+
+struct SwapMayThrow {
+ friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
+};
+
+// !is_nothrow_swappable_v<E>
+static_assert(!MemberSwapNoexcept<SwapMayThrow>);
+
+constexpr bool test() {
+ // this->has_value() && rhs.has_value()
+ {
+ std::expected<void, int> x;
+ std::expected<void, int> y;
+ x.swap(y);
+
+ assert(x.has_value());
+ assert(y.has_value());
+ }
+
+ // !this->has_value() && !rhs.has_value()
+ {
+ std::expected<void, ADLSwap> x(std::unexpect, 5);
+ std::expected<void, ADLSwap> 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<void, Traced> e1(std::in_place);
+ std::expected<void, Traced> 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<void, Traced> e1(std::unexpect, s, 10);
+ std::expected<void, Traced> 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;
+}
+
+void testException() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ // !e1.has_value() && e2.has_value()
+ {
+ bool e1Destroyed = false;
+ std::expected<void, ThrowOnMove> e1(std::unexpect, e1Destroyed);
+ std::expected<void, ThrowOnMove> e2(std::in_place);
+ try {
+ e1.swap(e2);
+ assert(false);
+ } catch (Except) {
+ assert(!e1.has_value());
+ assert(e2.has_value());
+ assert(!e1Destroyed);
+ }
+ }
+
+ // e1.has_value() && !e2.has_value()
+ {
+ bool e2Destroyed = false;
+ std::expected<void, ThrowOnMove> e1(std::in_place);
+ std::expected<void, ThrowOnMove> e2(std::unexpect, e2Destroyed);
+ try {
+ e1.swap(e2);
+ assert(false);
+ } catch (Except) {
+ assert(e1.has_value());
+ assert(!e2.has_value());
+ assert(!e2Destroyed);
+ }
+ }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ testException();
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/expected/types.h b/libcxx/test/std/utilities/expected/types.h
new file mode 100644
index 0000000000000..278ab0f0ec746
--- /dev/null
+++ b/libcxx/test/std/utilities/expected/types.h
@@ -0,0 +1,145 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <utility>
+#include "test_macros.h"
+
+template <bool copyMoveNoexcept, bool convertNoexcept = true>
+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<false>;
+using TracedNoexcept = TracedBase<true>;
+
+using MoveThrowConvNoexcept = TracedBase<false, true>;
+using MoveNoexceptConvThrow = TracedBase<true, false>;
+using BothMayThrow = TracedBase<false, false>;
+using BothNoexcept = TracedBase<true, true>;
+
+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 <bool Noexcept>
+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;
+ }
+};
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct Except {};
+
+struct ThrowOnCopyConstruct {
+ ThrowOnCopyConstruct() = default;
+ ThrowOnCopyConstruct(const ThrowOnCopyConstruct&) { throw Except{}; }
+ ThrowOnCopyConstruct& operator=(const ThrowOnCopyConstruct&) = default;
+};
+
+struct ThrowOnMoveConstruct {
+ ThrowOnMoveConstruct() = default;
+ ThrowOnMoveConstruct(ThrowOnMoveConstruct&&) { throw Except{}; }
+ ThrowOnMoveConstruct& operator=(ThrowOnMoveConstruct&&) = default;
+};
+
+struct ThrowOnConvert {
+ ThrowOnConvert() = default;
+ ThrowOnConvert(const int&) { throw Except{}; }
+ ThrowOnConvert(int&&) { throw Except{}; }
+ ThrowOnConvert(const ThrowOnConvert&) noexcept(false) {}
+ ThrowOnConvert& operator=(const ThrowOnConvert&) = default;
+ ThrowOnConvert(ThrowOnConvert&&) noexcept(false) {}
+ ThrowOnConvert& operator=(ThrowOnConvert&&) = default;
+};
+
+struct ThrowOnMove {
+ bool* destroyed = nullptr;
+ ThrowOnMove() = default;
+ ThrowOnMove(bool& d) : destroyed(&d) {}
+ ThrowOnMove(ThrowOnMove&&) { throw Except{}; };
+ ThrowOnMove& operator=(ThrowOnMove&&) = default;
+ ~ThrowOnMove() {
+ if (destroyed) {
+ *destroyed = true;
+ }
+ }
+};
+
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+#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
index 81086993a5f49..891981d45b8d6 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -308,6 +308,10 @@ def add_version_header(tc):
"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
index 6019abeb7f365..e96551d1f7ad3 100755
--- a/libcxx/utils/generate_header_inclusion_tests.py
+++ b/libcxx/utils/generate_header_inclusion_tests.py
@@ -68,6 +68,7 @@ def get_libcxx_paths():
"concepts": "20",
"coroutine": "20",
"cuchar": "11",
+ "expected": "23",
"filesystem": "17",
"initializer_list": "11",
"optional": "17",
More information about the libcxx-commits
mailing list