From 9483fcd68aef250c56a74556258dc80d9cc58220 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Mon, 13 Feb 2023 17:27:12 +0100 Subject: [PATCH] QObject: Handle pointers to incomplete types in auto-connections The code for the QMetaMethod queuedConnectionTypes overload relied on QMetaMethod::parameterMetaType and QMetaType::flags() to detect whether we're dealing with a pointer (and then use the VoidStar metatype instead). However, if the type was incomplete when the slot was defined, and the type was not registered when connect was called, we would not find a metatype for the argument. However, in that case we might still be able to handle the method, by checking whether the type name of the arguments ends with a "*". This patch does that, fixing a regression from 5.15. Pick-to: 6.5 6.4 6.2 Fixes: QTBUG-108537 Change-Id: I54cc48a3343444480ab9094fe1ebaaa5aa75cee0 Reviewed-by: Ulf Hermann Reviewed-by: Volker Hilsheimer --- src/corelib/kernel/qobject.cpp | 2 + .../corelib/kernel/qobject/tst_qobject.cpp | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 829cd4c79f..c49a65136a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -84,6 +84,8 @@ static int *queuedConnectionTypes(const QMetaMethod &method) typeIds[i] = QMetaType::VoidStar; else typeIds[i] = metaType.id(); + if (!typeIds[i] && method.parameterTypeName(i).endsWith('*')) + typeIds[i] = QMetaType::VoidStar; if (!typeIds[i]) { const QByteArray typeName = method.parameterTypeName(i); qCWarning(lcConnect, diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 207aae7608..1b678d8851 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -58,6 +58,7 @@ private slots: void connectNotify_connectSlotsByName(); void connectDisconnectNotify_shadowing(); void connectReferenceToIncompleteTypes(); + void connectAutoQueuedIncomplete(); void emitInDefinedOrder(); void customTypes(); void streamCustomTypes(); @@ -893,6 +894,42 @@ void tst_QObject::connectReferenceToIncompleteTypes() { QVERIFY(connection); } +struct Incomplete2; +class QObjectWithIncomplete2 : public QObject { + Q_OBJECT + +public: + QObjectWithIncomplete2(QObject *parent=nullptr) : QObject(parent) {} +signals: + void signalWithIncomplete(Incomplete2 *ptr); +public slots: + void slotWithIncomplete(Incomplete2 *) { calledSlot = true; } + void run() { Q_EMIT signalWithIncomplete(nullptr); } +public: + bool calledSlot = false; +}; + +void tst_QObject::connectAutoQueuedIncomplete() +{ + auto objectWithIncomplete1 = new QObjectWithIncomplete2(); + auto objectWithIncomplete2 = new QObjectWithIncomplete2(); + auto t = new QThread(this); + auto cleanup = qScopeGuard([&](){ + t->quit(); + QVERIFY(t->wait()); + delete objectWithIncomplete1; + delete objectWithIncomplete2; + }); + + t->start(); + objectWithIncomplete2->moveToThread(t); + + connect(objectWithIncomplete2, &QObjectWithIncomplete2::signalWithIncomplete, + objectWithIncomplete1, &QObjectWithIncomplete2::slotWithIncomplete); + QMetaObject::invokeMethod(objectWithIncomplete2, "run", Qt::QueuedConnection); + QTRY_VERIFY(objectWithIncomplete1->calledSlot); +} + static void connectDisconnectNotifyTestSlot() {} void tst_QObject::connectDisconnectNotifyPMF()