summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2024-08-07 15:28:51 -0700
committerThiago Macieira <thiago.macieira@intel.com>2024-08-10 11:06:45 -0700
commit91a27c1a516068b69ab62778a07c566ad22f3576 (patch)
treed077bcbc2b55677d3eb56d3630698bb55487edd7 /src/corelib
parent8fa8c574c04ea4f82d7675d5be5b9808c0b8f7b6 (diff)
QDebug: cast the QFlags value to the right-sized unsigned type (1/2)
This change fixes three problems in the non-Q_ENUM overload. First, the printing of the sign bit for a signed flag. This is correct, but unexpected: QFlags(0x1|0x2|-0x80000000) By using unsigned types, we'll print instead: QFlags(0x1|0x2|0x80000000) Second, shifting into the sign bit is UB, so we remove the problem by not having a sign bit at all. Third, this provides an out-of-line non-template overload of the implementation for unsigned QFlags, thereby avoiding an unnecessary instantiation of the template function qt_QMetaEnum_flagDebugOperator() in user code. Pick-to: 6.8 Change-Id: I8a96935cf6c742259c9dfffd17e992caa315e1d3 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/compat/removed_api.cpp7
-rw-r--r--src/corelib/io/qdebug.cpp6
-rw-r--r--src/corelib/io/qdebug.h7
3 files changed, 15 insertions, 5 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
index c5ec16a2467..bee1b27f7c1 100644
--- a/src/corelib/compat/removed_api.cpp
+++ b/src/corelib/compat/removed_api.cpp
@@ -984,6 +984,13 @@ QDataStream &QDataStream::operator<<(bool i)
return (*this << qint8(i));
}
+#include "qdebug.h"
+
+Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
+{
+ qt_QMetaEnum_flagDebugOperator(debug, sizeofT, uint(value));
+}
+
#include "qdir.h" // inlined API
bool QDir::operator==(const QDir &dir) const
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 42515be1187..d5bdfadba92 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1323,13 +1323,13 @@ QDebugStateSaver::~QDebugStateSaver()
\internal
Specialization of the primary template in qdebug.h to out-of-line
- the common case of QFlags<T>::Int being int.
+ the common case of QFlags<T>::Int being 32-bit.
Just call the generic version so the two don't get out of sync.
*/
-void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
+void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value)
{
- qt_QMetaEnum_flagDebugOperator<int>(debug, sizeofT, value);
+ qt_QMetaEnum_flagDebugOperator<uint>(debug, sizeofT, value);
}
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index f941bf40cb0..d311b74c1c0 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -523,11 +523,13 @@ inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
return debug;
}
-Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value);
+Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value);
template <typename Int>
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
{
+ static_assert(std::is_unsigned_v<Int>,
+ "Cast value to an unsigned type before calling this function");
const QDebugStateSaver saver(debug);
debug.resetFormat();
debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
@@ -591,7 +593,8 @@ template <class T>
inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
#endif
{
- qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), typename QFlags<T>::Int(flags));
+ using UInt = typename QIntegerForSizeof<T>::Unsigned;
+ qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), UInt(flags.toInt()));
return debug;
}