[PATCH] libsupc++: Change _Unordered comparison value to minimum value of signed char.
Tomasz Kamiński
tkaminsk@redhat.com
Wed Aug 27 06:27:31 GMT 2025
For any minimum value of a signed type, its negation (with wraparound) results
in the same value, behaving like zero. Representing the unordered result with
this minimum value, along with 0 for equal, 1 for greater, and -1 for less
in partial_ordering, allows its value to be reversed using unary negation:
static_cast<unsigned char>(static_cast<unsigned int>(-_M_value))).
The static casts are required to avoid undefined behavior from signed overflow.
The operator<=(partial_order, zero_type) now checks if the reversed value is
positive. This works correctly because the _Unordered value remains unchanged
and thus negative.
libstdc++-v3/ChangeLog:
* libsupc++/compare (__cmp_cat::__utype): Define.
(_Ncmp::_Unordered): Change the value to minimum value of
signed char.
(partial_ordering::_M_reverse()): Define.
(operator<=(partial_ordering, __cmp_cat::__unspec))
(operator>=(__cmp_cat::__unspec, partial_ordering)): Implemented
in terms of negated _M_value.
(operator>=(partial_ordering, __cmp_cat::__unspec))
(operator<=(__cmp_cat::__unspec, partial_ordering)): Directly
compare _M_value, as _Unordered value is negative.
---
Tested on x86_64-linux. Testing on powerpc64le.
OK for trunk when test passes?
libstdc++-v3/libsupc++/compare | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 82b5c53139c..ae3a1c5e612 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -53,10 +53,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
namespace __cmp_cat
{
using type = signed char;
+ using __utype = unsigned char;
enum class _Ord : type { equivalent = 0, less = -1, greater = 1 };
- enum class _Ncmp : type { _Unordered = 2 };
+ enum class _Ncmp : type {
+ // minimum value of signed char, wraparound negation is no-op
+ _Unordered = static_cast<type>(static_cast<__utype>(1u << (__CHAR_BIT__ - 1)))
+ };
struct __unspec
{
@@ -66,7 +70,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
class partial_ordering
{
- // less=0xff, equiv=0x00, greater=0x01, unordered=0x02
+ // less=0xff, equiv=0x00, greater=0x01, unordered=0x80
__cmp_cat::type _M_value;
constexpr explicit
@@ -82,6 +86,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
friend class weak_ordering;
friend class strong_ordering;
+ [[__gnu__::__always_inline__]]
+ constexpr __cmp_cat::type
+ _M_reverse() const
+ {
+ return static_cast<__cmp_cat::type>(
+ static_cast<__cmp_cat::__utype>(
+ static_cast<unsigned int>(-_M_value)));
+ }
+
public:
// valid values
static const partial_ordering less;
@@ -112,12 +125,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
[[nodiscard]]
friend constexpr bool
operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept
- { return __v._M_value <= 0; }
+ { return __v._M_reverse() >= 0; }
[[nodiscard]]
friend constexpr bool
operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept
- { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
+ { return __v._M_value >= 0; }
[[nodiscard]]
friend constexpr bool
@@ -132,12 +145,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
[[nodiscard]]
friend constexpr bool
operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept
- { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
+ { return 0 <= __v._M_value; }
[[nodiscard]]
friend constexpr bool
operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept
- { return 0 >= __v._M_value; }
+ { return 0 <= __v._M_reverse(); }
[[nodiscard]]
friend constexpr partial_ordering
--
2.50.1
More information about the Libstdc++
mailing list