QDebug: cast the QFlags value to the right-sized unsigned type (2/2)

This applies to the Q_ENUM/Q_FLAGS overload of the debugging functions.
This prevents the sign-extension of a signed QFlags field when
converting to quint64, which would have resulted in 0x8000'0000 becoming
0xffff'ffff'8000'0000.

Right now, this is a no-op change because the implementation in
qt_QMetaEnum_flagDebugOperator() calls QMetaEnum::valueToKey(), which is
limited to int (32 bits).

Change-Id: I8a96935cf6c742259c9dfffd17e998c3a0538146
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 232ad339ab14965b6207d04a45d8d37ec3139558)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-08-07 17:18:18 -07:00 committed by Qt Cherry-pick Bot
parent 9883f88850
commit 3d90aa1771
3 changed files with 23 additions and 13 deletions

View File

@ -543,9 +543,10 @@ inline typename std::enable_if<
QDebug>::type
qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags)
{
using UInt = typename QIntegerForSizeof<T>::Unsigned;
const QMetaObject *obj = qt_getEnumMetaObject(T());
const char *name = qt_getEnumName(T());
return qt_QMetaEnum_flagDebugOperator(debug, flags.toInt(), obj, name);
return qt_QMetaEnum_flagDebugOperator(debug, UInt(flags.toInt()), obj, name);
}
template <class T>

View File

@ -51,8 +51,8 @@ class tst_QDebug: public QObject
{
Q_OBJECT
public:
enum EnumType { EnumValue1 = 1, EnumValue2 = 2 };
enum FlagType { EnumFlag1 = 1, EnumFlag2 = 2 };
enum EnumType { EnumValue1 = 1, EnumValue2 = INT_MIN };
enum FlagType { EnumFlag1 = 1, EnumFlag2 = INT_MIN };
Q_ENUM(EnumType)
Q_DECLARE_FLAGS(Flags, FlagType)
Q_FLAG(Flags)

View File

@ -11,8 +11,8 @@ class tst_QMetaEnum : public QObject
{
Q_OBJECT
public:
enum SuperEnum { SuperValue1 = 1 , SuperValue2 = 2 };
enum Flag { Flag1 = 1 , Flag2 = 2 };
enum SuperEnum { SuperValue1 = 1, SuperValue2 = INT_MIN };
enum Flag { Flag1 = 1, Flag2 = INT_MIN };
Q_DECLARE_FLAGS(Flags, Flag)
Q_ENUM(SuperEnum)
Q_FLAG(Flags)
@ -47,34 +47,43 @@ Q_DECLARE_METATYPE(Qt::WindowFlags)
void tst_QMetaEnum::valuesToKeys_data()
{
QTest::addColumn<Qt::WindowFlags>("windowFlags");
QTest::addColumn<QMetaEnum>("me");
QTest::addColumn<quint64>("flags");
QTest::addColumn<QByteArray>("expected");
QTest::newRow("Window")
<< Qt::WindowFlags(Qt::Window)
<< QMetaEnum::fromType<Qt::WindowFlags>()
<< quint64(Qt::Window)
<< QByteArrayLiteral("Window");
// Verify that Qt::Dialog does not cause 'Window' to appear in the output.
QTest::newRow("Frameless_Dialog")
<< (Qt::Dialog | Qt::FramelessWindowHint)
<< QMetaEnum::fromType<Qt::WindowFlags>()
<< quint64(Qt::Dialog | Qt::FramelessWindowHint)
<< QByteArrayLiteral("Dialog|FramelessWindowHint");
// Similarly, Qt::WindowMinMaxButtonsHint should not show up as
// WindowMinimizeButtonHint|WindowMaximizeButtonHint
QTest::newRow("Tool_MinMax_StaysOnTop")
<< (Qt::Tool | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint)
<< QMetaEnum::fromType<Qt::WindowFlags>()
<< quint64(Qt::Tool | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint)
<< QByteArrayLiteral("Tool|WindowMinMaxButtonsHint|WindowStaysOnTopHint");
QTest::newRow("INT_MIN")
<< QMetaEnum::fromType<Flags>()
<< quint64(uint(Flag2))
<< QByteArrayLiteral("Flag2");
}
void tst_QMetaEnum::valuesToKeys()
{
QFETCH(Qt::WindowFlags, windowFlags);
QFETCH(QMetaEnum, me);
QFETCH(quint64, flags);
QFETCH(QByteArray, expected);
QMetaEnum me = QMetaEnum::fromType<Qt::WindowFlags>();
QCOMPARE(me.valueToKeys(windowFlags), expected);
QCOMPARE(me.valueToKeys(flags), expected);
bool ok = false;
QCOMPARE(uint(me.keysToValue(expected, &ok)), windowFlags.toInt());
QCOMPARE(uint(me.keysToValue(expected, &ok)), flags);
QVERIFY(ok);
}