From 4be779f59b04947324889b7e1488fb9a68c81d53 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 7 Feb 2020 20:50:00 +0000 Subject: [PATCH] libstdc++: Define operator<=> for types Another piece of P1614R2 for C++20. This also adds tests for operator< in C++11, which was present but untested. * include/std/system_error (error_category::operator<=>) (operator<=>(const error_code&, const error_code&)) (operator<=>(const error_condition&, const error_condition&)): Define for C++20. * testsuite/19_diagnostics/error_category/operators/less.cc: New test. * testsuite/19_diagnostics/error_category/operators/three_way.cc: New test. * testsuite/19_diagnostics/error_code/operators/equal.cc: Remove incorrect comment. * testsuite/19_diagnostics/error_code/operators/less.cc: New test. * testsuite/19_diagnostics/error_code/operators/not_equal.cc: Remove incorrect comment. * testsuite/19_diagnostics/error_code/operators/three_way.cc: New test. * testsuite/19_diagnostics/error_condition/operators/equal.cc: Remove incorrect comment. * testsuite/19_diagnostics/error_condition/operators/less.cc: New test. * testsuite/19_diagnostics/error_condition/operators/not_equal.cc: Remove incorrect comment. * testsuite/19_diagnostics/error_condition/operators/three_way.cc: New test. --- libstdc++-v3/ChangeLog | 21 +++++ libstdc++-v3/include/std/system_error | 79 +++++++++++++------ .../error_category/operators/less.cc | 30 +++++++ .../error_category/operators/three_way.cc | 48 +++++++++++ .../error_code/operators/equal.cc | 1 - .../error_code/operators/less.cc | 38 +++++++++ .../error_code/operators/not_equal.cc | 1 - .../error_code/operators/three_way.cc | 60 ++++++++++++++ .../error_condition/operators/equal.cc | 1 - .../error_condition/operators/less.cc | 38 +++++++++ .../error_condition/operators/not_equal.cc | 1 - .../error_condition/operators/three_way.cc | 60 ++++++++++++++ 12 files changed, 350 insertions(+), 28 deletions(-) create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_category/operators/less.cc create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_category/operators/three_way.cc create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_code/operators/less.cc create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_code/operators/three_way.cc create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/less.cc create mode 100644 libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/three_way.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0ad5ffea043..b4b95dfc5e7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,26 @@ 2020-02-20 Jonathan Wakely + * include/std/system_error (error_category::operator<=>) + (operator<=>(const error_code&, const error_code&)) + (operator<=>(const error_condition&, const error_condition&)): Define + for C++20. + * testsuite/19_diagnostics/error_category/operators/less.cc: New test. + * testsuite/19_diagnostics/error_category/operators/three_way.cc: New + test. + * testsuite/19_diagnostics/error_code/operators/equal.cc: Remove + incorrect comment. + * testsuite/19_diagnostics/error_code/operators/less.cc: New test. + * testsuite/19_diagnostics/error_code/operators/not_equal.cc: Remove + incorrect comment. + * testsuite/19_diagnostics/error_code/operators/three_way.cc: New test. + * testsuite/19_diagnostics/error_condition/operators/equal.cc: Remove + incorrect comment. + * testsuite/19_diagnostics/error_condition/operators/less.cc: New test. + * testsuite/19_diagnostics/error_condition/operators/not_equal.cc: + Remove incorrect comment. + * testsuite/19_diagnostics/error_condition/operators/three_way.cc: New + test. + * libsupc++/typeinfo (type_info::operator!=): Remove for C++20. * include/std/thread (thread::id::operator<=>): Define for C++20. diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index f1aebd59d02..f92b4345895 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -39,6 +39,9 @@ #include #include #include +#if __cplusplus > 201703L +# include +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -129,17 +132,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual bool equivalent(const error_code& __code, int __i) const noexcept; - bool - operator<(const error_category& __other) const noexcept - { return less()(this, &__other); } - bool operator==(const error_category& __other) const noexcept { return this == &__other; } +#if __cpp_lib_three_way_comparison + strong_ordering + operator<=>(const error_category& __rhs) const noexcept + { return std::compare_three_way()(this, &__rhs); } +#else bool operator!=(const error_category& __other) const noexcept { return this != &__other; } + + bool + operator<(const error_category& __other) const noexcept + { return less()(this, &__other); } +#endif }; // DR 890. @@ -230,6 +239,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION make_error_code(errc __e) noexcept { return error_code(static_cast(__e), generic_category()); } +#if __cpp_lib_three_way_comparison + inline strong_ordering + operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept + { + if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) + return __c; + return __lhs.value() <=> __rhs.value(); + } +#else inline bool operator<(const error_code& __lhs, const error_code& __rhs) noexcept { @@ -237,6 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION || (__lhs.category() == __rhs.category() && __lhs.value() < __rhs.value())); } +#endif template basic_ostream<_CharT, _Traits>& @@ -316,17 +335,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION make_error_condition(errc __e) noexcept { return error_condition(static_cast(__e), generic_category()); } - /// Define an ordering for error_condition objects. - /// @relates error_condition - inline bool - operator<(const error_condition& __lhs, - const error_condition& __rhs) noexcept - { - return (__lhs.category() < __rhs.category() - || (__lhs.category() == __rhs.category() - && __lhs.value() < __rhs.value())); - } - // 19.4.4 Comparison operators /// @relates error_code @@ -344,22 +352,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION || __rhs.category().equivalent(__lhs, __rhs.value())); } - /// @relates error_code /// @relates error_condition inline bool - operator==(const error_condition& __lhs, const error_code& __rhs) noexcept + operator==(const error_condition& __lhs, + const error_condition& __rhs) noexcept { - return (__rhs.category().equivalent(__rhs.value(), __lhs) - || __lhs.category().equivalent(__rhs, __lhs.value())); + return (__lhs.category() == __rhs.category() + && __lhs.value() == __rhs.value()); } +#if __cpp_lib_three_way_comparison + /// Define an ordering for error_condition objects. + /// @relates error_condition + inline strong_ordering + operator<=>(const error_condition& __lhs, + const error_condition& __rhs) noexcept + { + if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) + return __c; + return __lhs.value() <=> __rhs.value(); + } +#else + /// Define an ordering for error_condition objects. /// @relates error_condition inline bool - operator==(const error_condition& __lhs, - const error_condition& __rhs) noexcept + operator<(const error_condition& __lhs, + const error_condition& __rhs) noexcept { - return (__lhs.category() == __rhs.category() - && __lhs.value() == __rhs.value()); + return (__lhs.category() < __rhs.category() + || (__lhs.category() == __rhs.category() + && __lhs.value() < __rhs.value())); + } + + /// @relates error_code + /// @relates error_condition + inline bool + operator==(const error_condition& __lhs, const error_code& __rhs) noexcept + { + return (__rhs.category().equivalent(__rhs.value(), __lhs) + || __lhs.category().equivalent(__rhs, __lhs.value())); } /// @relates error_code @@ -384,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(const error_condition& __lhs, const error_condition& __rhs) noexcept { return !(__lhs == __rhs); } - +#endif // three_way_comparison /** * @brief An exception type that includes an `error_code` value. diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/less.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/less.cc new file mode 100644 index 00000000000..67831536b85 --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/less.cc @@ -0,0 +1,30 @@ +// { dg-do run { target c++11 } } +// { dg-additional-options "-static-libgcc" { target *-*-mingw* } } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + __gnu_test::test_category c1; + VERIFY( !(c1 < c1) ); + __gnu_test::test_derived_category c2; + VERIFY( (c1 < c2) || (c2 < c1) ); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/three_way.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/three_way.cc new file mode 100644 index 00000000000..efdf320dd36 --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/operators/three_way.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + __gnu_test::test_category c1; + VERIFY( std::is_eq(c1 <=> c1) ); + __gnu_test::test_derived_category c2; + VERIFY( std::is_neq(c1 <=> c2) ); +} + +void +test02() +{ + __gnu_test::test_category c1; + VERIFY( c1 <= c1 ); + VERIFY( c1 >= c1 ); + __gnu_test::test_derived_category c2; + VERIFY( (c1 < c2) || (c2 < c1) ); + VERIFY( (c1 > c2) || (c2 > c1) ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/equal.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/equal.cc index 5011c754fac..edb68b295ff 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/equal.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/equal.cc @@ -22,7 +22,6 @@ #include #include -// unspecified bool operator positive tests int main() { std::error_code e1; diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/less.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/less.cc new file mode 100644 index 00000000000..8cb3a7c3a7a --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/less.cc @@ -0,0 +1,38 @@ +// { dg-do run { target c++11 } } +// { dg-additional-options "-static-libstdc++" { target *-*-mingw* } } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + std::error_code e1; + std::error_code e2(std::make_error_code(std::errc::operation_not_supported)); + + VERIFY( !(e1 < e1) ); + VERIFY( !(e2 < e2) ); + + VERIFY( (e1 < e2) == (e1.value() < e2.value()) ); + + const __gnu_test::test_category cat; + std::error_code e3(e2.value(), cat); + VERIFY( !(e3 < e3) ); + VERIFY( (e2 < e3) == (e2.category() < e3.category()) ); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/not_equal.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/not_equal.cc index 7bc5b6d6882..5f261ed56fe 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/not_equal.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/not_equal.cc @@ -22,7 +22,6 @@ #include #include -// unspecified bool operator positive tests int main() { std::error_code e1; diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/three_way.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/three_way.cc new file mode 100644 index 00000000000..86416d6dbbd --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/three_way.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::error_code e1; + std::error_code e2(std::make_error_code(std::errc::operation_not_supported)); + + VERIFY( std::is_eq(e1 <=> e1) ); + VERIFY( std::is_lteq(e1 <=> e1) ); + VERIFY( std::is_gteq(e1 <=> e1) ); + + VERIFY( std::is_neq(e1 <=> e2) ); + VERIFY( std::is_lt(e1 <=> e2) || std::is_gt(e1 <=> e2) ); + VERIFY( (e1 <=> e2) == (e1.value() <=> e2.value()) ); + + VERIFY( e1 == e1 ); + VERIFY( !(e1 == e2) ); + + VERIFY( !(e1 < e1) ); + VERIFY( !(e2 < e2) ); + + const __gnu_test::test_category cat; + std::error_code e3(e2.value(), cat); + + VERIFY( std::is_neq(e2 <=> e3) ); + VERIFY( std::is_lt(e2 <=> e3) || std::is_gt(e2 <=> e3) ); + VERIFY( (e2 <=> e3) == (e2.category() <=> e3.category()) ); + + VERIFY( !(e2 == e3) ); + + VERIFY( !(e3 < e3) ); + VERIFY( (e2 < e3) == (e2.category() < e3.category()) ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/equal.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/equal.cc index 7fd3f7ec204..2c97fe201b5 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/equal.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/equal.cc @@ -21,7 +21,6 @@ #include #include -// unspecified bool operator positive tests void test01() { std::error_condition e1; diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/less.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/less.cc new file mode 100644 index 00000000000..20b32866565 --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/less.cc @@ -0,0 +1,38 @@ +// { dg-do run { target c++11 } } +// { dg-additional-options "-static-libstdc++" { target *-*-mingw* } } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +int main() +{ + std::error_condition e1; + std::error_condition e2(std::errc::operation_not_supported); + + VERIFY( !(e1 < e1) ); + VERIFY( !(e2 < e2) ); + + VERIFY( (e1 < e2) == (e1.value() < e2.value()) ); + + const __gnu_test::test_category cat; + std::error_condition e3(e2.value(), cat); + VERIFY( !(e3 < e3) ); + VERIFY( (e2 < e3) == (e2.category() < e3.category()) ); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/not_equal.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/not_equal.cc index 84cd92cc169..238fabbcc20 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/not_equal.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/not_equal.cc @@ -21,7 +21,6 @@ #include #include -// unspecified bool operator positive tests void test01() { std::error_condition e1; diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/three_way.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/three_way.cc new file mode 100644 index 00000000000..48c1671bdba --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/three_way.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::error_condition e1; + std::error_condition e2(std::errc::operation_not_supported); + + VERIFY( std::is_eq(e1 <=> e1) ); + VERIFY( std::is_lteq(e1 <=> e1) ); + VERIFY( std::is_gteq(e1 <=> e1) ); + + VERIFY( std::is_neq(e1 <=> e2) ); + VERIFY( std::is_lt(e1 <=> e2) || std::is_gt(e1 <=> e2) ); + VERIFY( (e1 <=> e2) == (e1.value() <=> e2.value()) ); + + VERIFY( e1 == e1 ); + VERIFY( !(e1 == e2) ); + + VERIFY( !(e1 < e1) ); + VERIFY( !(e2 < e2) ); + + const __gnu_test::test_category cat; + std::error_condition e3(e2.value(), cat); + + VERIFY( std::is_neq(e2 <=> e3) ); + VERIFY( std::is_lt(e2 <=> e3) || std::is_gt(e2 <=> e3) ); + VERIFY( (e2 <=> e3) == (e2.category() <=> e3.category()) ); + + VERIFY( !(e2 == e3) ); + + VERIFY( !(e3 < e3) ); + VERIFY( (e2 < e3) == (e2.category() < e3.category()) ); +} + +int main() +{ + test01(); +} -- 2.30.2