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 @@ -15,7 +15,7 @@ | `[type.info] `_,| `typeinfo `_,None,Adrian Vogelsgesang,|Complete| | `[coroutine.handle.compare] `_,| `coroutine_handle `_,[comparisons.three.way],Chuanqi Xu,|Complete| | `[pairs.spec] `_,| `pair `_,[expos.only.func],Kent Ross,|Complete| -| `[syserr.errcat.nonvirtuals] `_,| `error_category `_,[comparisons.three.way],Adrian Vogelsgesang,|In Progress| +| `[syserr.errcat.nonvirtuals] `_,| `error_category `_,[comparisons.three.way],Adrian Vogelsgesang,|Complete| | `[syserr.compare] `_,"| `error_code `_ | `error_condition `_",None,Adrian Vogelsgesang,|In Progress| | `[tuple.rel] `_,| `tuple `_,[expos.only.func],Kent Ross,|Complete| diff --git a/libcxx/include/system_error b/libcxx/include/system_error --- a/libcxx/include/system_error +++ b/libcxx/include/system_error @@ -32,8 +32,9 @@ virtual string message(int ev) const = 0; bool operator==(const error_category& rhs) const noexcept; - bool operator!=(const error_category& rhs) const noexcept; - bool operator<(const error_category& rhs) const noexcept; + bool operator!=(const error_category& rhs) const noexcept; // removed in C++20 + bool operator<(const error_category& rhs) const noexcept; // removed in C++20 + strong_ordering operator<=>(const error_category& rhs) const noexcept; // C++20 }; const error_category& generic_category() noexcept; @@ -147,6 +148,7 @@ #include <__errc> #include <__functional/hash.h> #include <__functional/unary_function.h> +#include <__memory/addressof.h> #include #include #include @@ -223,12 +225,21 @@ _LIBCPP_INLINE_VISIBILITY bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;} +#if _LIBCPP_STD_VER > 17 + + _LIBCPP_HIDE_FROM_ABI + strong_ordering operator<=>(const error_category& __rhs) const noexcept {return compare_three_way()(this, std::addressof(__rhs));} + +#else // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);} _LIBCPP_INLINE_VISIBILITY bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;} +#endif // _LIBCPP_STD_VER > 17 + friend class _LIBCPP_HIDDEN __do_message; }; diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.nonvirtuals/cmp.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.nonvirtuals/cmp.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.nonvirtuals/cmp.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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_category + +// strong_ordering operator<=>(const error_category& rhs) const noexcept; + +#include +#include + +#include "test_macros.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertOrderAreNoexcept(); + AssertOrderReturn(); + + const std::error_category& e_cat1 = std::generic_category(); + const std::error_category& e_cat2 = std::generic_category(); + const std::error_category& e_cat3 = std::system_category(); + + assert(testOrder(e_cat1, e_cat2, std::strong_ordering::equal)); + + bool isLess = e_cat1 < e_cat3; + assert(testOrder(e_cat1, e_cat3, isLess ? std::strong_ordering::less : std::strong_ordering::greater)); + + return 0; +}