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 <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2024-08-27 17:56:19 -07:00
parent 22ce92f804
commit d7bf3e122b
6 changed files with 61 additions and 33 deletions

View File

@ -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<QByteArray> 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();
}

View File

@ -445,7 +445,13 @@ template <typename F> struct SlotData : FunctionData<F, QtMocConstants::MethodSl
template <typename F> struct ConstructorData : FunctionData<F, QtMocConstants::MethodConstructor>
{
using FunctionData<F, QtMocConstants::MethodConstructor>::FunctionData;
using Base = FunctionData<F, QtMocConstants::MethodConstructor>;
// 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 <typename F> struct RevisionedMethodData :
@ -469,7 +475,14 @@ template <typename F> struct RevisionedSlotData :
template <typename F> struct RevisionedConstructorData :
FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodConstructor>
{
using FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodConstructor>::FunctionData;
using Base = FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodConstructor>;
// 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)
{}
};

View File

@ -833,7 +833,11 @@ void Generator::addFunctions(const QList<FunctionDef> &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<FunctionDef> &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");

View File

@ -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));

View File

@ -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<QByteArray> 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<QByteArray> paramNames = mm.parameterNames();
QCOMPARE(paramNames.size(), 1);
QCOMPARE(paramNames.at(0), QByteArray("str"));

View File

@ -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<QtMocHelpers::NoType()>(1, 2, AccessPublic, NoType, {});
QCOMPARE(result.header[0], 1U);
auto result = ConstructorData<QtMocHelpers::NoType()>(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<QtMocHelpers::NoType(QObject *)>(0, 1, AccessPublic, NoType,
auto result = ConstructorData<QtMocHelpers::NoType(QObject *)>(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<uint, N> &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<QObject *>());
@ -574,7 +573,7 @@ checkConstructors(const std::array<uint, N> &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<uint, N> &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<QString>());
}
@ -596,14 +595,14 @@ void tst_MocHelpers::constructorUintGroup()
using QtMocHelpers::NoType;
QTest::setThrowOnFail(true);
constexpr QtMocHelpers::UintData constructors = {
QtMocHelpers::ConstructorData<NoType(QObject *)>(0, 1, QtMocConstants::AccessPublic,
0x80000000 | 1, {{ { QMetaType::QObjectStar, 2 } }}
QtMocHelpers::ConstructorData<NoType(QObject *)>(1, QtMocConstants::AccessPublic,
{{ { QMetaType::QObjectStar, 2 } }}
),
QtMocHelpers::ConstructorData<NoType()>(0, 1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned,
0x80000000 | 1, {{ }}
QtMocHelpers::ConstructorData<NoType()>(1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned,
{{ }}
),
QtMocHelpers::ConstructorData<NoType(const QString &)>(0, 1, QtMocConstants::AccessPublic,
0x80000000 | 1, {{ { QMetaType::QString, 3 }, }}
QtMocHelpers::ConstructorData<NoType(const QString &)>(1, QtMocConstants::AccessPublic,
{{ { QMetaType::QString, 3 }, }}
)
};
testUintData(constructors);
@ -715,14 +714,14 @@ void tst_MocHelpers::uintArray()
QtMocHelpers::EnumData<QFlags<E1>>(11, 1, EnumIsFlag).add({ { 3, E1::AnEnumValue } }),
},
QtMocHelpers::UintData{
QtMocHelpers::ConstructorData<NoType(QObject *)>(0, 1, QtMocConstants::AccessPublic,
0x80000000 | 1, {{ { QMetaType::QObjectStar, 2 } }}
QtMocHelpers::ConstructorData<NoType(QObject *)>(1, QtMocConstants::AccessPublic,
{{ { QMetaType::QObjectStar, 2 } }}
),
QtMocHelpers::ConstructorData<NoType()>(0, 1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned,
0x80000000 | 1, {{ }}
QtMocHelpers::ConstructorData<NoType()>(1, QtMocConstants::AccessPublic | QtMocConstants::MethodCloned,
{{ }}
),
QtMocHelpers::ConstructorData<NoType(const QString &)>(0, 1, QtMocConstants::AccessPublic,
0x80000000 | 1, {{ { QMetaType::QString, 3 }, }}
QtMocHelpers::ConstructorData<NoType(const QString &)>(1, QtMocConstants::AccessPublic,
{{ { QMetaType::QString, 3 }, }}
)
}, QtMocHelpers::ClassInfos({{1, 2}, {3, 4}}));