Commit 4be779f5 by Jonathan Wakely

libstdc++: Define operator<=> for <system_error> 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.
parent 20fa41e6
2020-02-20 Jonathan Wakely <jwakely@redhat.com> 2020-02-20 Jonathan Wakely <jwakely@redhat.com>
* 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. * libsupc++/typeinfo (type_info::operator!=): Remove for C++20.
* include/std/thread (thread::id::operator<=>): Define for C++20. * include/std/thread (thread::id::operator<=>): Define for C++20.
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#include <bits/error_constants.h> #include <bits/error_constants.h>
#include <iosfwd> #include <iosfwd>
#include <stdexcept> #include <stdexcept>
#if __cplusplus > 201703L
# include <compare>
#endif
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
...@@ -130,16 +133,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -130,16 +133,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
equivalent(const error_code& __code, int __i) const noexcept; equivalent(const error_code& __code, int __i) const noexcept;
bool bool
operator<(const error_category& __other) const noexcept
{ return less<const error_category*>()(this, &__other); }
bool
operator==(const error_category& __other) const noexcept operator==(const error_category& __other) const noexcept
{ return this == &__other; } { 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 bool
operator!=(const error_category& __other) const noexcept operator!=(const error_category& __other) const noexcept
{ return this != &__other; } { return this != &__other; }
bool
operator<(const error_category& __other) const noexcept
{ return less<const error_category*>()(this, &__other); }
#endif
}; };
// DR 890. // DR 890.
...@@ -230,6 +239,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -230,6 +239,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_error_code(errc __e) noexcept make_error_code(errc __e) noexcept
{ return error_code(static_cast<int>(__e), generic_category()); } { return error_code(static_cast<int>(__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 inline bool
operator<(const error_code& __lhs, const error_code& __rhs) noexcept operator<(const error_code& __lhs, const error_code& __rhs) noexcept
{ {
...@@ -237,6 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -237,6 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| (__lhs.category() == __rhs.category() || (__lhs.category() == __rhs.category()
&& __lhs.value() < __rhs.value())); && __lhs.value() < __rhs.value()));
} }
#endif
template<typename _CharT, typename _Traits> template<typename _CharT, typename _Traits>
basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>&
...@@ -316,17 +335,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -316,17 +335,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_error_condition(errc __e) noexcept make_error_condition(errc __e) noexcept
{ return error_condition(static_cast<int>(__e), generic_category()); } { return error_condition(static_cast<int>(__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 // 19.4.4 Comparison operators
/// @relates error_code /// @relates error_code
...@@ -344,22 +352,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -344,22 +352,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| __rhs.category().equivalent(__lhs, __rhs.value())); || __rhs.category().equivalent(__lhs, __rhs.value()));
} }
/// @relates error_code
/// @relates error_condition /// @relates error_condition
inline bool 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) return (__lhs.category() == __rhs.category()
|| __lhs.category().equivalent(__rhs, __lhs.value())); && __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 /// @relates error_condition
inline bool inline bool
operator==(const error_condition& __lhs, operator<(const error_condition& __lhs,
const error_condition& __rhs) noexcept const error_condition& __rhs) noexcept
{ {
return (__lhs.category() == __rhs.category() return (__lhs.category() < __rhs.category()
&& __lhs.value() == __rhs.value()); || (__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 /// @relates error_code
...@@ -384,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -384,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(const error_condition& __lhs, operator!=(const error_condition& __lhs,
const error_condition& __rhs) noexcept const error_condition& __rhs) noexcept
{ return !(__lhs == __rhs); } { return !(__lhs == __rhs); }
#endif // three_way_comparison
/** /**
* @brief An exception type that includes an `error_code` value. * @brief An exception type that includes an `error_code` value.
......
// { 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
// <http://www.gnu.org/licenses/>.
#include <system_error>
#include <testsuite_error.h>
int main()
{
__gnu_test::test_category c1;
VERIFY( !(c1 < c1) );
__gnu_test::test_derived_category c2;
VERIFY( (c1 < c2) || (c2 < c1) );
}
// 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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do run { target c++2a } }
#include <system_error>
#include <testsuite_error.h>
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();
}
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <system_error> #include <system_error>
#include <testsuite_error.h> #include <testsuite_error.h>
// unspecified bool operator positive tests
int main() int main()
{ {
std::error_code e1; std::error_code e1;
......
// { 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
// <http://www.gnu.org/licenses/>.
#include <system_error>
#include <testsuite_error.h>
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()) );
}
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <system_error> #include <system_error>
#include <testsuite_error.h> #include <testsuite_error.h>
// unspecified bool operator positive tests
int main() int main()
{ {
std::error_code e1; std::error_code e1;
......
// 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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do run { target c++2a } }
#include <system_error>
#include <testsuite_error.h>
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();
}
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <system_error> #include <system_error>
#include <testsuite_error.h> #include <testsuite_error.h>
// unspecified bool operator positive tests
void test01() void test01()
{ {
std::error_condition e1; std::error_condition e1;
......
// { 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
// <http://www.gnu.org/licenses/>.
#include <system_error>
#include <testsuite_error.h>
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()) );
}
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <system_error> #include <system_error>
#include <testsuite_error.h> #include <testsuite_error.h>
// unspecified bool operator positive tests
void test01() void test01()
{ {
std::error_condition e1; std::error_condition e1;
......
// 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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do run { target c++2a } }
#include <system_error>
#include <testsuite_error.h>
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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment