From d7bf3e122b234ce063a6edcf3b8e1c13c7c2556f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 27 Aug 2024 17:56:19 -0700 Subject: [PATCH] moc: remove always-known parameters to (Revisioned)ConstructorData It's a meta method so it must have a name and a return type, even though constructors have neither. The method name of a constructor QMetaMethod is the name of the class and the name is already required to be stored at index 0. We just have to be careful when the class is not directly in the global namespace, because then the first string contains the full scope. Prior to this change, it stored an empty string as the method return type, but QMetaMethod::returnMetaType() already protects against reading it, with: if (!mobj || methodType() == QMetaMethod::Constructor) return QMetaType{}; which was added in commit fa987d44417528856d5e80ed7b48ba99e19fa307 ("MetaObject: Store the QMetaType of the methods") because there is no metatype stored for this non-existent return type. This commit repeats some of that to QMetaMethod::typeName(). Change-Id: Ia903287c2c07b1d588a9fffdaf22fff0b0d6ce9f Reviewed-by: Fabian Kosmale --- src/corelib/kernel/qmetaobject.cpp | 12 +++++- src/corelib/kernel/qtmochelpers.h | 17 +++++++- src/tools/moc/generator.cpp | 13 ++++-- .../kernel/qmetamethod/tst_qmetamethod.cpp | 5 ++- tests/auto/tools/moc/tst_moc.cpp | 6 +-- .../auto/tools/mochelpers/tst_mochelpers.cpp | 41 +++++++++---------- 6 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 38beac2b4ac..c9848ece499 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -652,7 +652,7 @@ bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &me if (priv->parameterCount() != argc) return false; - if (stringData(m, data.name()) != name) + if (QMetaMethodPrivate::get(&method)->name() != name) return false; const QtPrivate::QMetaTypeInterface * const *ifaces = priv->parameterMetaTypeInterfaces(); @@ -2277,7 +2277,11 @@ QList QMetaMethod::parameterNames() const /*! - Returns the return type name of this method. + Returns the return type name of this method. If this method is a + constructor, this function returns an empty string (constructors have no + return types). + + \note In Qt 7, this function will return a null pointer for constructors. \sa returnType(), QMetaType::type() */ @@ -2285,6 +2289,10 @@ const char *QMetaMethod::typeName() const { if (!mobj) return nullptr; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + if (methodType() == QMetaMethod::Constructor) + return ""; +#endif return QMetaMethodPrivate::get(this)->rawReturnTypeName(); } diff --git a/src/corelib/kernel/qtmochelpers.h b/src/corelib/kernel/qtmochelpers.h index d33b00bbbde..d93e62f459c 100644 --- a/src/corelib/kernel/qtmochelpers.h +++ b/src/corelib/kernel/qtmochelpers.h @@ -445,7 +445,13 @@ template struct SlotData : FunctionData struct ConstructorData : FunctionData { - using FunctionData::FunctionData; + using Base = FunctionData; + + // the name for a constructor is always the class name (string index zero) + // and it has no return type + constexpr ConstructorData(uint tagIndex, uint flags, typename Base::ParametersArray params = {}) + : Base(0, tagIndex, flags, QMetaType::UnknownType, params) + {} }; template struct RevisionedMethodData : @@ -469,7 +475,14 @@ template struct RevisionedSlotData : template struct RevisionedConstructorData : FunctionData { - using FunctionData::FunctionData; + using Base = FunctionData; + + // the name for a constructor is always the class name (string index zero) + // and it has no return type + constexpr RevisionedConstructorData(uint tagIndex, uint flags, uint revision, + typename Base::ParametersArray params = {}) + : Base(0, tagIndex, flags, revision, QMetaType::UnknownType, params) + {} }; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index a6ce39c1ebd..5243ea64908 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -833,7 +833,11 @@ void Generator::addFunctions(const QList &list, const char *functyp comma = ", "; } - fprintf(out, ")%s>(%d, %d, ", f.isConst ? " const" : "", stridx(f.name), stridx(f.tag)); + if (f.isConstructor) + fprintf(out, ")>(%d, ", stridx(f.tag)); + else + fprintf(out, ")%s>(%d, %d, ", f.isConst ? " const" : "", stridx(f.name), stridx(f.tag)); + // flags // access right is always present if (f.access == FunctionDef::Private) @@ -854,9 +858,10 @@ void Generator::addFunctions(const QList &list, const char *functyp fprintf(out, ", %#x", f.revision); // return type (if not a constructor) - const bool allowEmptyName = f.isConstructor; - fprintf(out, ", "); - generateTypeInfo(f.normalizedType, allowEmptyName); + if (!f.isConstructor) { + fprintf(out, ", "); + generateTypeInfo(f.normalizedType); + } if (f.arguments.isEmpty()) { fprintf(out, "),\n"); diff --git a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp index 1eb97e26cbb..190b8fabdaf 100644 --- a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp +++ b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp @@ -618,7 +618,10 @@ void tst_QMetaMethod::method() QCOMPARE(method.tag(), ""); QCOMPARE(method.returnType(), returnType); - QVERIFY(method.typeName() != 0); + if (QT7_ONLY(method.methodType() == QMetaMethod::Constructor) QT6_ONLY(false)) + QVERIFY(method.typeName()); + else + QVERIFY(method.typeName() != 0); if (QByteArray(method.typeName()) != returnTypeName) { // QMetaMethod should always produce a semantically equivalent typename QCOMPARE(QMetaType::fromName(method.typeName()), QMetaType::fromName(returnTypeName)); diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 873acb6c77c..bd53f8e39ab 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1879,7 +1879,7 @@ void tst_Moc::constructors() QCOMPARE(mm.access(), QMetaMethod::Public); QCOMPARE(mm.methodType(), QMetaMethod::Constructor); QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QObject*)")); - QCOMPARE(mm.typeName(), ""); + QCOMPARE(QByteArrayView(mm.typeName()), QByteArrayView()); QList paramNames = mm.parameterNames(); QCOMPARE(paramNames.size(), 1); QCOMPARE(paramNames.at(0), QByteArray("parent")); @@ -1892,7 +1892,7 @@ void tst_Moc::constructors() QCOMPARE(mm.access(), QMetaMethod::Public); QCOMPARE(mm.methodType(), QMetaMethod::Constructor); QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass()")); - QCOMPARE(mm.typeName(), ""); + QCOMPARE(QByteArrayView(mm.typeName()), QByteArrayView()); QCOMPARE(mm.parameterNames().size(), 0); QCOMPARE(mm.parameterTypes().size(), 0); } @@ -1901,7 +1901,7 @@ void tst_Moc::constructors() QCOMPARE(mm.access(), QMetaMethod::Public); QCOMPARE(mm.methodType(), QMetaMethod::Constructor); QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QString)")); - QCOMPARE(mm.typeName(), ""); + QCOMPARE(QByteArrayView(mm.typeName()), QByteArrayView()); QList paramNames = mm.parameterNames(); QCOMPARE(paramNames.size(), 1); QCOMPARE(paramNames.at(0), QByteArray("str")); diff --git a/tests/auto/tools/mochelpers/tst_mochelpers.cpp b/tests/auto/tools/mochelpers/tst_mochelpers.cpp index 41f6a9953cc..9513a5bd646 100644 --- a/tests/auto/tools/mochelpers/tst_mochelpers.cpp +++ b/tests/auto/tools/mochelpers/tst_mochelpers.cpp @@ -512,29 +512,28 @@ void tst_MocHelpers::methodUintGroup() void tst_MocHelpers::constructorUintData() { - constexpr uint NoType = 0x80000000 | 1; using namespace QtMocHelpers; using namespace QtMocConstants; { - auto result = ConstructorData(1, 2, AccessPublic, NoType, {}); - QCOMPARE(result.header[0], 1U); + auto result = ConstructorData(2, AccessPublic, {}); + QCOMPARE(result.header[0], 0U); QCOMPARE(result.header[1], 0U); QCOMPARE(result.header[3], 2U); QCOMPARE(result.header[4], AccessPublic | MethodConstructor); QCOMPARE(result.header[5], 0U); - QCOMPARE(result.payload[0], NoType); + QCOMPARE(result.payload[0], uint(QMetaType::UnknownType)); QCOMPARE(result.metaTypes().count(), 0); } { - auto result = ConstructorData(0, 1, AccessPublic, NoType, + auto result = ConstructorData(1, AccessPublic, {{ { QMetaType::QObjectStar, 2 } }}); QCOMPARE(result.header[0], 0U); QCOMPARE(result.header[1], 1U); QCOMPARE(result.header[3], 1U); QCOMPARE(result.header[4], AccessPublic | MethodConstructor); QCOMPARE(result.header[5], 0U); - QCOMPARE(result.payload[0], NoType); + QCOMPARE(result.payload[0], uint(QMetaType::UnknownType)); QCOMPARE(result.payload[1], uint(QMetaType::QObjectStar)); QCOMPARE(result.payload[2], 2U); @@ -561,7 +560,7 @@ checkConstructors(const std::array &data, const QtPrivate::QMetaTypeInt QCOMPARE(header[4], AccessPublic | MethodConstructor); QCOMPARE_GT(header[5], 0U); const uint *payload = data.data() + header[2]; - QCOMPARE(payload[0], 0x80000000U | 1); + QCOMPARE(payload[0], uint(QMetaType::UnknownType)); QCOMPARE(payload[1], uint(QMetaType::QObjectStar)); QCOMPARE(QMetaType(metaTypes[header[5]]), QMetaType::fromType()); @@ -574,7 +573,7 @@ checkConstructors(const std::array &data, const QtPrivate::QMetaTypeInt QCOMPARE(header[4], AccessPublic | MethodConstructor | MethodCloned); QCOMPARE_GT(header[5], 0U); payload = data.data() + header[2]; - QCOMPARE(payload[0], 0x80000000U | 1); + QCOMPARE(payload[0], uint(QMetaType::UnknownType)); // no metatype stored for this constructor // Constructor(const QString &) @@ -586,7 +585,7 @@ checkConstructors(const std::array &data, const QtPrivate::QMetaTypeInt QCOMPARE(header[4], AccessPublic | MethodConstructor); QCOMPARE_GT(header[5], 0U); payload = data.data() + header[2]; - QCOMPARE(payload[0], 0x80000000U | 1); + QCOMPARE(payload[0], uint(QMetaType::UnknownType)); QCOMPARE(payload[1], uint(QMetaType::QString)); QCOMPARE(QMetaType(metaTypes[header[5]]), QMetaType::fromType()); } @@ -596,14 +595,14 @@ void tst_MocHelpers::constructorUintGroup() using QtMocHelpers::NoType; QTest::setThrowOnFail(true); constexpr QtMocHelpers::UintData constructors = { - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic, - 0x80000000 | 1, {{ { QMetaType::QObjectStar, 2 } }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic, + {{ { QMetaType::QObjectStar, 2 } }} ), - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned, - 0x80000000 | 1, {{ }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned, + {{ }} ), - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic, - 0x80000000 | 1, {{ { QMetaType::QString, 3 }, }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic, + {{ { QMetaType::QString, 3 }, }} ) }; testUintData(constructors); @@ -715,14 +714,14 @@ void tst_MocHelpers::uintArray() QtMocHelpers::EnumData>(11, 1, EnumIsFlag).add({ { 3, E1::AnEnumValue } }), }, QtMocHelpers::UintData{ - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic, - 0x80000000 | 1, {{ { QMetaType::QObjectStar, 2 } }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic, + {{ { QMetaType::QObjectStar, 2 } }} ), - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned, - 0x80000000 | 1, {{ }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned, + {{ }} ), - QtMocHelpers::ConstructorData(0, 1, QtMocConstants::AccessPublic, - 0x80000000 | 1, {{ { QMetaType::QString, 3 }, }} + QtMocHelpers::ConstructorData(1, QtMocConstants::AccessPublic, + {{ { QMetaType::QString, 3 }, }} ) }, QtMocHelpers::ClassInfos({{1, 2}, {3, 4}}));