diff options
| author | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-12-03 12:35:16 +0100 |
|---|---|---|
| committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-12-06 14:41:53 +0100 |
| commit | 637ccf5332010b2b6480697993a779457702fd70 (patch) | |
| tree | e6d11d4ee57e17398655ab9e6fec3eeebb5b87b6 | |
| parent | 746dba248eea494fe53fe81108e1f880cb095651 (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.cpp | 27 | ||||
| -rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 1 | ||||
| -rw-r--r-- | src/corelib/kernel/qmetaobjectbuilder.cpp | 3 | ||||
| -rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 2 | ||||
| -rw-r--r-- | src/corelib/kernel/qtmocconstants.h | 3 | ||||
| -rw-r--r-- | src/corelib/kernel/qtmochelpers.h | 7 | ||||
| -rw-r--r-- | src/dbus/qdbusmetaobject.cpp | 3 | ||||
| -rw-r--r-- | src/tools/moc/generator.cpp | 11 | ||||
| -rw-r--r-- | src/tools/moc/generator.h | 6 | ||||
| -rw-r--r-- | src/tools/moc/moc.cpp | 4 | ||||
| -rw-r--r-- | tests/auto/tools/mochelpers/tst_mochelpers.cpp | 7 |
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 } }} |
