diff --git a/stl/inc/system_error b/stl/inc/system_error index c500401a377..6329e6eda66 100644 --- a/stl/inc/system_error +++ b/stl/inc/system_error @@ -16,7 +16,11 @@ #include #ifndef _M_CEE_PURE #include -#endif +#endif // _M_CEE_PURE + +#if _HAS_CXX20 +#include +#endif // _HAS_CXX20 #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -90,13 +94,22 @@ public: return _Addr == _Right._Addr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const error_category& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 +// TRANSITION, GH-489 +#ifdef __cpp_lib_concepts + _NODISCARD strong_ordering operator<=>(const error_category& _Right) const noexcept { + return compare_three_way{}(_Addr, _Right._Addr); + } +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv _NODISCARD bool operator<(const error_category& _Right) const noexcept { return _Addr < _Right._Addr; } +#endif // !defined(__cpp_lib_concepts) error_category(const error_category&) = delete; error_category& operator=(const error_category&) = delete; @@ -173,6 +186,21 @@ public: return _System_error_equal(_Left, _Right); } +// TRANSITION, GH-489 +#ifdef __cpp_lib_concepts + _NODISCARD friend strong_ordering operator<=>(const error_code& _Left, const error_code& _Right) noexcept { + if (const auto _Result = _Left.category() <=> _Right.category(); _Result != 0) { + return _Result; + } + return _Left.value() <=> _Right.value(); + } +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv + _NODISCARD friend bool operator<(const error_code& _Left, const error_code& _Right) noexcept { + return _Left.category() < _Right.category() + || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); + } +#endif // !defined(__cpp_lib_concepts) +#if !_HAS_CXX20 _NODISCARD friend bool operator==(const error_condition& _Left, const error_code& _Right) noexcept { return _System_error_equal(_Right, _Left); } @@ -188,11 +216,7 @@ public: _NODISCARD friend bool operator!=(const error_condition& _Left, const error_code& _Right) noexcept { return !_System_error_equal(_Right, _Left); } - - _NODISCARD friend bool operator<(const error_code& _Left, const error_code& _Right) noexcept { - return _Left.category() < _Right.category() - || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); - } +#endif // !_HAS_CXX20 #endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS private: @@ -249,22 +273,36 @@ public: return _Left.category() == _Right.category() && _Left.value() == _Right.value(); } - _NODISCARD friend bool operator!=(const error_condition& _Left, const error_condition& _Right) noexcept { - return !(_Left == _Right); +// TRANSITION, GH-489 +#ifdef __cpp_lib_concepts + _NODISCARD friend strong_ordering operator<=>( + const error_condition& _Left, const error_condition& _Right) noexcept { + if (const auto _Result = _Left.category() <=> _Right.category(); _Result != 0) { + return _Result; + } + return _Left.value() <=> _Right.value(); } - +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv _NODISCARD friend bool operator<(const error_condition& _Left, const error_condition& _Right) noexcept { return _Left.category() < _Right.category() || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); } +#endif // !defined(__cpp_lib_concepts) +#if !_HAS_CXX20 + _NODISCARD friend bool operator!=(const error_condition& _Left, const error_condition& _Right) noexcept { + return !(_Left == _Right); + } +#endif // !_HAS_CXX20 // We grant friendship to the operators from error_code here to allow is_error_code_enum_v but not // is_error_condition_enum_v enums to be compared directly with error_condition; for example: // io_errc::stream == make_error_condition(errc::out_of_memory) friend bool operator==(const error_code& _Left, const error_condition& _Right) noexcept; +#if !_HAS_CXX20 friend bool operator==(const error_condition& _Left, const error_code& _Right) noexcept; friend bool operator!=(const error_code& _Left, const error_condition& _Right) noexcept; friend bool operator!=(const error_condition& _Left, const error_code& _Right) noexcept; +#endif // !_HAS_CXX20 #endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS private: @@ -285,14 +323,42 @@ _NODISCARD inline bool operator==(const error_code& _Left, const error_condition return _Left.category().equivalent(_Left.value(), _Right) || _Right.category().equivalent(_Left, _Right.value()); } -_NODISCARD inline bool operator==(const error_condition& _Left, const error_code& _Right) noexcept { - return _Right.category().equivalent(_Right.value(), _Left) || _Left.category().equivalent(_Right, _Left.value()); -} - _NODISCARD inline bool operator==(const error_condition& _Left, const error_condition& _Right) noexcept { return _Left.category() == _Right.category() && _Left.value() == _Right.value(); } +// TRANSITION, GH-489 +#ifdef __cpp_lib_concepts +_NODISCARD inline strong_ordering operator<=>(const error_code& _Left, const error_code& _Right) noexcept { + if (const auto _Result = _Left.category() <=> _Right.category(); _Result != 0) { + return _Result; + } + return _Left.value() <=> _Right.value(); +} + +_NODISCARD inline strong_ordering operator<=>(const error_condition& _Left, const error_condition& _Right) noexcept { + if (const auto _Result = _Left.category() <=> _Right.category(); _Result != 0) { + return _Result; + } + return _Left.value() <=> _Right.value(); +} +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv +_NODISCARD inline bool operator<(const error_code& _Left, const error_code& _Right) noexcept { + return _Left.category() < _Right.category() + || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); +} + +_NODISCARD inline bool operator<(const error_condition& _Left, const error_condition& _Right) noexcept { + return _Left.category() < _Right.category() + || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); +} +#endif // !defined(__cpp_lib_concepts) + +#if !_HAS_CXX20 +_NODISCARD inline bool operator==(const error_condition& _Left, const error_code& _Right) noexcept { + return _Right.category().equivalent(_Right.value(), _Left) || _Left.category().equivalent(_Right, _Left.value()); +} + _NODISCARD inline bool operator!=(const error_code& _Left, const error_code& _Right) noexcept { return !(_Left == _Right); } @@ -308,16 +374,7 @@ _NODISCARD inline bool operator!=(const error_condition& _Left, const error_code _NODISCARD inline bool operator!=(const error_condition& _Left, const error_condition& _Right) noexcept { return !(_Left == _Right); } - -_NODISCARD inline bool operator<(const error_code& _Left, const error_code& _Right) noexcept { - return _Left.category() < _Right.category() - || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); -} - -_NODISCARD inline bool operator<(const error_condition& _Left, const error_condition& _Right) noexcept { - return _Left.category() < _Right.category() - || (_Left.category() == _Right.category() && _Left.value() < _Right.value()); -} +#endif // !_HAS_CXX20 #endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS // VIRTUALS FOR error_category diff --git a/tests/std/tests/P1614R2_spaceship/env.lst b/tests/std/tests/P1614R2_spaceship/env.lst index f3ccc8613c6..20ea5fe3426 100644 --- a/tests/std/tests/P1614R2_spaceship/env.lst +++ b/tests/std/tests/P1614R2_spaceship/env.lst @@ -2,3 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception RUNALL_INCLUDE ..\concepts_matrix.lst +RUNALL_CROSSLIST +PM_CL="/D_STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS=0" +PM_CL="/D_STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS=1" diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index 7c76cee6b79..84160c9ece7 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,15 @@ namespace std { }; } // namespace std +struct dummy_diagnostic : std::error_category { + const char* name() const noexcept override { + return "dummy"; + } + std::string message(int) const override { + return ""; + } +}; + template void spaceship_test(const SmallType& smaller, const EqualType& smaller_equal, const LargeType& larger) { assert(smaller == smaller_equal); @@ -165,6 +175,36 @@ void unordered_containers_test( assert(something != different); } +template +void diagnostics_test() { + dummy_diagnostic c_mem[2]; + { + ErrorType e_smaller(0, c_mem[0]); + ErrorType e_equal(0, c_mem[0]); + ErrorType e_larger(1, c_mem[1]); + + spaceship_test(e_smaller, e_equal, e_larger); + } + { + ErrorType e_smaller(0, c_mem[0]); + ErrorType e_larger(0, c_mem[1]); + + assert(e_smaller < e_larger); + assert(!(e_larger < e_smaller)); + assert((e_smaller <=> e_larger) < 0); + assert((e_larger <=> e_smaller) > 0); + } + { + ErrorType e_smaller(0, c_mem[0]); + ErrorType e_larger(1, c_mem[0]); + + assert(e_smaller < e_larger); + assert(!(e_larger < e_smaller)); + assert((e_smaller <=> e_larger) < 0); + assert((e_larger <=> e_smaller) > 0); + } +} + void ordering_test_cases() { { // constexpr array constexpr std::array a0{{2, 8, 9, 1, 9}}; @@ -412,6 +452,35 @@ void ordering_test_cases() { static_assert(std::is_same_v, std::weak_ordering>); static_assert(std::is_same_v, std::partial_ordering>); } + { // Diagnostics Library + diagnostics_test(); + diagnostics_test(); + + dummy_diagnostic c_mem[2]; + { + std::error_code e1(0, c_mem[0]); + std::error_condition e2(0, c_mem[0]); + + assert(e1 == e2); + assert(e2 == e1); + } + { + std::error_code e1(0, c_mem[0]); + std::error_condition e2(0, c_mem[1]); + + assert(e1 != e2); + assert(e2 != e1); + } + { + std::error_code e1(1, c_mem[0]); + std::error_condition e2(0, c_mem[0]); + + assert(e1 != e2); + assert(e2 != e1); + } + + spaceship_test(c_mem[0], c_mem[0], c_mem[1]); + } } template