summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2024-08-07 15:23:39 -0700
committerThiago Macieira <thiago.macieira@intel.com>2024-10-09 15:48:15 -0700
commit094f7cab54db7f9ce3b62fc1041c33ab30c202f0 (patch)
tree3bc41b07c9727448bbce05d7a50b9178058fc943
parent2971dbfe062de6b0be3ed9f251f9506bd45d5854 (diff)
QDebug: improve support for printing 64-bit QFlags
Like the 32-bit version, we add an explicitly-exported non-template overload. And we can call the 64-bit implementation from the 32-bit one to save in code generation inside QtCore. Task-number: QTBUG-111926 Change-Id: I8a96935cf6c742259c9dfffd17e9928218333c04 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/corelib/io/qdebug.cpp14
-rw-r--r--src/corelib/io/qdebug.h7
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp52
3 files changed, 67 insertions, 6 deletions
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index d5bdfadba92..598355e4296 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1329,9 +1329,19 @@ QDebugStateSaver::~QDebugStateSaver()
*/
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value)
{
- qt_QMetaEnum_flagDebugOperator<uint>(debug, sizeofT, value);
+ qt_QMetaEnum_flagDebugOperator(debug, sizeofT, quint64(value));
}
+/*!
+ \internal
+ Ditto, for 64-bit.
+*/
+void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value)
+{
+ qt_QMetaEnum_flagDebugOperator<quint64>(debug, sizeofT, value);
+}
+
+
#ifndef QT_NO_QOBJECT
/*!
\internal
@@ -1449,7 +1459,7 @@ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaO
debug << '(';
}
- debug << me.valueToKeys(static_cast<int>(value));
+ debug << me.valueToKeys(value);
if (enumScope)
debug << ')';
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 9b86c8eb1a1..c4be5955c8e 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -526,6 +526,7 @@ inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, qint64 value, const QMetaObject *meta, const char *name);
Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value);
+Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value);
template <typename Int>
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
@@ -556,9 +557,13 @@ inline QDebug operator<<(QDebug debug, Flags flags)
using UInt = typename QIntegerForSizeof<T>::Unsigned;
#if !defined(QT_NO_QOBJECT)
if constexpr (QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<Flags>::Value) {
+ // if QFlags<T> is a Q_FLAG, we always zero-extend; if not, we need to
+ // allow it to sign-extend if it is signed (see QMetaEnum::valueToKeys)
+ using Int = std::conditional_t<QtPrivate::IsQEnumHelper<Flags>::Value, UInt,
+ std::underlying_type_t<T>>;
const QMetaObject *obj = qt_getEnumMetaObject(T());
const char *name = qt_getEnumName(T());
- return qt_QMetaEnum_flagDebugOperator(debug, UInt(flags.toInt()), obj, name);
+ return qt_QMetaEnum_flagDebugOperator(debug, Int(flags.toInt()), obj, name);
} else
#endif
{
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 5d4d4048129..fafda8bce87 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -54,9 +54,14 @@ class tst_QDebug: public QObject
public:
enum EnumType { EnumValue1 = 1, EnumValue2 = INT_MIN };
enum FlagType { EnumFlag1 = 1, EnumFlag2 = INT_MIN };
+ enum Enum64Type { Enum64Value1 = 1, Enum64Value2 = Q_UINT64_C(0x1'0000'0002) };
+ enum Flag64Type : qlonglong { Enum64Flag1 = 1, Enum64Flag2 = Q_UINT64_C(0x1'0000'0002) };
Q_ENUM(EnumType)
+ Q_ENUM(Enum64Type)
Q_DECLARE_FLAGS(Flags, FlagType)
Q_FLAG(Flags)
+ Q_DECLARE_FLAGS(Flags64, Flag64Type)
+ Q_FLAG(Flags64)
private slots:
void assignment() const;
@@ -88,6 +93,7 @@ private slots:
void qDebugQByteArray() const;
void qDebugQByteArrayView() const;
void qDebugQFlags() const;
+ void qDebugQFlags64() const;
void qDebugStdChrono_data() const;
void qDebugStdChrono() const;
void qDebugStdOptional() const;
@@ -106,6 +112,8 @@ private slots:
void objcInObjcMode() const;
#endif
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(tst_QDebug::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(tst_QDebug::Flags64)
void tst_QDebug::assignment() const
{
@@ -1096,8 +1104,9 @@ void tst_QDebug::qDebugQFlags() const
QString file, function;
int line = 0;
QFlags<TestEnum> flags(Flag1 | Flag2 | SignFlag);
-
MessageHandlerSetter mhs(myMessageHandler);
+
+ // first, test QFlags on an enum where neither are Q_FLAG or Q_ENUM
{ qDebug() << flags; }
#ifndef QT_NO_MESSAGELOGCONTEXT
file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
@@ -1108,17 +1117,54 @@ void tst_QDebug::qDebugQFlags() const
QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function);
- // Test the output of QFlags with an enum not declared with Q_DECLARE_FLAGS and Q_FLAGS
+ // QFlags where the backing enum is a Q_ENUM but the QFlags isn't a QFLAG
QFlags<EnumType> flags2(EnumValue2);
qDebug() << flags2;
QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::EnumType>(EnumValue2)"));
- // A now for one that was fully declared
+ // And now for one that was fully declared
tst_QDebug::Flags flags3(EnumFlag1);
qDebug() << flags3;
QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::FlagType>(EnumFlag1)"));
}
+enum class TestEnum64 : qulonglong {
+ Flag1 = 0x1,
+ Flag2 = Q_UINT64_C(0x8000'0000'0000'0000)
+};
+
+Q_DECLARE_FLAGS(TestFlags64, TestEnum64)
+Q_DECLARE_OPERATORS_FOR_FLAGS(TestFlags64)
+
+void tst_QDebug::qDebugQFlags64() const
+{
+ QString file, function;
+ int line = 0;
+ QFlags<TestEnum64> flags(TestEnum64::Flag1 | TestEnum64::Flag2);
+ MessageHandlerSetter mhs(myMessageHandler);
+
+ // first, test QFlags on an enum where neither are Q_FLAG or Q_ENUM
+ qDebug() << flags;
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, "QFlags(0x1|0x8000000000000000)");
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ // QFlags where the backing enum is a Q_ENUM but the QFlags isn't a QFLAG
+ QFlags<Enum64Type> flags2(Enum64Value2);
+ qDebug() << flags2;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::Enum64Type>(Enum64Value2)"));
+
+ // And now for one that was fully declared
+ tst_QDebug::Flags64 flags3(Enum64Flag1|Enum64Flag2);
+ qDebug() << flags3;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::Flag64Type>(Enum64Flag1|Enum64Flag2)"));
+}
+
using ToStringFunction = std::function<QString()>;
void tst_QDebug::qDebugStdChrono_data() const
{