qt: add patches to fix SFINAE errors/warnings with gcc16
What changed, and why it matters
This commit adds four build-compatibility patches to the Qt source code that Bitcoin Core downloads and compiles. The patches fix C++ template/header ordering problems that cause errors or warnings when building with the upcoming GCC 16 compiler. These are compile-time hygiene fixes, not security bug fixes, and they do not change how Bitcoin Core behaves at runtime.
No security action required. Treat as a normal build-system maintenance commit. Reviewers may verify the upstream Qt commit hashes match the backported patches.
Security signals we found
No security-relevant code changes in Bitcoin Core itself
Patches address compiler warnings/errors, not memory safety, logic bugs, or cryptographic issues
Upstream Qt commits are build-compatibility backports for GCC 16
No mention of CVE, vulnerability, exploit, or security impact in commit message or diff
Evidence from the diff
The change backports four upstream Qt commits (679e8bda, 3312e89b, 05f201a3, d68fc6ec) into Bitcoin Core’s depends build system. Each patch resolves SFINAE/ODR header-dependency issues in Qt 6 CoreLib: completing QBitArray before std::hash SFINAE in qhashfunctions.h, moving QChar::fromUcs4 into qchar.h to break an include cycle, moving QStringView::count(QRegularExpression) into qregularexpression.h where the type is complete, and including qchar.h in qbytearrayview.h for ordering comparisons. The Bitcoin Core commit only wires these patches into depends/packages/qt.mk; it does not alter consensus, networking, wallet, or runtime code.
Changed components
depends/packages/qt.mkdepends/patches/qt/fix-gcc16-sfinae-qbitarray.patchdepends/patches/qt/fix-gcc16-sfinae-qchar.patchdepends/patches/qt/fix-gcc16-sfinae-qregularexpression.patchdepends/patches/qt/fix-qbytearray-include.patchInspect captured patch +304 / −1
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index b88add68..257735a3 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -20,6 +20,10 @@ $(package)_patches += rcc_hardcode_timestamp.patch
$(package)_patches += qttools_skip_dependencies.patch
$(package)_patches += static_fixes.patch
$(package)_patches += fix-gcc16-qcompare.patch
+$(package)_patches += fix-gcc16-sfinae-qregularexpression.patch
+$(package)_patches += fix-gcc16-sfinae-qchar.patch
+$(package)_patches += fix-gcc16-sfinae-qbitarray.patch
+$(package)_patches += fix-qbytearray-include.patch
$(package)_qttranslations_file_name=$(qt_details_qttranslations_file_name)
$(package)_qttranslations_sha256_hash=$(qt_details_qttranslations_sha256_hash)
@@ -270,7 +274,11 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/qtbase_skip_tools.patch && \
patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch && \
patch -p1 -i $($(package)_patch_dir)/static_fixes.patch && \
- patch -p1 -i $($(package)_patch_dir)/fix-gcc16-qcompare.patch
+ patch -p1 -i $($(package)_patch_dir)/fix-gcc16-qcompare.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix-gcc16-sfinae-qregularexpression.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix-gcc16-sfinae-qchar.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix-gcc16-sfinae-qbitarray.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix-qbytearray-include.patch
endef
ifeq ($(host),$(build))
$(package)_preprocess_cmds += && patch -p1 -i $($(package)_patch_dir)/qttools_skip_dependencies.patch
diff --git a/depends/patches/qt/fix-gcc16-sfinae-qbitarray.patch b/depends/patches/qt/fix-gcc16-sfinae-qbitarray.patch
new file mode 100644
index 00000000..03460375
--- /dev/null
+++ b/depends/patches/qt/fix-gcc16-sfinae-qbitarray.patch
@@ -0,0 +1,56 @@
+From 679e8bda1eb0cc98acb981e9a10204bed1c179f2 Mon Sep 17 00:00:00 2001
+From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date: Tue, 20 Jan 2026 15:23:31 +0100
+Subject: [PATCH] qhashfunctions.h: include QBitArray
+
+In qhashfunctions.h we're declaring a std::hash specialization for
+QBitArray. That specialization instantiates
+QNothrowHashable_v<QBitArray>, which checks if qHash(QBitArray) is
+noexcept.
+
+The problem is that there are already qHash(QByteArrayView) and
+qHash(QStringView) around, which will be picked up by overload
+resolution. That, in turn, will try to instantiate the QBAV/QSV
+constructors from a generic container. That instantiation will fail
+because QBitArray is not complete yet.
+
+When we later complete QBitArray, GCC is going to complain.
+
+Therefore, complete QBitArray before attempting SFINAE tricks on it.
+
+As an alternative, I could've moved the std::hash specialization
+to qbitarray.h. However I noticed that qHash(QBitArray) is still
+declared into qhashfunctions.h, i.e. hashing QBitArrays didn't
+require the full type, and therefore moving std::hash would've been
+a potential SIC?
+
+Task-number: QTBUG-143470
+Change-Id: Ie79d15e77d1fb3c86de6d7480a66bddc39f17666
+Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
+---
+ src/corelib/tools/qhashfunctions.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/qtbase/src/corelib/tools/qhashfunctions.h b/qtbase/src/corelib/tools/qhashfunctions.h
+index 8f1394c8ad35..beef80557865 100644
+--- a/qtbase/src/corelib/tools/qhashfunctions.h
++++ b/qtbase/src/corelib/tools/qhashfunctions.h
+@@ -8,6 +8,9 @@
+
+ #include <QtCore/qstring.h>
+ #include <QtCore/qstringfwd.h>
++#ifndef QT_BOOTSTRAPPED
++#include <QtCore/qbitarray.h>
++#endif
+
+ #include <numeric> // for std::accumulate
+ #include <functional> // for std::hash
+@@ -25,8 +28,6 @@
+
+ QT_BEGIN_NAMESPACE
+
+-class QBitArray;
+-
+ #if QT_DEPRECATED_SINCE(6,6)
+ QT_DEPRECATED_VERSION_X_6_6("Use QHashSeed instead")
+ Q_CORE_EXPORT int qGlobalQHashSeed();
diff --git a/depends/patches/qt/fix-gcc16-sfinae-qchar.patch b/depends/patches/qt/fix-gcc16-sfinae-qchar.patch
new file mode 100644
index 00000000..888e128c
--- /dev/null
+++ b/depends/patches/qt/fix-gcc16-sfinae-qchar.patch
@@ -0,0 +1,131 @@
+From 05f201a3d559452287b20becb960de3a50249540 Mon Sep 17 00:00:00 2001
+From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date: Wed, 4 Feb 2026 12:12:37 +0100
+Subject: [PATCH] Move QChar::fromUcs4 into qchar.h
+
+Right now fromUcs4 lives in qstringview.h because the return type has an
+implicit conversion operator towards QStringView. This however creates
+an inclusion loop: qchar.h includes qstringview.h, and qstringview.h
+includes qchar.h. Only the latter should exist.
+
+We can move the code back into qchar.h and drop the QStringView
+dependency by making the type returned from fromUcs4 have data(). That
+would make it a string-like range and become implicitly convertible to
+QStringView through its ranged constructor.
+
+In fact, add a test that checks for the *implicit* conversion; and
+add a test that checks for a conversion towards std::u16string_view.
+
+QMetaType was calling the conversion operator from the return type of
+fromUcs4 to QStringView directly (...Hyrum law...), although we never
+documented the presence of that operator, only that the conversion was
+possible; fix it by using a conversion.
+
+Fixes: QTBUG-143873
+Task-number: QTBUG-143470
+Change-Id: Id07657dd411cc2e1446fb18789e04db9cecd8ae0
+Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
+Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
+---
+ src/corelib/kernel/qmetatype.cpp | 2 +-
+ src/corelib/text/qchar.h | 16 +++++++++++++---
+ src/corelib/text/qstringview.h | 16 ----------------
+ tests/auto/corelib/text/qchar/tst_qchar.cpp | 10 ++++++++++
+ 4 files changed, 24 insertions(+), 20 deletions(-)
+
+diff --git a/qtbase/src/corelib/kernel/qmetatype.cpp b/qtbase/src/corelib/kernel/qmetatype.cpp
+index e70583404a46..54a0fe671fe0 100644
+--- a/qtbase/src/corelib/kernel/qmetatype.cpp
++++ b/qtbase/src/corelib/kernel/qmetatype.cpp
+@@ -1212,7 +1212,7 @@ QT_WARNING_DISABLE_CLANG("-Wtautological-compare")
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Char32,
+- result = QChar::fromUcs4(source).operator QStringView().toString();
++ result = QStringView(QChar::fromUcs4(source)).toString();
+ return true;
+ );
+ #if QT_CONFIG(datestring)
+diff --git a/qtbase/src/corelib/text/qchar.h b/qtbase/src/corelib/text/qchar.h
+index 4a3aad0ca0c1..f96ca590f2e2 100644
+--- a/qtbase/src/corelib/text/qchar.h
++++ b/qtbase/src/corelib/text/qchar.h
+@@ -88,7 +88,19 @@ class QT6_ONLY(Q_CORE_EXPORT) QChar {
+ #endif
+
+ static constexpr QChar fromUcs2(char16_t c) noexcept { return QChar{c}; }
+- static constexpr inline auto fromUcs4(char32_t c) noexcept;
++ [[nodiscard]] static constexpr inline auto fromUcs4(char32_t c) noexcept
++ {
++ struct R {
++ char16_t chars[2];
++ [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
++ [[nodiscard]] constexpr const char16_t *data() const noexcept { return chars; }
++ [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
++ [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
++ };
++ return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
++ QChar::lowSurrogate(c)}} :
++ R{{char16_t(c), u'\0'}} ;
++ }
+
+ // Unicode information
+
+@@ -666,5 +678,3 @@ struct hash<QT_PREPEND_NAMESPACE(QChar)>
+ } // namespace std
+
+ #endif // QCHAR_H
+-
+-#include <QtCore/qstringview.h> // for QChar::fromUcs4() definition
+diff --git a/qtbase/src/corelib/text/qstringview.h b/qtbase/src/corelib/text/qstringview.h
+index 6d5edfc06d7d..d5897af6da2d 100644
+--- a/qtbase/src/corelib/text/qstringview.h
++++ b/qtbase/src/corelib/text/qstringview.h
+@@ -472,22 +472,6 @@ template <typename QStringLike, typename std::enable_if<
+ inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
+ { return QStringView(s.begin(), s.size()); }
+
+-// QChar inline functions:
+-
+-[[nodiscard]] constexpr auto QChar::fromUcs4(char32_t c) noexcept
+-{
+- struct R {
+- char16_t chars[2];
+- [[nodiscard]] constexpr operator QStringView() const noexcept { return {begin(), end()}; }
+- [[nodiscard]] constexpr qsizetype size() const noexcept { return chars[1] ? 2 : 1; }
+- [[nodiscard]] constexpr const char16_t *begin() const noexcept { return chars; }
+- [[nodiscard]] constexpr const char16_t *end() const noexcept { return begin() + size(); }
+- };
+- return requiresSurrogates(c) ? R{{QChar::highSurrogate(c),
+- QChar::lowSurrogate(c)}} :
+- R{{char16_t(c), u'\0'}} ;
+-}
+-
+ qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::CaseSensitivity cs) noexcept
+ {
+ if (from < -str.size()) // from < 0 && abs(from) > str.size(), avoiding overflow
+diff --git a/qtbase/tests/auto/corelib/text/qchar/tst_qchar.cpp b/qtbase/tests/auto/corelib/text/qchar/tst_qchar.cpp
+index 6701f0e33f3d..5781d36e458b 100644
+--- a/qtbase/tests/auto/corelib/text/qchar/tst_qchar.cpp
++++ b/qtbase/tests/auto/corelib/text/qchar/tst_qchar.cpp
+@@ -142,10 +142,20 @@ void tst_QChar::fromUcs4()
+ QCOMPARE(result.chars[0], QChar::highSurrogate(ucs4));
+ QCOMPARE(result.chars[1], QChar::lowSurrogate(ucs4));
+ QCOMPARE(QStringView{result}.size(), 2);
++ QStringView v = result;
++ QCOMPARE(v.size(), 2);
++#if __cplusplus >= 202302L // no FTM for the ranged constructor of basic_string_view
++ QCOMPARE(std::u16string_view{result}.size(), 2);
++#endif
+ } else {
+ QCOMPARE(result.chars[0], ucs4);
+ QCOMPARE(result.chars[1], 0u);
+ QCOMPARE(QStringView{result}.size(), 1);
++ QStringView v = result;
++ QCOMPARE(v.size(), 1);
++#if __cplusplus >= 202302L // no FTM for the ranged constructor of basic_string_view
++ QCOMPARE(std::u16string_view{result}.size(), 1);
++#endif
+ }
+ }
+
diff --git a/depends/patches/qt/fix-gcc16-sfinae-qregularexpression.patch b/depends/patches/qt/fix-gcc16-sfinae-qregularexpression.patch
new file mode 100644
index 00000000..9ded0424
--- /dev/null
+++ b/depends/patches/qt/fix-gcc16-sfinae-qregularexpression.patch
@@ -0,0 +1,68 @@
+From 3312e89b47f8c2ea0b4263b39841c25b83a37332 Mon Sep 17 00:00:00 2001
+From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date: Fri, 16 Jan 2026 21:54:45 +0100
+Subject: [PATCH] QStringView: fix benign ODR violation for
+ count(QRegularExpression)
+
+QRegularExpression is only forward declared in qstringview.h.
+QStringView::count(const QRegularExpression &re) simply calls
+`QtPrivate::count(*this, re)`. The problem is that this latter
+count is overloaded, and there's a `QtPrivate::count(QStringView,
+QStringView)` overload available.
+
+This overload is not viable because there is no conversion from
+QRegularExpression to QStringView. To determine this, the compiler
+instantiates the QStringView(const Container &) constructor template,
+with Container = QRegularExpression. This function template is
+constrained via SFINAE, and it will fail the constraint checks
+_because QRegularExpression is incomplete_ (in particular std::data
+itself has SFINAE, and it fails in there).
+
+GCC doesn't like the idea that at a later time we complete
+QRegularExpression, because it fears that the prior result might
+have been different had QRegularExpression been complete.
+
+We know it's not different, but still, silence the warning by
+moving the call to QtPrivate::count where QRegularExpression
+is complete.
+
+Pick-to: 6.11
+Change-Id: I294c5ccb7c4ab3d52e518182c159e690575cbb00
+Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
+---
+ src/corelib/text/qregularexpression.h | 5 +++++
+ src/corelib/text/qstringview.h | 5 +----
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/qtbase/src/corelib/text/qregularexpression.h b/qtbase/src/corelib/text/qregularexpression.h
+index 462786179cb5..ece094ca768f 100644
+--- a/qtbase/src/corelib/text/qregularexpression.h
++++ b/qtbase/src/corelib/text/qregularexpression.h
+@@ -191,6 +191,11 @@ Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpression &re);
+ Q_CORE_EXPORT QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions);
+ #endif
+
++[[nodiscard]] inline qsizetype QStringView::count(const QRegularExpression &re) const
++{
++ return QtPrivate::count(*this, re);
++}
++
+ struct QRegularExpressionMatchPrivate;
+ QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionMatchPrivate, Q_CORE_EXPORT)
+
+diff --git a/qtbase/src/corelib/text/qstringview.h b/qtbase/src/corelib/text/qstringview.h
+index d586620c8b09..6d5edfc06d7d 100644
+--- a/qtbase/src/corelib/text/qstringview.h
++++ b/qtbase/src/corelib/text/qstringview.h
+@@ -329,10 +329,7 @@ class QStringView
+ {
+ return QtPrivate::contains(*this, re, rmatch);
+ }
+- [[nodiscard]] qsizetype count(const QRegularExpression &re) const
+- {
+- return QtPrivate::count(*this, re);
+- }
++ [[nodiscard]] qsizetype count(const QRegularExpression &re) const; // defined in qregularexpression.h
+ #endif
+
+ [[nodiscard]] bool isRightToLeft() const noexcept
diff --git a/depends/patches/qt/fix-qbytearray-include.patch b/depends/patches/qt/fix-qbytearray-include.patch
new file mode 100644
index 00000000..e1e68090
--- /dev/null
+++ b/depends/patches/qt/fix-qbytearray-include.patch
@@ -0,0 +1,40 @@
+From d68fc6ecc88a0e4532754b1a9f209881a248f4ee Mon Sep 17 00:00:00 2001
+From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date: Wed, 4 Feb 2026 12:33:08 +0100
+Subject: [PATCH] QByteArrayView: include qchar.h
+
+QByteArrayView needs the complete definition of QChar in order to
+define its relational operators against it.
+
+In particular, the expansion of the
+
+Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, QChar, QT_ASCII_CAST_WARN)
+
+macro creates an overload set where the QByteArrayView(Container)
+constructor is considered. GCC complains that that constructor is
+excluded via SFINAE for Container = QChar, not because QChar isn't a
+suitable container (indeed, it's not), but because it's *incomplete* at
+that point. When QChar is later completed, GCC is afraid that the
+previous substitution failure might have yielded a different result,
+and warns about it. Fix this by including QChar.
+
+Task-number: QTBUG-143470
+Change-Id: I705f91ef1133b59363df0cd6dbab91a5854e248c
+Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
+Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
+---
+ src/corelib/text/qbytearrayview.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/qtbase/src/corelib/text/qbytearrayview.h b/qtbase/src/corelib/text/qbytearrayview.h
+index 7d3e82e72a02..b19f6fd5424e 100644
+--- a/qtbase/src/corelib/text/qbytearrayview.h
++++ b/qtbase/src/corelib/text/qbytearrayview.h
+@@ -4,6 +4,7 @@
+ #define QBYTEARRAYVIEW_H
+
+ #include <QtCore/qbytearrayalgorithms.h>
++#include <QtCore/qchar.h>
+ #include <QtCore/qcompare.h>
+ #include <QtCore/qcontainerfwd.h>
+ #include <QtCore/qstringfwd.h>
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.