summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetaobject.cpp27
-rw-r--r--src/corelib/kernel/qmetaobject_p.h2
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp9
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/dbus/qdbusmetaobject.cpp6
-rw-r--r--src/tools/moc/generator.cpp95
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp11
7 files changed, 98 insertions, 54 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 650ea60617..a574bec179 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -384,6 +384,33 @@ QString QMetaObject::tr(const char *s, const char *c, int n) const
{
return QCoreApplication::translate(objectClassName(this), s, c, n);
}
+
+/*!
+ \since 6.2
+ Returns the metatype corresponding to this metaobject.
+ If the metaobject originates from a namespace, an invalid metatype is returned.
+ */
+QMetaType QMetaObject::metaType() const
+{
+
+ const QMetaObjectPrivate *d = priv(this->d.data);
+ if (d->revision < 10) {
+ // before revision 10, we did not store the metatype in the metatype array
+ return QMetaType::fromName(className());
+ } else {
+ /* in the metatype array, we store
+ idx: 0 propertyCount - 1 propertyCount
+ data:QMetaType(prop0), ..., QMetaType(propPropCount-1), QMetaType(class),...
+ */
+ auto iface = this->d.metaTypes[d->propertyCount];
+ if (iface == QtPrivate::qMetaTypeInterfaceForType<void>())
+ return QMetaType(); // return invalid meta-type for namespaces
+ if (iface)
+ return QMetaType(iface);
+ else // in case of a dynamic metaobject, we might have no metatype stored
+ return QMetaType::fromName(className()); // try lookup by name in that case
+ }
+}
#endif // QT_NO_TRANSLATION
/*!
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index dbd82ba27b..c25735cb86 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -172,7 +172,7 @@ struct QMetaObjectPrivate
// revision 7 is Qt 5.0 everything lower is not supported
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
// revision 9 is Qt 6.0: It adds the metatype of properties and methods
- enum { OutputRevision = 9 }; // Used by moc, qmetaobjectbuilder and qdbus
+ enum { OutputRevision = 10 }; // Used by moc, qmetaobjectbuilder and qdbus
enum { IntsPerMethod = QMetaMethod::Data::Size };
enum { IntsPerEnum = QMetaEnum::Data::Size };
enum { IntsPerProperty = QMetaProperty::Data::Size };
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 3ee7d17545..8c55bdb3ae 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1203,7 +1203,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
- int(d->methods.size()) // return "parameters" don't have names
- int(d->constructors.size()); // "this" parameters don't have names
if constexpr (mode == Construct) {
- static_assert(QMetaObjectPrivate::OutputRevision == 9, "QMetaObjectBuilder should generate the same version as moc");
+ static_assert(QMetaObjectPrivate::OutputRevision == 10, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
@@ -1281,7 +1281,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
// Output the methods in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
- int parameterMetaTypesIndex = int(d->properties.size());
+ // + 1 for metatype of this metaobject
+ int parameterMetaTypesIndex = int(d->properties.size()) + 1;
for (const auto &method : d->methods) {
[[maybe_unused]] int name = strings.enter(method.name());
int argc = method.parameterCount();
@@ -1448,6 +1449,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
types++;
}
+ // add metatype interface for this metaobject - must be null
+ // as we can't know our metatype
+ *types = nullptr;
+ types++;
for (const auto &method: d->methods) {
QMetaType mt(QMetaType::fromName(method.returnType).id());
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 5ade222ac5..00a6b62eab 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -173,6 +173,8 @@ struct Q_CORE_EXPORT QMetaObject
QString tr(const char *s, const char *c, int n = -1) const;
#endif // QT_NO_TRANSLATION
+ QMetaType metaType() const;
+
int methodOffset() const;
int enumeratorOffset() const;
int propertyOffset() const;
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index 90a50cc600..1026f6429f 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -422,7 +422,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
- methods.count(); // ditto
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
- static_assert(QMetaObjectPrivate::OutputRevision == 9, "QtDBus meta-object generator should generate the same version as moc");
+ static_assert(QMetaObjectPrivate::OutputRevision == 10, "QtDBus meta-object generator should generate the same version as moc");
header->revision = QMetaObjectPrivate::OutputRevision;
header->className = 0;
header->classInfoCount = 0;
@@ -459,6 +459,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
idata[typeidOffset++] = 0; // eod
int totalMetaTypeCount = properties.count();
+ ++totalMetaTypeCount; // + 1 for metatype of dynamic metaobject
for (const auto& methodContainer: {signals_, methods}) {
for (const auto& method: methodContainer) {
int argc = method.inputTypes.size() + qMax(qsizetype(0), method.outputTypes.size() - 1);
@@ -469,7 +470,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
int propertyId = 0;
// add each method:
- int currentMethodMetaTypeOffset = properties.count();
+ int currentMethodMetaTypeOffset = properties.count() + 1;
for (int x = 0; x < 2; ++x) {
// Signals must be added before other methods, to match moc.
QMap<QByteArray, Method> &map = (x == 0) ? signals_ : methods;
@@ -559,6 +560,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
metaTypes[propertyId++] = QMetaType(mp.type);
}
+ metaTypes[propertyId] = QMetaType(); // we can't know our own metatype
Q_ASSERT(offset == header->propertyDBusData);
Q_ASSERT(signatureOffset == header->methodDBusData);
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 78829ce93c..ad3df36292 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -396,7 +396,8 @@ void Generator::generateCode()
//
generateClassInfos();
- int initialMetaTypeOffset = cdef->propertyList.count();
+ // all property metatypes, + 1 for the type of the current class itself
+ int initialMetaTypeOffset = cdef->propertyList.count() + 1;
//
// Build signals array first, otherwise the signal indices would be wrong
@@ -560,64 +561,60 @@ void Generator::generateCode()
else
fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData());
- bool constructorListContainsArgument = false;
- for (int i = 0; i< cdef->constructorList.count(); ++i) {
- const FunctionDef& fdef = cdef->constructorList.at(i);
- if (fdef.arguments.count()) {
- constructorListContainsArgument = true;
- break;
- }
- }
- if (cdef->propertyList.isEmpty() && cdef->signalList.isEmpty() && cdef->slotList.isEmpty() && cdef->methodList.isEmpty() && !constructorListContainsArgument) {
- fprintf(out, " nullptr,\n");
+ bool needsComma = false;
+ const bool requireCompleteness = requireCompleteTypes || cdef->requireCompleteMethodTypes;
+ if (!requireCompleteness) {
+ fprintf(out, "qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t\n", qualifiedClassNameIdentifier.constData());
+ needsComma = true;
} else {
- bool needsComma = false;
- const bool requireCompleteness = requireCompleteTypes || cdef->requireCompleteMethodTypes;
- if (!requireCompleteness) {
- fprintf(out, "qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t\n", qualifiedClassNameIdentifier.constData());
- needsComma = true;
- } else {
- fprintf(out, "qt_metaTypeArray<\n");
- }
- for (int i = 0; i < cdef->propertyList.count(); ++i) {
- const PropertyDef &p = cdef->propertyList.at(i);
+ fprintf(out, "qt_metaTypeArray<\n");
+ }
+ // metatypes for properties
+ for (int i = 0; i < cdef->propertyList.count(); ++i) {
+ const PropertyDef &p = cdef->propertyList.at(i);
+ if (requireCompleteness)
+ fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data());
+ else
+ fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", p.type.data());
+ needsComma = true;
+ }
+ // type name for the Q_OJBECT/GADGET itself, void for namespaces
+ auto ownType = !cdef->hasQNamespace ? cdef->classname.data() : "void";
+ if (requireCompleteness)
+ fprintf(out, "%s%s", needsComma ? ", " : "", ownType);
+ else
+ fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", ownType);
+
+ // metatypes for all exposed methods
+ // no need to check for needsComma any longer, as we always need one due to the classname being present
+ for (const QList<FunctionDef> &methodContainer :
+ { cdef->signalList, cdef->slotList, cdef->methodList }) {
+ for (int i = 0; i< methodContainer.count(); ++i) {
+ const FunctionDef& fdef = methodContainer.at(i);
if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data());
+ fprintf(out, ", %s", fdef.type.name.data());
else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::true_type>", needsComma ? ", " : "", p.type.data());
- needsComma = true;
- }
- for (const QList<FunctionDef> &methodContainer :
- { cdef->signalList, cdef->slotList, cdef->methodList }) {
- for (int i = 0; i< methodContainer.count(); ++i) {
- const FunctionDef& fdef = methodContainer.at(i);
- if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", fdef.type.name.data());
- else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::false_type>", needsComma ? ", " : "", fdef.type.name.data());
- needsComma = true;
- for (const auto &argument: fdef.arguments) {
- if (requireCompleteness)
- fprintf(out, ", %s", argument.type.name.data());
- else
- fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
- }
- }
- fprintf(out, "\n");
- }
- for (int i = 0; i< cdef->constructorList.count(); ++i) {
- const FunctionDef& fdef = cdef->constructorList.at(i);
+ fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", fdef.type.name.data());
for (const auto &argument: fdef.arguments) {
if (requireCompleteness)
- fprintf(out, "%s%s", needsComma ? ", " : "", argument.type.name.data());
+ fprintf(out, ", %s", argument.type.name.data());
else
- fprintf(out, "%sQtPrivate::TypeAndForceComplete<%s, std::false_type>", needsComma ? ", " : "", argument.type.name.data());
- needsComma = true;
+ fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
}
}
fprintf(out, "\n");
- fprintf(out, ">,\n");
}
+ for (int i = 0; i< cdef->constructorList.count(); ++i) {
+ const FunctionDef& fdef = cdef->constructorList.at(i);
+ for (const auto &argument: fdef.arguments) {
+ if (requireCompleteness)
+ fprintf(out, ", %s", argument.type.name.data());
+ else
+ fprintf(out, ", QtPrivate::TypeAndForceComplete<%s, std::false_type>", argument.type.name.data());
+ }
+ }
+ fprintf(out, "\n");
+ fprintf(out, ">,\n");
fprintf(out, " nullptr\n} };\n\n");
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 86501b74ea..968ccee043 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -315,6 +315,8 @@ private slots:
void propertyConstant();
void propertyFinal();
+ void metaType();
+
void stdSet();
void classInfo();
@@ -1612,6 +1614,15 @@ void tst_QMetaObject::propertyFinal()
QVERIFY(!prop.isFinal());
}
+void tst_QMetaObject::metaType()
+{
+ QCOMPARE(QObject::staticMetaObject.metaType(), QMetaType::fromType<QObject>());
+ QCOMPARE(MyGadget::staticMetaObject.metaType(), QMetaType::fromType<MyGadget>());
+ QCOMPARE(QAbstractProxyModel::staticMetaObject.metaType(), QMetaType::fromType<QAbstractProxyModel>());
+ auto qtNameSpaceMetaType = Qt::staticMetaObject.metaType();
+ QVERIFY2(!qtNameSpaceMetaType.isValid(), qtNameSpaceMetaType.name());
+}
+
class ClassInfoTestObjectA : public QObject
{
Q_OBJECT