From 3d90aa17714ba8a53a506969d47dbb4c80a9f68c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 7 Aug 2024 17:18:18 -0700 Subject: [PATCH] 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 Reviewed-by: Fabian Kosmale (cherry picked from commit 232ad339ab14965b6207d04a45d8d37ec3139558) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/io/qdebug.h | 3 +- tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 4 +-- .../kernel/qmetaenum/tst_qmetaenum.cpp | 29 ++++++++++++------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index ea0bb869381..b68c96c7182 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -543,9 +543,10 @@ inline typename std::enable_if< QDebug>::type qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags &flags) { + using UInt = typename QIntegerForSizeof::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 diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 877924e6e49..efbb13e89ac 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -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) diff --git a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp index 3d958a78fe9..83dd8c62988 100644 --- a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp +++ b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp @@ -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("windowFlags"); + QTest::addColumn("me"); + QTest::addColumn("flags"); QTest::addColumn("expected"); QTest::newRow("Window") - << Qt::WindowFlags(Qt::Window) + << QMetaEnum::fromType() + << 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() + << 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() + << quint64(Qt::Tool | Qt::WindowMinMaxButtonsHint | Qt::WindowStaysOnTopHint) << QByteArrayLiteral("Tool|WindowMinMaxButtonsHint|WindowStaysOnTopHint"); + + QTest::newRow("INT_MIN") + << QMetaEnum::fromType() + << 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(); - 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); }