diff options
author | Marc Mutz <[email protected]> | 2025-06-02 17:25:40 +0200 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2025-06-06 22:16:36 +0200 |
commit | a97ac8507e39a421f530f5ad612a7e4bb58f6718 (patch) | |
tree | 855595d187f000c2d7b46528121b8d8867eecffb /tests | |
parent | 99ad6a51a595430c75323c4d5c2ecbc7fbd8d7f0 (diff) |
The kludge that was added to argumentTypesFromString() for Qt 6 to
support merging QVector into QList—specifically, the replacement of
QVector< with QList<—was unfortunately not removed before the Qt 6.0
release. As a kludge, it has unintended consequences, as Thiago
pointed out in a comment on a related patch.
This change adds a reproducer that demonstrates cases where the
kludge causes correct code to fail incorrectly. We need this test to
ensure that we do not silently change behavior when deprecating and
eventually removing the kludge.
Adapt the MyQList normalization test, which was carefully written to
avoid hitting the kludge, to use template arguments. This will allow
it to trigger the buggy code path and avoid confusing the reader with
the mention of a non-template MyQList, given that MyQList is now a
template.
Reported-by: Thiago Macieira <[email protected]>
Pick-to: 6.10 6.9 6.8 6.5
Task-number: QTBUG-135572
Change-Id: I91d769d494489fe63dbbb67f849b78fc7aa39ec6
Reviewed-by: Ahmad Samir <[email protected]>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 07bd4a12a51..f714ce8f23e 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -14,6 +14,9 @@ #endif #include <private/qmetaobject_p.h> +#include <deque> +#include <vector> + Q_DECLARE_METATYPE(const QMetaObject *) #include "forwarddeclared.h" @@ -49,6 +52,28 @@ public: Q_INVOKABLE MyGadget() {} }; +template <typename T> +class MyQList +{ + std::vector<T> m_data; +public: + MyQList(std::initializer_list<T> il) : m_data{il} {} + + const std::vector<T> &data() const { return m_data; } + std::vector<T> &data() { return m_data; } +}; + +template <typename T> +class MyQVector +{ + std::deque<T> m_data; +public: + MyQVector(std::initializer_list<T> il) : m_data{il} {} + + const std::deque<T> &data() const { return m_data; } + std::deque<T> &data() { return m_data; } +}; + namespace MyNamespace { // Used in tst_QMetaObject::checkScope class MyClass : public QObject @@ -316,6 +341,7 @@ private slots: void normalizedType_data(); void normalizedType(); void customPropertyType(); + void customQVectorSuffix(); void keysToValue_data(); void keysToValue(); // Also keyToValue() void propertyNotify(); @@ -361,6 +387,8 @@ private slots: signals: void value6Changed(); void value7Changed(const QString &); + void myQListChanged(const MyQList<int> &); + void myQVectorChanged(const MyQVector<double> &); // needs different template arg from MyQList! }; void tst_QMetaObject::stdSet() @@ -2309,8 +2337,11 @@ void tst_QMetaObject::normalizedSignature_data() QTest::newRow("const13") << "void foo(const Foo<Bar>&)" << "void foo(Foo<Bar>)"; QTest::newRow("const14") << "void foo(Foo<Bar>const&)" << "void foo(Foo<Bar>)"; QTest::newRow("QVector") << "void foo(QVector<int>)" << "void foo(QList<int>)"; - QTest::newRow("QVector1") << "void foo(const Template<QVector, MyQList const>)" - << "void foo(Template<QList,const MyQList>)"; + QTest::newRow("QVector1") << "void foo(const Template<QVector, MyQList<int> const>)" + << "void foo(Template<QList,const MyQList<int>>)"; + QTest::newRow("MyQVector") << "void foo(MyQVector<int>)" << "void foo(MyQVector<int>)"; + QTest::newRow("MyQVector1") << "void foo(const Template<QVector, MyQVector<int> const>)" + << "void foo(Template<QList,const MyQVector<int>>)"; QTest::newRow("refref") << "const char* foo(const X &&,X const &&, const X* &&) && " << "const char*foo(const X&&,const X&&,const X*&&)&&"; @@ -2433,6 +2464,22 @@ void tst_QMetaObject::customPropertyType() QCOMPARE(prop.metaType().id(), QMetaType::QVariantList); } +void tst_QMetaObject::customQVectorSuffix() +{ + QObject ctx; + QVERIFY(connect(this, SIGNAL(myQListChanged(MyQList<int>)), + &ctx, SLOT(deleteLater()))); // just some compatible slot... + + // QMetaObject internally does s/QVector</QList</ indiscriminently, so the + // existing signal is not found: + QEXPECT_FAIL("", "Qt 6 QVector -> QList kludge getting in the way", Continue); + QTest::ignoreMessage(QtWarningMsg, + QRegularExpression(R"(.*QObject::connect: No such signal )" + R"(tst_QMetaObject.*::myQVectorChanged\(MyQVector<double>\).*)"_L1)); + QVERIFY(connect(this, SIGNAL(myQVectorChanged(MyQVector<double>)), + &ctx, SLOT(deleteLater()))); // just some compatible slot... +} + void tst_QMetaObject::keysToValue_data() { QTest::addColumn<QObject *>("object"); @@ -2807,10 +2854,11 @@ void tst_QMetaObject::indexOfMethod_data() QTest::addColumn<QObject *>("object"); QTest::addColumn<QByteArray>("name"); QTest::addColumn<bool>("isSignal"); + QTest::addColumn<bool>("found"); - auto row = [this] (const char *fun, bool sig) { + auto row = [this] (const char *fun, bool sig, bool found = true) { QObject *o = this; - QTest::addRow("%s", fun) << o << QByteArray(fun) << sig; + QTest::addRow("%s", fun) << o << QByteArray(fun) << sig << found; }; row("indexOfMethod_data()", false); @@ -2819,6 +2867,9 @@ void tst_QMetaObject::indexOfMethod_data() row("value7Changed(QString)", true); row("destroyed()", true); row("destroyed(QObject*)", true); + row("myQListChanged(MyQList<int>)", true); + row("myQListChanged(MyQVector<int>)", true, false); + row("myQVectorChanged(MyQVector<double>)", true); } void tst_QMetaObject::indexOfMethod() @@ -2826,9 +2877,16 @@ void tst_QMetaObject::indexOfMethod() QFETCH(QObject *, object); QFETCH(QByteArray, name); QFETCH(bool, isSignal); + QFETCH(const bool, found); + QEXPECT_FAIL("myQListChanged(MyQVector<int>)", "Qt 6 QVector -> QList kludge getting in the way", Abort); + QEXPECT_FAIL("myQVectorChanged(MyQVector<double>)", "Qt 6 QVector -> QList kludge getting in the way", Abort); int idx = object->metaObject()->indexOfMethod(name); - QVERIFY(idx >= 0); - QCOMPARE(object->metaObject()->method(idx).methodSignature(), name); + if (found) + QVERIFY(idx >= 0); + else + QVERIFY(idx < 0); + if (found) + QCOMPARE(object->metaObject()->method(idx).methodSignature(), name); QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx); QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx); } |