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>
This commit is contained in:
parent
8fa8c574c0
commit
91a27c1a51
@ -984,6 +984,13 @@ QDataStream &QDataStream::operator<<(bool i)
|
|||||||
return (*this << qint8(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
|
#include "qdir.h" // inlined API
|
||||||
|
|
||||||
bool QDir::operator==(const QDir &dir) const
|
bool QDir::operator==(const QDir &dir) const
|
||||||
|
@ -1323,13 +1323,13 @@ QDebugStateSaver::~QDebugStateSaver()
|
|||||||
\internal
|
\internal
|
||||||
|
|
||||||
Specialization of the primary template in qdebug.h to out-of-line
|
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.
|
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
|
#ifndef QT_NO_QOBJECT
|
||||||
|
@ -523,11 +523,13 @@ inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
|
|||||||
return debug;
|
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>
|
template <typename Int>
|
||||||
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
|
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);
|
const QDebugStateSaver saver(debug);
|
||||||
debug.resetFormat();
|
debug.resetFormat();
|
||||||
debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
|
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)
|
inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
|
||||||
#endif
|
#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;
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1085,7 +1085,8 @@ void tst_QDebug::qDebugQByteArrayView() const
|
|||||||
|
|
||||||
enum TestEnum {
|
enum TestEnum {
|
||||||
Flag1 = 0x1,
|
Flag1 = 0x1,
|
||||||
Flag2 = 0x10
|
Flag2 = 0x10,
|
||||||
|
SignFlag = INT_MIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(TestFlags, TestEnum)
|
Q_DECLARE_FLAGS(TestFlags, TestEnum)
|
||||||
@ -1094,7 +1095,7 @@ void tst_QDebug::qDebugQFlags() const
|
|||||||
{
|
{
|
||||||
QString file, function;
|
QString file, function;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
QFlags<TestEnum> flags(Flag1 | Flag2);
|
QFlags<TestEnum> flags(Flag1 | Flag2 | SignFlag);
|
||||||
|
|
||||||
MessageHandlerSetter mhs(myMessageHandler);
|
MessageHandlerSetter mhs(myMessageHandler);
|
||||||
{ qDebug() << flags; }
|
{ qDebug() << flags; }
|
||||||
@ -1102,7 +1103,7 @@ void tst_QDebug::qDebugQFlags() const
|
|||||||
file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
|
file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
|
||||||
#endif
|
#endif
|
||||||
QCOMPARE(s_msgType, QtDebugMsg);
|
QCOMPARE(s_msgType, QtDebugMsg);
|
||||||
QCOMPARE(s_msg, QString::fromLatin1("QFlags(0x1|0x10)"));
|
QCOMPARE(s_msg, QString::fromLatin1("QFlags(0x1|0x10|0x80000000)"));
|
||||||
QCOMPARE(QString::fromLatin1(s_file), file);
|
QCOMPARE(QString::fromLatin1(s_file), file);
|
||||||
QCOMPARE(s_line, line);
|
QCOMPARE(s_line, line);
|
||||||
QCOMPARE(QString::fromLatin1(s_function), function);
|
QCOMPARE(QString::fromLatin1(s_function), function);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user