diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 4da62b73586..5f2fccfa5a8 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -26,6 +26,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -741,6 +743,31 @@ inline int QMetaObjectPrivate::indexOfMethodRelative(const QMetaObject **baseObj \sa constructor(), constructorCount(), normalizedSignature() */ +#if QT_DEPRECATED_SINCE(6, 10) +Q_DECL_COLD_FUNCTION +static int compat_indexOf(const char *what, const char *sig, const QMetaObject *mo, + int (*indexOf)(const QMetaObject *, const char *)) +{ + const QByteArray normalized = QByteArray(sig).replace("QVector<", "QList<"); + const int i = indexOf(mo, normalized.data()); + if (i >= 0) { + qWarning(R"(QMetaObject::indexOf%s: argument "%s" is not normalized, because it contains "QVector<". )" + R"(Earlier versions of Qt 6 incorrectly normalized QVector< to QList<, silently. )" + R"(This behavior is deprecated as of 6.10, and will be removed in a future version of Qt.)", + what, sig); + } + return i; +} + +#define INDEXOF_COMPAT(what, arg) \ + do { \ + if (i < 0 && Q_UNLIKELY(std::strstr(arg, "QVector<"))) \ + i = compat_indexOf(#what, arg, this, &indexOf ## what ## _helper); \ + } while (false) +#else +#define INDEXOF_COMPAT(what, arg) +#endif // QT_DEPRECATED_SINCE(6, 10) + static int indexOfConstructor_helper(const QMetaObject *mo, const char *constructor) { QArgumentTypeArray types; @@ -752,6 +779,7 @@ int QMetaObject::indexOfConstructor(const char *constructor) const { Q_ASSERT(priv(d.data)->revision >= 7); int i = indexOfConstructor_helper(this, constructor); + INDEXOF_COMPAT(Constructor, constructor); return i; } @@ -782,6 +810,7 @@ int QMetaObject::indexOfMethod(const char *method) const { const QMetaObject *m = this; int i = indexOfMethod_helper(m, method); + INDEXOF_COMPAT(Method, method); return i; } @@ -804,7 +833,6 @@ static void argumentTypesFromString(const char *str, const char *end, ++str; } QByteArray argType(begin, str - begin); - argType.replace("QVector<", "QList<"); types += QArgumentType(std::move(argType)); } } @@ -856,6 +884,7 @@ int QMetaObject::indexOfSignal(const char *signal) const { const QMetaObject *m = this; int i = indexOfSignal_helper(m, signal); + INDEXOF_COMPAT(Signal, signal); return i; } @@ -912,9 +941,12 @@ int QMetaObject::indexOfSlot(const char *slot) const { const QMetaObject *m = this; int i = indexOfSlot_helper(m, slot); + INDEXOF_COMPAT(Slot, slot); return i; } +#undef INDEXOF_COMPAT + // same as indexOfSignalRelative but for slots. int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m, QByteArrayView name, int argc, diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index c44345c6ed7..a26a0b1a42a 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -40,6 +40,17 @@ Q_DECLARE_METATYPE(const QMetaObject *) using namespace Qt::StringLiterals; +#if QT_DEPRECATED_SINCE(6, 10) +static void eatIndexOfNonNormalizedWarning() +{ + static const QRegularExpression rx(R"(QMetaObject::indexOf(Constructor|Method|Signal|Slot): )" + R"(argument ".+" is not normalized, )" + R"(because it contains "QVector<"\.)"_L1); + QTest::ignoreMessage(QtWarningMsg, rx); +} +#define NORMALIZES_QVECTOR_QLIST +#endif + struct MyStruct { int i; @@ -2470,12 +2481,8 @@ void tst_QMetaObject::customQVectorSuffix() QVERIFY(connect(this, SIGNAL(myQListChanged(MyQList)), &ctx, SLOT(deleteLater()))); // just some compatible slot... - // QMetaObject internally does s/QVector QList kludge getting in the way", Continue); - QTest::ignoreMessage(QtWarningMsg, - QRegularExpression(R"(.*QObject::connect: No such signal )" - R"(tst_QMetaObject.*::myQVectorChanged\(MyQVector\).*)"_L1)); + // QMetaObject used to internally s/QVector)), &ctx, SLOT(deleteLater()))); // just some compatible slot... } @@ -2759,12 +2766,18 @@ void tst_QMetaObject::metaMethod() QCOMPARE(obj.slotResult, QString("sl5:12345")); // check Qt 6 QVector/QList alias: +#ifdef NORMALIZES_QVECTOR_QLIST + eatIndexOfNonNormalizedWarning(); index = QtTestObject::staticMetaObject.indexOfMethod("sl13v(QVector)"); QVERIFY(index > 0); +#endif index = QtTestObject::staticMetaObject.indexOfMethod("sl13v(QList)"); QVERIFY(index > 0); +#ifdef NORMALIZES_QVECTOR_QLIST + eatIndexOfNonNormalizedWarning(); index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QVector)"); QVERIFY(index > 0); +#endif index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList)"); QVERIFY(index > 0); QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); @@ -2781,14 +2794,20 @@ void tst_QMetaObject::metaMethod() index = QtTestObject::staticMetaObject.indexOfConstructor("QtTestObject(QObject*,QList)"); QVERIFY(index > 0); +#ifdef NORMALIZES_QVECTOR_QLIST + eatIndexOfNonNormalizedWarning(); index = QtTestObject::staticMetaObject.indexOfConstructor("QtTestObject(QObject*,QVector)"); QVERIFY(index > 0); +#endif QCOMPARE(QtTestObject::staticMetaObject.constructor(index).methodSignature(), "QtTestObject(QObject*,QList)"); index = QtTestObject::staticMetaObject.indexOfConstructor("QtTestObject(QList,QObject*)"); QVERIFY(index > 0); +#ifdef NORMALIZES_QVECTOR_QLIST + eatIndexOfNonNormalizedWarning(); index = QtTestObject::staticMetaObject.indexOfConstructor("QtTestObject(QVector,QObject*)"); QVERIFY(index > 0); +#endif QCOMPARE(QtTestObject::staticMetaObject.constructor(index).methodSignature(), "QtTestObject(QList,QObject*)"); } @@ -2832,8 +2851,11 @@ void tst_QMetaObject::metaMethodNoMacro() QCOMPARE(obj.slotResult, QString("sl5:12345")); // check Qt 6 QVector/QList alias: +#ifdef NORMALIZES_QVECTOR_QLIST + eatIndexOfNonNormalizedWarning(); index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QVector)"); QVERIFY(index > 0); +#endif index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList)"); QVERIFY(index > 0); QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); @@ -2878,8 +2900,11 @@ void tst_QMetaObject::indexOfMethod() QFETCH(QByteArray, name); QFETCH(bool, isSignal); QFETCH(const bool, found); +#ifdef NORMALIZES_QVECTOR_QLIST QEXPECT_FAIL("myQListChanged(MyQVector)", "Qt 6 QVector -> QList kludge getting in the way", Abort); - QEXPECT_FAIL("myQVectorChanged(MyQVector)", "Qt 6 QVector -> QList kludge getting in the way", Abort); + if (qstrcmp(QTest::currentDataTag(), "myQListChanged(MyQVector)") == 0) + eatIndexOfNonNormalizedWarning(); +#endif int idx = object->metaObject()->indexOfMethod(name); if (found) QVERIFY(idx >= 0); @@ -3333,5 +3358,9 @@ void tst_QMetaObject::connectByMetaMethodToFreeFunction() QCOMPARE(emit o.sig1(u"foo"_s), u"foofoo"_s); } +#ifdef NORMALIZES_QVECTOR_QLIST +# undef NORMALIZES_QVECTOR_QLIST +#endif + QTEST_MAIN(tst_QMetaObject) #include "tst_qmetaobject.moc"