Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1From 7fccc79dd5744ea837ffe200bbfc9f2756870220 Mon Sep 17 00:00:00 20012From: Thiago Macieira <[email protected]>3Date: Wed, 14 Jan 2026 08:57:22 -08004Subject: [PATCH] QtCompare: adapt to GCC 16 breaking ABI for5std::partial_ordering7They changed[1] the stored value of the unordered constant from 2 to8-SCHAR_MAX-1 (0x80). This commit hardens the check for all three9std::*_ordering types and in all compilers, even though only the10unordered value has been observed to be a problem.12For:14std::partial_ordering f(Qt::partial_ordering o) { return o; }16With GCC < 16, this remains a plain bitcast. For GCC >= 16, this now17generates:18cmpb $2, %dil19movl $-128, %eax20cmovne %edi, %eax22Hopefully, when this is used in context, the comparisons will be elided23through constant propagation.25[1] https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=fcb3009a32dc33906934a2360e556dfeb98980cf27Pick-to: 6.11 6.10 6.8 6.528Change-Id: I04bc40f0aeef5c0c778dfffdaea0bf68c571946229Reviewed-by: Volker Hilsheimer <[email protected]>30Reviewed-by: Edward Welbourne <[email protected]>31---32src/corelib/global/qcompare.cpp | 2 +33src/corelib/global/qcompare.h | 60 ++++++++++++++-----34.../corelib/global/qcompare/tst_qcompare.cpp | 2 +353 files changed, 50 insertions(+), 14 deletions(-)37diff --git a/qtbase/src/corelib/global/qcompare.cpp b/qtbase/src/corelib/global/qcompare.cpp38index 8106a84ddcd7..7f7facafbb87 10064439--- a/qtbase/src/corelib/global/qcompare.cpp40+++ b/qtbase/src/corelib/global/qcompare.cpp41@@ -18,7 +18,9 @@ QT_BEGIN_NAMESPACE42static_assert(std::bit_cast<std:: type ## _ordering>(Qt:: type ## _ordering:: flag) \43== std:: type ## _ordering :: flag) \44/* end */45+#if !defined(__GLIBCXX__)46CHECK(partial, unordered);47+#endif48CHECK(partial, less);49CHECK(partial, greater);50CHECK(partial, equivalent);51diff --git a/qtbase/src/corelib/global/qcompare.h b/qtbase/src/corelib/global/qcompare.h52index d82cf5ab4a4e..7eee69db66a3 10064453--- a/qtbase/src/corelib/global/qcompare.h54+++ b/qtbase/src/corelib/global/qcompare.h55@@ -36,6 +36,15 @@ enum class Ordering : CompareUnderlyingType57enum class Uncomparable : CompareUnderlyingType58{59+ // We choose the value of our Uncomparable to be the same that the C++60+ // Standard Library chooses for its own std::partial_ordering::unordered,61+ // so we can convert from their type to ours via simple std::bit_cast.62+#if 063+ // GCC 16 broke ABI, so we cannot use the std::*_ordering types64+ // in our ABI until we drop support for GCC 15 and earlier. When that65+ // happens and std::bit_cast is guaranteed, this can be simplified to:66+ Unordered = std::bit_cast<CompareUnderlyingType>(std::partial_ordering::unordered);67+#else68Unordered =69#if defined(_LIBCPP_VERSION) // libc++70-12771@@ -44,12 +53,26 @@ enum class Uncomparable : CompareUnderlyingType72#else // assume MSSTL73-12874#endif75+#endif // future Qt76};78} // namespace QtPrivate80namespace QtOrderingPrivate {82+using QtPrivate::Ordering;83+using QtPrivate::Uncomparable;84+85+#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_three_way_comparison)86+inline constexpr bool OrderingValuesAreEqual =87+ std::bit_cast<Ordering>(std::weak_ordering::equivalent) == Ordering::Equivalent &&88+ std::bit_cast<Ordering>(std::strong_ordering::equal) == Ordering::Equal &&89+ std::bit_cast<Ordering>(std::strong_ordering::less) == Ordering::Less &&90+ std::bit_cast<Ordering>(std::strong_ordering::greater) == Ordering::Greater;91+inline constexpr bool UnorderedValueIsEqual =92+ std::bit_cast<Uncomparable>(std::partial_ordering::unordered) == Uncomparable::Unordered;93+#endif94+95template <typename O>96constexpr O reversed(O o) noexcept97{98@@ -61,6 +84,9 @@ constexpr O reversed(O o) noexcept100} // namespace QtOrderingPrivate102+QT_WARNING_PUSH103+QT_WARNING_DISABLE_MSVC(4702) // unreachable code104+105namespace Qt {107class weak_ordering;108@@ -156,12 +182,18 @@ public:109constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept110{111static_assert(sizeof(*this) == sizeof(std::partial_ordering));112-#ifdef __cpp_lib_bit_cast113- return std::bit_cast<std::partial_ordering>(*this);114-#else115using O = QtPrivate::Ordering;116using U = QtPrivate::Uncomparable;117using R = std::partial_ordering;118+#ifdef __cpp_lib_bit_cast119+ if constexpr (QtOrderingPrivate::OrderingValuesAreEqual) {120+ if constexpr (!QtOrderingPrivate::UnorderedValueIsEqual) {121+ if (m_order == qToUnderlying(U::Unordered))122+ return R::unordered;123+ }124+ return std::bit_cast<R>(*this);125+ }126+#endif // __cpp_lib_bit_cast127switch (m_order) {128case qToUnderlying(O::Less): return R::less;129case qToUnderlying(O::Greater): return R::greater;130@@ -169,7 +201,6 @@ public:131case qToUnderlying(U::Unordered): return R::unordered;132}133Q_UNREACHABLE_RETURN(R::unordered);134-#endif // __cpp_lib_bit_cast135}137friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept138@@ -347,18 +378,18 @@ public:139constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept140{141static_assert(sizeof(*this) == sizeof(std::weak_ordering));142-#ifdef __cpp_lib_bit_cast143- return std::bit_cast<std::weak_ordering>(*this);144-#else145using O = QtPrivate::Ordering;146using R = std::weak_ordering;147+#ifdef __cpp_lib_bit_cast148+ if constexpr (QtOrderingPrivate::OrderingValuesAreEqual)149+ return std::bit_cast<R>(*this);150+#endif // __cpp_lib_bit_cast151switch (m_order) {152case qToUnderlying(O::Less): return R::less;153case qToUnderlying(O::Greater): return R::greater;154case qToUnderlying(O::Equivalent): return R::equivalent;155}156Q_UNREACHABLE_RETURN(R::equivalent);157-#endif // __cpp_lib_bit_cast158}160friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept161@@ -542,18 +573,18 @@ public:162constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept163{164static_assert(sizeof(*this) == sizeof(std::strong_ordering));165-#ifdef __cpp_lib_bit_cast166- return std::bit_cast<std::strong_ordering>(*this);167-#else168using O = QtPrivate::Ordering;169using R = std::strong_ordering;170+#ifdef __cpp_lib_bit_cast171+ if constexpr (QtOrderingPrivate::OrderingValuesAreEqual)172+ return std::bit_cast<R>(*this);173+#endif // __cpp_lib_bit_cast174switch (m_order) {175case qToUnderlying(O::Less): return R::less;176case qToUnderlying(O::Greater): return R::greater;177case qToUnderlying(O::Equal): return R::equal;178}179Q_UNREACHABLE_RETURN(R::equal);180-#endif // __cpp_lib_bit_cast181}183friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept184@@ -620,6 +651,8 @@ inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::G186} // namespace Qt188+QT_WARNING_POP189+190QT_BEGIN_INCLUDE_NAMESPACE192// This is intentionally included after Qt::*_ordering types and before193diff --git a/qtbase/tests/auto/corelib/global/qcompare/tst_qcompare.cpp b/qtbase/tests/auto/corelib/global/qcompare/tst_qcompare.cpp194index b79a6661db33..ff5920134cc8 100644195--- a/qtbase/tests/auto/corelib/global/qcompare/tst_qcompare.cpp196+++ b/qtbase/tests/auto/corelib/global/qcompare/tst_qcompare.cpp197@@ -185,7 +185,9 @@ void tst_QCompare::stdQtBinaryCompatibility()198QCOMPARE_EQ(valueOf( Qt:: type ## _ordering :: flag), \199valueOf(std:: type ## _ordering :: flag)) \200/* end */201+# if !defined(__GLIBCXX__) || QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)202CHECK(partial, unordered);203+# endif204CHECK(partial, less);205CHECK(partial, greater);206CHECK(partial, equivalent);
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.