summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier De Cannière <olivier.decanniere@qt.io>2025-12-03 12:35:16 +0100
committerOlivier De Cannière <olivier.decanniere@qt.io>2025-12-06 14:41:53 +0100
commit637ccf5332010b2b6480697993a779457702fd70 (patch)
treee6d11d4ee57e17398655ab9e6fec3eeebb5b87b6
parent746dba248eea494fe53fe81108e1f880cb095651 (diff)
QMetaObject: Include a class def's hash in the meta object
The hash has the following format <hash_revision>$<hash_b64>, where hash_revision is an integer and hash_b64 is the base64 encoding of the hash. MetaObjects built using QMetaObjectBuilder do not yet support the hash. That will need to be added at a later point. Task-number: QTBUG-142186 Change-Id: Ifafc7df2202decf48e8a1a45e652c2f61c5cea64 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/corelib/kernel/qmetaobject.cpp27
-rw-r--r--src/corelib/kernel/qmetaobject_p.h1
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp3
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/corelib/kernel/qtmocconstants.h3
-rw-r--r--src/corelib/kernel/qtmochelpers.h7
-rw-r--r--src/dbus/qdbusmetaobject.cpp3
-rw-r--r--src/tools/moc/generator.cpp11
-rw-r--r--src/tools/moc/generator.h6
-rw-r--r--src/tools/moc/moc.cpp4
-rw-r--r--tests/auto/tools/mochelpers/tst_mochelpers.cpp7
11 files changed, 59 insertions, 15 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 24cc58829c8..c7e50788b45 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -469,6 +469,33 @@ QMetaType QMetaObject::metaType() const
}
}
+static inline QByteArrayView objectMetaObjectHash(const QMetaObject *m)
+{
+ // metaObjectHash didn't exist before revision 14
+ if (QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && priv(m->d.data)->revision < 14)
+ return {};
+ const auto index = priv(m->d.data)->metaObjectHashIndex;
+ if (index == -1)
+ return {};
+ return stringDataView(m, index);
+}
+
+/*!
+ \since 6.11
+
+ Returns the revisioned hash of the contents of this QMetaObject or nullptr.
+
+ The hash has the following format <hash_revision>$<hash_b64>, where
+ hash_revision is an integer and hash_b64 is the base64 encoding of the
+ hash.
+
+ Note that only hashes of the same revision should be compared.
+*/
+const char *QMetaObject::metaObjectHash() const
+{
+ return objectMetaObjectHash(this).constData();
+}
+
/*!
Returns the method offset for this class; i.e. the index position
of this class's first member function.
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index bfda30fda28..7264d2a956f 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -124,6 +124,7 @@ struct QMetaObjectPrivate
int constructorCount, constructorData;
int flags;
int signalCount;
+ int metaObjectHashIndex;
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 6065bf2baea..6c1503ee97d 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -1177,10 +1177,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
int methodParametersDataSize = aggregateParameterCount(d->methods)
+ aggregateParameterCount(d->constructors);
if constexpr (mode == Construct) {
- static_assert(QMetaObjectPrivate::OutputRevision == 13, "QMetaObjectBuilder should generate the same version as moc");
+ static_assert(QMetaObjectPrivate::OutputRevision == 14, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags.toInt() | AllocatedMetaObject;
pmeta->className = 0; // Class name is always the first string.
+ pmeta->metaObjectHashIndex = -1; // TODO support hash in the builder too
//pmeta->signalCount is handled in the "output method loop" as an optimization.
pmeta->classInfoCount = d->classInfoNames.size();
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 848102cc57a..d3e761982f5 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -247,6 +247,8 @@ struct Q_CORE_EXPORT QMetaObject
QMetaType metaType() const;
+ const char *metaObjectHash() const;
+
int methodOffset() const;
int enumeratorOffset() const;
int propertyOffset() const;
diff --git a/src/corelib/kernel/qtmocconstants.h b/src/corelib/kernel/qtmocconstants.h
index 260ac2fa5f8..822e02e6c8e 100644
--- a/src/corelib/kernel/qtmocconstants.h
+++ b/src/corelib/kernel/qtmocconstants.h
@@ -30,7 +30,8 @@ namespace QtMocConstants {
// revision 11 is Qt 6.5: The metatype for void is stored in the metatypes array
// revision 12 is Qt 6.6: It adds the metatype for enums
// revision 13 is Qt 6.9: Adds support for 64-bit QFlags and moves the method revision
-enum { OutputRevision = 13 }; // Used by moc, qmetaobjectbuilder and qdbus
+// revision 14 is Qt 6.11: Adds a hash of meta object contents
+enum { OutputRevision = 14 }; // Used by moc, qmetaobjectbuilder and qdbus
enum PropertyFlags : uint {
Invalid = 0x00000000,
diff --git a/src/corelib/kernel/qtmochelpers.h b/src/corelib/kernel/qtmochelpers.h
index 4c549e78ad5..3d2b59d2a73 100644
--- a/src/corelib/kernel/qtmochelpers.h
+++ b/src/corelib/kernel/qtmochelpers.h
@@ -511,7 +511,8 @@ template <typename ObjectType, typename Unique, typename Strings,
typename Constructors = UintData<>, typename ClassInfo = detail::UintDataBlock<0, 0>>
constexpr auto metaObjectData(uint flags, const Strings &strings,
const Methods &methods, const Properties &properties,
- const Enums &enums, const Constructors &constructors = {},
+ const Enums &enums, int qt_metaObjectHashIndex = -1,
+ const Constructors &constructors = {},
const ClassInfo &classInfo = {})
{
constexpr uint MetaTypeCount = Properties::metaTypeCount()
@@ -520,7 +521,7 @@ constexpr auto metaObjectData(uint flags, const Strings &strings,
+ Methods::metaTypeCount()
+ Constructors::metaTypeCount();
- constexpr uint HeaderSize = 14;
+ constexpr uint HeaderSize = 15;
constexpr uint TotalSize = HeaderSize
+ Properties::dataSize()
+ Enums::dataSize()
@@ -582,6 +583,8 @@ constexpr auto metaObjectData(uint flags, const Strings &strings,
}
}
+ data[14] = qt_metaObjectHashIndex;
+
return result;
}
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index 149392f9c3c..a4ffd7a64dd 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -383,9 +383,10 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
- methods.size(); // ditto
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
- static_assert(QMetaObjectPrivate::OutputRevision == 13, "QtDBus meta-object generator should generate the same version as moc");
+ static_assert(QMetaObjectPrivate::OutputRevision == 14, "QtDBus meta-object generator should generate the same version as moc");
header->revision = QMetaObjectPrivate::OutputRevision;
header->className = 0;
+ header->metaObjectHashIndex = -1; // TODO support hash in dbus metaobject too
header->classInfoCount = 0;
header->classInfoData = 0;
header->methodCount = int(signals_.size() + methods.size());
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 292ec61413d..94c75ae6eb3 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -80,14 +80,16 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
Generator::Generator(Moc *moc, const ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
- bool requireCompleteTypes)
+ const QHash<QByteArray, QByteArray> &knownGadgets,
+ const QHash<QByteArray, QByteArray> &hashes,
+ FILE *outfile, bool requireCompleteTypes)
: parser(moc),
out(outfile),
cdef(classDef),
metaTypes(metaTypes),
knownQObjectClasses(knownQObjectClasses),
knownGadgets(knownGadgets),
+ hashes(hashes),
requireCompleteTypes(requireCompleteTypes)
{
if (cdef->superclassList.size())
@@ -232,6 +234,7 @@ void Generator::generateCode()
// Register all strings used in data section
//
strreg(cdef->qualified);
+ strreg(hashes[cdef->qualified]);
registerClassInfoStrings();
registerFunctionStrings(cdef->signalList);
registerFunctionStrings(cdef->slotList);
@@ -290,6 +293,8 @@ void Generator::generateCode()
addEnums();
fprintf(out, " };\n");
+ fprintf(out, " uint qt_metaObjectHashIndex = %d;\n", stridx(hashes[cdef->qualified]));
+
const char *uintDataParams = "";
if (isConstructible || !cdef->classInfoList.isEmpty()) {
if (isConstructible) {
@@ -322,7 +327,7 @@ void Generator::generateCode()
if (!requireCompleteness)
tagType = "qt_meta_tag_" + qualifiedClassNameIdentifier + "_t";
fprintf(out, " return QtMocHelpers::metaObjectData<%s, %s>(%s, qt_stringData,\n"
- " qt_methods, qt_properties, qt_enums%s);\n"
+ " qt_methods, qt_properties, qt_enums, qt_metaObjectHashIndex%s);\n"
"}\n",
ownType, tagType.constData(), metaObjectFlags, uintDataParams);
}
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 482e0de46a6..77be2fc6714 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -18,8 +18,9 @@ class Generator
public:
Generator(Moc *moc, const ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr,
- bool requireCompleteTypes = false);
+ const QHash<QByteArray, QByteArray> &knownGadgets,
+ const QHash<QByteArray, QByteArray> &hashes,
+ FILE *outfile = nullptr, bool requireCompleteTypes = false);
void generateCode();
qsizetype registeredStringsCount() { return strings.size(); }
@@ -54,6 +55,7 @@ private:
QList<QByteArray> metaTypes;
QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
+ QHash<QByteArray, QByteArray> hashes;
bool requireCompleteTypes;
};
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 1dde33ebe1e..7f05f34edb6 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1301,8 +1301,8 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
fputs("", out);
for (const ClassDef &def : std::as_const(classList)) {
- Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, out,
- requireCompleteTypes);
+ Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets,
+ metaObjectHashes, out, requireCompleteTypes);
generator.generateCode();
// generator.generateCode() should have already registered all strings
diff --git a/tests/auto/tools/mochelpers/tst_mochelpers.cpp b/tests/auto/tools/mochelpers/tst_mochelpers.cpp
index 7e5d18d160e..ae80f0c2b58 100644
--- a/tests/auto/tools/mochelpers/tst_mochelpers.cpp
+++ b/tests/auto/tools/mochelpers/tst_mochelpers.cpp
@@ -104,7 +104,7 @@ void tst_MocHelpers::classinfoDataGroup()
{
constexpr auto data = QtMocHelpers::metaObjectData<void, void>(0, dummyStringData,
QtMocHelpers::UintData{}, QtMocHelpers::UintData{},
- QtMocHelpers::UintData{}, QtMocHelpers::UintData{},
+ QtMocHelpers::UintData{}, -1, QtMocHelpers::UintData{},
QtMocHelpers::ClassInfos({{1, 2}, {3, 4}}));
checkClassInfos(data.staticData.data);
}
@@ -612,7 +612,7 @@ void tst_MocHelpers::constructorUintGroup()
constexpr auto data = QtMocHelpers::metaObjectData<void, void>(0, dummyStringData,
QtMocHelpers::UintData{}, QtMocHelpers::UintData{},
- QtMocHelpers::UintData{}, constructors);
+ QtMocHelpers::UintData{}, -1, constructors);
checkConstructors(data.staticData.data, data.relocatingData.metaTypes);
}
@@ -676,7 +676,7 @@ void tst_MocHelpers::uintArrayNoMethods()
QtMocHelpers::EnumData<E2>(7, 6, EnumIsFlag | EnumIsScoped)
.add({ { 7, E2::V0 }, { 10, E2::V1 }, }),
QtMocHelpers::EnumData<QFlags<E1>>(11, 1, EnumIsFlag).add({ { 3, E1::AnEnumValue } }),
- }, QtMocHelpers::UintData{}, QtMocHelpers::ClassInfos({{1, 2}, {3, 4}}));
+ }, -1, QtMocHelpers::UintData{}, QtMocHelpers::ClassInfos({{1, 2}, {3, 4}}));
auto &data = mo.staticData.data;
auto &metaTypes = mo.relocatingData.metaTypes;
@@ -724,6 +724,7 @@ void tst_MocHelpers::uintArray()
.add({ { 7, E2::V0 }, { 10, E2::V1 }, }),
QtMocHelpers::EnumData<QFlags<E1>>(11, 1, EnumIsFlag).add({ { 3, E1::AnEnumValue } }),
},
+ -1,
QtMocHelpers::UintData{
QtMocHelpers::ConstructorData<NoType(QObject *)>(1, QtMocConstants::AccessPublic,
{{ { QMetaType::QObjectStar, 2 } }}