diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2017-04-18 12:08:12 +0200 |
---|---|---|
committer | Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com> | 2017-04-22 11:25:49 +0000 |
commit | d4cdc4542609e61d04802902d73c693faa8d8969 (patch) | |
tree | ac3ef546a85667205e96b6d38cbe2d575af0de8b | |
parent | 23287dfb15bb2bee19d2fa3530c030a6b75facfa (diff) |
Fix QMetaMethod::invoke and automatic type registration
This was simply not working for two reasons:
- The index passed to QMetaObject::metacall was not right (there was an offset
because of the return type)
- If the registration succeeded, the arguments were not even initialized.
The tests in tst_moc always called QMetaMethod::parameterType before calling invoke,
which was properly registering the type. So this was not seen in the tests before.
[ChangeLog][QtCore][QMetaMethod] Fixed crash in invoke() with QueuedConnection and
types whose metatype gets automatically registered.
Task-number: QTBUG-60185
Change-Id: I4247628484214fba0a8acc1813ed8f112f59c888
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 12 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 29 |
2 files changed, 36 insertions, 5 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 2e0dd8e5d2..a8003f7e46 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2241,12 +2241,10 @@ bool QMetaMethod::invoke(QObject *object, for (int i = 1; i < paramCount; ++i) { types[i] = QMetaType::type(typeNames[i]); - if (types[i] != QMetaType::UnknownType) { - args[i] = QMetaType::create(types[i], param[i]); - ++nargs; - } else if (param[i]) { + if (types[i] == QMetaType::UnknownType && param[i]) { // Try to register the type and try again before reporting an error. - void *argv[] = { &types[i], &i }; + int index = nargs - 1; + void *argv[] = { &types[i], &index }; QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType, idx_relative + idx_offset, argv); if (types[i] == -1) { @@ -2261,6 +2259,10 @@ bool QMetaMethod::invoke(QObject *object, return false; } } + if (types[i] != QMetaType::UnknownType) { + args[i] = QMetaType::create(types[i], param[i]); + ++nargs; + } } QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index fd32dc1ef8..e793d71fe2 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -206,6 +206,7 @@ private slots: void invokeMetaConstructor(); void invokeTypedefTypes(); void invokeException(); + void invokeQueuedAutoRegister(); void qtMetaObjectInheritance(); void normalizedSignature_data(); void normalizedSignature(); @@ -377,6 +378,7 @@ class QtTestObject: public QObject public: QtTestObject(); + QtTestObject(const QString &s) : slotResult(s) {} Q_INVOKABLE QtTestObject(QObject *parent); public slots: @@ -416,6 +418,15 @@ public slots: return s2; } + void slotWithRegistrableArgument(QtTestObject *o1, QPointer<QtTestObject> o2, + QSharedPointer<QtTestObject> o3, QWeakPointer<QtTestObject> o4, + QVector<QtTestObject *> o5, QList<QtTestObject *> o6) + { + slotResult = QLatin1String("slotWithRegistrableArgument:") + o1->slotResult + o2->slotResult + + o3->slotResult + o4.data()->slotResult + QString::number(o5.size()) + + QString::number(o6.size()); + } + signals: void sig0(); QString sig1(QString s1); @@ -944,6 +955,24 @@ void tst_QMetaObject::invokeException() #endif } +void tst_QMetaObject::invokeQueuedAutoRegister() +{ + QtTestObject obj; + + auto shared = QSharedPointer<QtTestObject>::create(QStringLiteral("myShared-")); + + QVERIFY(QMetaObject::invokeMethod( + &obj, "slotWithRegistrableArgument", Qt::QueuedConnection, + Q_ARG(QtTestObject *, shared.data()), Q_ARG(QPointer<QtTestObject>, shared.data()), + Q_ARG(QSharedPointer<QtTestObject>, shared), Q_ARG(QWeakPointer<QtTestObject>, shared), + Q_ARG(QVector<QtTestObject *>, QVector<QtTestObject *>()), + Q_ARG(QList<QtTestObject *>, QList<QtTestObject *>()))); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, + QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00")); +} + void tst_QMetaObject::normalizedSignature_data() { QTest::addColumn<QString>("signature"); |