diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -17,7 +17,7 @@ | `[pairs.spec] `_,| `pair `_,[expos.only.func],Kent Ross,|Complete| | `[syserr.errcat.nonvirtuals] `_,| `error_category `_,[comparisons.three.way],Adrian Vogelsgesang,|Complete| | `[syserr.compare] `_,"| `error_code `_ -| `error_condition `_",None,Adrian Vogelsgesang,|In Progress| +| `error_condition `_",None,Adrian Vogelsgesang,|Complete| | `[tuple.rel] `_,| `tuple `_,[expos.only.func],Kent Ross,|Complete| "| `[optional.relops] `_ | `[optional.nullops] `_ diff --git a/libcxx/include/system_error b/libcxx/include/system_error --- a/libcxx/include/system_error +++ b/libcxx/include/system_error @@ -76,7 +76,6 @@ }; // non-member functions: -bool operator<(const error_code& lhs, const error_code& rhs) noexcept; template basic_ostream& operator<<(basic_ostream& os, const error_code& ec); @@ -103,8 +102,6 @@ explicit operator bool() const noexcept; }; -bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept; - class system_error : public runtime_error { @@ -129,12 +126,16 @@ // Comparison operators: bool operator==(const error_code& lhs, const error_code& rhs) noexcept; bool operator==(const error_code& lhs, const error_condition& rhs) noexcept; -bool operator==(const error_condition& lhs, const error_code& rhs) noexcept; +bool operator==(const error_condition& lhs, const error_code& rhs) noexcept; // removed in C++20 bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept; -bool operator!=(const error_code& lhs, const error_code& rhs) noexcept; -bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept; -bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept; -bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept; +bool operator!=(const error_code& lhs, const error_code& rhs) noexcept; // removed in C++20 +bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept; // removed in C++20 +bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept; // removed in C++20 +bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept; // removed in C++20 +bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept; // removed in C++20 +bool operator<(const error_code& lhs, const error_code& rhs) noexcept; // removed in C++20 +strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept; // C++20 +strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept; // C++20 template <> struct hash; template <> struct hash; @@ -314,14 +315,6 @@ return error_condition(static_cast(__e), generic_category()); } -inline _LIBCPP_INLINE_VISIBILITY -bool -operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT -{ - return __x.category() < __y.category() - || (__x.category() == __y.category() && __x.value() < __y.value()); -} - // error_code class _LIBCPP_TYPE_VIS error_code @@ -390,14 +383,6 @@ return error_code(static_cast(__e), generic_category()); } -inline _LIBCPP_INLINE_VISIBILITY -bool -operator<(const error_code& __x, const error_code& __y) _NOEXCEPT -{ - return __x.category() < __y.category() - || (__x.category() == __y.category() && __x.value() < __y.value()); -} - inline _LIBCPP_INLINE_VISIBILITY bool operator==(const error_code& __x, const error_code& __y) _NOEXCEPT @@ -413,12 +398,14 @@ || __y.category().equivalent(__x, __y.value()); } +#if _LIBCPP_STD_VER <= 17 inline _LIBCPP_INLINE_VISIBILITY bool operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT { return __y == __x; } +#endif inline _LIBCPP_INLINE_VISIBILITY bool @@ -427,6 +414,8 @@ return __x.category() == __y.category() && __x.value() == __y.value(); } +#if _LIBCPP_STD_VER <= 17 + inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT @@ -447,6 +436,42 @@ operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT {return !(__x == __y);} +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT +{ + return __x.category() < __y.category() + || (__x.category() == __y.category() && __x.value() < __y.value()); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const error_code& __x, const error_code& __y) _NOEXCEPT +{ + return __x.category() < __y.category() + || (__x.category() == __y.category() && __x.value() < __y.value()); +} + +#else // _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering +operator<=>(const error_code& __x, const error_code& __y) noexcept +{ + if (auto __c = __x.category() <=> __y.category(); __c != 0) + return __c; + return __x.value() <=> __y.value(); +} + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering +operator<=>(const error_condition& __x, const error_condition& __y) noexcept +{ + if (auto __c = __x.category() <=> __y.category(); __c != 0) + return __c; + return __x.value() <=> __y.value(); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <> struct _LIBCPP_TEMPLATE_VIS hash : public __unary_function diff --git a/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_code.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_code.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_code.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 + +// + +// class error_code + +// strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept + +#include +#include + +#include "test_macros.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertOrderAreNoexcept(); + AssertOrderReturn(); + + // Same error category + std::error_code ec1a = std::error_code(1, std::generic_category()); + std::error_code ec1b = std::error_code(1, std::generic_category()); + std::error_code ec2 = std::error_code(2, std::generic_category()); + + assert(testOrder(ec1a, ec1b, std::strong_ordering::equal)); + assert(testOrder(ec1a, ec2, std::strong_ordering::less)); + + // Different error category + const std::error_code& ec3 = std::error_code(2, std::system_category()); + + bool isLess = ec2 < ec3; + assert(testOrder(ec2, ec3, isLess ? std::strong_ordering::less : std::strong_ordering::greater)); + + return 0; +} diff --git a/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_condition.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_condition.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/diagnostics/syserr/syserr.compare/cmp_error_condition.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 + +// + +// class error_condition + +// strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept + +#include +#include + +#include "test_macros.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertOrderAreNoexcept(); + AssertOrderReturn(); + + // Same error category + std::error_condition ec1a = std::error_condition(1, std::generic_category()); + std::error_condition ec1b = std::error_condition(1, std::generic_category()); + std::error_condition ec2 = std::error_condition(2, std::generic_category()); + + assert(testOrder(ec1a, ec1b, std::strong_ordering::equal)); + assert(testOrder(ec1a, ec2, std::strong_ordering::less)); + + // Different error category + const std::error_condition& ec3 = std::error_condition(2, std::system_category()); + + bool isLess = ec2 < ec3; + assert(testOrder(ec2, ec3, isLess ? std::strong_ordering::less : std::strong_ordering::greater)); + + return 0; +}