From a4e0f070ae156ec01897cd9d35781f92fc146344 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 31 Jul 2022 09:52:42 -0700 Subject: [PATCH] QMetaObject: fix calling overloaded functions & constructors The rewrites in a1c34d8bd09bfc6e80dcb06c7900d40c2d32518c, 0f76e55bc440a70f5d9530a192c9ce6334a8f069 and in commit b73ab954dffffc462b6f6efe5a2dd97efeab0038 didn't do this right, though no problem ended up happening. In particular, the constructor one failed to check if there were even more parameters. Change-Id: I6f936da6f6e84d649f70fffd1706f827ba635584 Reviewed-by: Fabian Kosmale --- src/corelib/kernel/qmetaobject.cpp | 4 +- .../kernel/qmetaobject/tst_qmetaobject.cpp | 71 ++++++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index e3b57ccaa0..80c511107a 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -277,6 +277,8 @@ QObject *QMetaObject::newInstance(QGenericArgument val0, auto priv = QMetaObjectPrivate::get(this); for (int i = 0; i < priv->constructorCount; ++i) { QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(this, i); + if (m.parameterCount() != (paramCount - 1)) + continue; // attempt to call QMetaMethodPrivate::InvokeFailReason r = @@ -1489,7 +1491,7 @@ bool QMetaObject::invokeMethod(QObject *obj, auto priv = QMetaObjectPrivate::get(meta); for (int i = 0; i < priv->methodCount; ++i) { QMetaMethod m = QMetaMethod::fromRelativeMethodIndex(meta, i); - if (m.parameterCount() > (paramCount - 1)) + if (m.parameterCount() != (paramCount - 1)) continue; if (name != stringDataView(meta, m.data.name())) continue; diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 192970c7ac..01f9617be1 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -465,6 +465,8 @@ public: QtTestObject(); QtTestObject(const QString &s) : slotResult(s) {} Q_INVOKABLE QtTestObject(QObject *parent); + Q_INVOKABLE QtTestObject(QObject *parent, int, int); + Q_INVOKABLE QtTestObject(QObject *parent, int); public slots: void sl0(); @@ -487,10 +489,13 @@ public slots: qint64 sl14(); qlonglong *sl15(qlonglong *); MyForwardDeclaredType *sl16(MyForwardDeclaredType *); + + void overloadedSlot(); + void overloadedSlot(int, int); + void overloadedSlot(int); + void testSender(); - void testReference(QString &str); - void testLongLong(qint64 ll1, quint64 ll2); void moveToThread(QThread *t) @@ -548,6 +553,14 @@ QtTestObject::QtTestObject(QObject *parent) { } +QtTestObject::QtTestObject(QObject *parent, int, int) + : QObject(parent) +{ slotResult = "ii"; } + +QtTestObject::QtTestObject(QObject *parent, int) + : QObject(parent) +{ slotResult = "i"; } + void QtTestObject::sl0() { slotResult = "sl0"; }; QString QtTestObject::sl1(QString s1) { slotResult = "sl1:" + s1; return "yessir"; } void QtTestObject::sl2(QString s1, QString s2) { slotResult = "sl2:" + s1 + s2; } @@ -593,6 +606,15 @@ MyForwardDeclaredType *QtTestObject::sl16(MyForwardDeclaredType *ptr) return getForwardDeclaredPointer(); } +void QtTestObject::overloadedSlot() +{ slotResult = "overloadedSlot"; } + +void QtTestObject::overloadedSlot(int x, int y) +{ slotResult = "overloadedSlot:" + QString::number(x) + ',' + QString::number(y); } + +void QtTestObject::overloadedSlot(int x) +{ slotResult = "overloadedSlot:" + QString::number(x); } + void QtTestObject::testReference(QString &str) { slotResult = "testReference:" + str; str = "gotcha"; } @@ -761,6 +783,14 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(forwardPtr, getForwardDeclaredPointer()); QCOMPARE(obj.slotResult, QString("sl16:null")); + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot")); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Q_ARG(int, 1))); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Q_ARG(int, 1), Q_ARG(int, 42))); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + //test signals QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); QCOMPARE(obj.slotResult, QString("sl0")); @@ -889,6 +919,17 @@ void tst_QMetaObject::invokeQueuedMetaMember() qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl15")); + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, Q_ARG(int, 1))); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, Q_ARG(int, 1), Q_ARG(int, 42))); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + // signals obj.slotResult.clear(); @@ -1131,6 +1172,14 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() QCOMPARE(forwardPtr, getForwardDeclaredPointer()); QCOMPARE(obj.slotResult, QString("sl16:null")); + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1))); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1), Q_ARG(int, 42))); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + //test signals QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl0")); @@ -1334,6 +1383,24 @@ void tst_QMetaObject::invokeMetaConstructor() QTest::ignoreMessage(QtWarningMsg, "QMetaObject::newInstance: type MyGadget does not inherit QObject"); QVERIFY(!MyGadget::staticMetaObject.newInstance()); } + + // overloaded constructors + QObject parent; + { + QObject *obj = mo->newInstance(Q_ARG(QObject*, &parent)); + QVERIFY(obj); + QCOMPARE(static_cast(obj)->slotResult, ""); + } + { + QObject *obj = mo->newInstance(Q_ARG(QObject*, &parent), Q_ARG(int, 1)); + QVERIFY(obj); + QCOMPARE(static_cast(obj)->slotResult, "i"); + } + { + QObject *obj = mo->newInstance(Q_ARG(QObject*, &parent), Q_ARG(int, 1), Q_ARG(int, 42)); + QVERIFY(obj); + QCOMPARE(static_cast(obj)->slotResult, "ii"); + } } void tst_QMetaObject::invokeTypedefTypes()