QMetaObjectBuilder: Fix construction logic for enums

We need to put metatypes in the correct place; this is especially vital
starting with Qt 6.9, given that we need it to query it to figure out
whether we have a 64bit value or not.

As a drive-by, replace some ugly casting when constructing the meta-type
array with a call to QMetaType::iface.

Change-Id: I4b1f42f974e9f7a21f6aa4c87c3f8919f6965d6e
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit d392d3b22c94f86fea50f26284bc9ac8b35f6851)
This commit is contained in:
Fabian Kosmale 2024-10-07 15:13:38 +02:00
parent d12327bc3c
commit dd5c13d09e
2 changed files with 33 additions and 6 deletions

View File

@ -1250,8 +1250,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the methods in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
// + 1 for metatype of this metaobject
int parameterMetaTypesIndex = int(d->properties.size()) + 1;
// property count + enum count + 1 for metatype of this metaobject
int parameterMetaTypesIndex = int(d->properties.size()) + int(d->enumerators.size()) + 1;
for (const auto &method : d->methods) {
[[maybe_unused]] int name = strings.enter(method.name());
int argc = method.parameterCount();
@ -1409,12 +1409,19 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
ALIGN(size, QtPrivate::QMetaTypeInterface *);
auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size);
auto types = reinterpret_cast<const QtPrivate::QMetaTypeInterface **>(buf + size);
if constexpr (mode == Construct) {
meta->d.metaTypes = types;
for (const auto &prop : d->properties) {
QMetaType mt = prop.metaType;
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
*types = mt.iface();
types++;
}
// add metatypes for enumerators
for (const auto &enumerator: d->enumerators) {
QMetaType mt = enumerator.metaType;
mt.registerType();
*types = mt.iface();
types++;
}
// add metatype interface for this metaobject - must be null
@ -1427,14 +1434,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
types++;
for (const auto &parameterType: method.parameterTypes()) {
QMetaType mt = QMetaType::fromName(parameterType);
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
*types = mt.iface();
types++;
}
}
for (const auto &constructor : d->constructors) {
for (const auto &parameterType : constructor.parameterTypes()) {
QMetaType mt = QMetaType::fromName(parameterType);
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
*types = mt.iface();
types++;
}
}

View File

@ -39,6 +39,7 @@ private slots:
void classNameFirstInStringData();
void propertyMetaType();
void enumCloning();
void cleanupTestCase();
@ -1657,6 +1658,25 @@ void tst_QMetaObjectBuilder::propertyMetaType()
free(mo);
}
void tst_QMetaObjectBuilder::enumCloning()
{
QMetaObjectBuilder builder(&SomethingOfEverything::staticMetaObject);
auto smo = SomethingOfEverything::staticMetaObject;
auto mo = builder.toMetaObject();
auto cleanup = qScopeGuard([&]() { free(mo); });
QCOMPARE_EQ(mo->enumeratorCount(), smo.enumeratorCount());
for (int enumIndex = 0; enumIndex < smo.enumeratorCount(); ++enumIndex) {
QMetaEnum metaEnumFromBuilder = mo->enumerator(enumIndex);
QMetaEnum originalMetaEnum = smo.enumerator(enumIndex);
QCOMPARE_EQ(metaEnumFromBuilder.metaType(), originalMetaEnum.metaType());
QCOMPARE_EQ(metaEnumFromBuilder.keyCount(), originalMetaEnum.keyCount());
for (int k = 0; k < originalMetaEnum.keyCount(); ++k) {
QCOMPARE_EQ(QByteArrayView(metaEnumFromBuilder.key(k)), QByteArrayView(originalMetaEnum.key(k)));
QCOMPARE_EQ(metaEnumFromBuilder.value(k), originalMetaEnum.value(k));
}
}
}
void tst_QMetaObjectBuilder::ownMetaTypeNoProperties()
{
QMetaObjectBuilder builder;