diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-19 10:47:29 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-06-02 22:42:15 +0200 |
commit | fa987d44417528856d5e80ed7b48ba99e19fa307 (patch) | |
tree | 50cd74c1a9dd3c2197f7de2ac0d431a5b16b0a42 /src | |
parent | 5306fdabc1ceb09875f791526553b3665017f7ce (diff) |
MetaObject: Store the QMetaType of the methods
This does the analog of 46f407126ef3e94d59254012cdc34d6a4ad2faf2 for the
methods we care about (signals, slots, Q_INVOKABLEs). In addition to the
actual QMetaType, we store an array with offsets so that we later can do
a mapping from methodIndex to metatype.
The newly added QMetaMethod::{return,parameter}MetaType methods can then
be used to retrieve the metatypes.
This does however require that all involved types are complete. This is
unfortunately not a feasible requirement. Thus, we only populate the
metatype array on a best effort basis. For any incomplete type, we store
QMetaType::Unknown. Then, when accessing the metatype, we fall back to
the old string based code base if it's Unknown.
Squashes "moc: support incomplete types" and "Fix compile failures
after QMetaMethod change"
Fixes: QTBUG-82932
Change-Id: I6b7a587cc364b7cad0c158d6de54e8a204289ad4
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
41 files changed, 280 insertions, 92 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index f68a042db0..a234b46d70 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -618,7 +618,7 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject, ? (priv(m->d.data)->signalCount) : 0; for (; i >= end; --i) { - int handle = priv(m->d.data)->methodData + 5*i; + int handle = priv(m->d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i; if (methodMatch(m, handle, name, argc, types)) { *baseObject = m; return i; @@ -819,7 +819,7 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra int argc, const QArgumentType *types) { for (int i = priv(m->d.data)->constructorCount-1; i >= 0; --i) { - int handle = priv(m->d.data)->constructorData + 5*i; + int handle = priv(m->d.data)->constructorData + QMetaObjectPrivate::IntsPerMethod*i; if (methodMatch(m, handle, name, argc, types)) return i; } @@ -895,7 +895,7 @@ QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index) if (i >= 0 && i < priv(m->d.data)->signalCount) { result.mobj = m; - result.handle = priv(m->d.data)->methodData + 5*i; + result.handle = priv(m->d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i; } return result; } @@ -1078,7 +1078,7 @@ QMetaMethod QMetaObject::constructor(int index) const Q_ASSERT(priv(d.data)->revision >= 2); if (i >= 0 && i < priv(d.data)->constructorCount) { result.mobj = this; - result.handle = priv(d.data)->constructorData + 5*i; + result.handle = priv(d.data)->constructorData + QMetaObjectPrivate::IntsPerMethod*i; } return result; } @@ -1098,7 +1098,7 @@ QMetaMethod QMetaObject::method(int index) const QMetaMethod result; if (i >= 0 && i < priv(d.data)->methodCount) { result.mobj = this; - result.handle = priv(d.data)->methodData + 5*i; + result.handle = priv(d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i; } return result; } @@ -1844,7 +1844,7 @@ QByteArray QMetaMethodPrivate::tag() const int QMetaMethodPrivate::ownMethodIndex() const { // recompute the methodIndex by reversing the arithmetic in QMetaObject::property() - return (handle - priv(mobj->d.data)->methodData) / 5; + return (handle - priv(mobj->d.data)->methodData) / QMetaObjectPrivate::IntsPerMethod; } /*! @@ -1884,13 +1884,30 @@ QByteArray QMetaMethod::name() const The return value is one of the types that are registered with QMetaType, or QMetaType::UnknownType if the type is not registered. - \sa parameterType(), QMetaType, typeName() + \sa parameterType(), QMetaType, typeName(), returnMetaType() */ int QMetaMethod::returnType() const { if (!mobj) return QMetaType::UnknownType; - return QMetaMethodPrivate::get(this)->returnType(); + return QMetaMethodPrivate::get(this)->returnType(); +} + +/*! + \since 6.0 + + Returns the return type of this method. + \sa parameterMetaType(), QMetaType, typeName() +*/ +QMetaType QMetaMethod::returnMetaType() const +{ + if (!mobj || methodType() == QMetaMethod::Constructor) + return QMetaType{}; + auto mt = QMetaType(mobj->d.metaTypes[mobj->d.data[handle + 5]]); + if (mt.id() == QMetaType::UnknownType) + return QMetaType(QMetaMethodPrivate::get(this)->returnType()); + else + return mt; } /*! @@ -1915,24 +1932,37 @@ int QMetaMethod::parameterCount() const The return value is one of the types that are registered with QMetaType, or QMetaType::UnknownType if the type is not registered. - \sa parameterCount(), returnType(), QMetaType + \sa parameterCount(), parameterMetaType(), returnType(), QMetaType */ int QMetaMethod::parameterType(int index) const { - if (!mobj || index < 0) - return QMetaType::UnknownType; - if (index >= QMetaMethodPrivate::get(this)->parameterCount()) - return QMetaType::UnknownType; + return parameterMetaType(index).id(); +} + +/*! + \since 6.0 + + Returns the metatype of the parameter at the given \a index. - int type = QMetaMethodPrivate::get(this)->parameterType(index); - if (type != QMetaType::UnknownType) - return type; + If the \a index is smaller than zero or larger than + parameterCount(), an invalid QMetaType is returned. - void *argv[] = { &type, &index }; - mobj->static_metacall(QMetaObject::RegisterMethodArgumentMetaType, QMetaMethodPrivate::get(this)->ownMethodIndex(), argv); - if (type != -1) - return type; - return QMetaType::UnknownType; + \sa parameterCount(), returnMetaType(), QMetaType +*/ +QMetaType QMetaMethod::parameterMetaType(int index) const +{ + if (!mobj || index < 0) + return {}; + auto priv = QMetaMethodPrivate::get(this); + if (index >= priv->parameterCount()) + return {}; + // + 1 if there exists a return type + auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1); + auto mt = QMetaType(mobj->d.metaTypes[mobj->d.data[handle + 5] + parameterOffset]); + if (mt.id() == QMetaType::UnknownType) + return QMetaType(QMetaMethodPrivate::get(this)->parameterType(index)); + else + return mt; } /*! @@ -2055,7 +2085,7 @@ int QMetaMethod::revision() const return 0; if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) { int offset = priv(mobj->d.data)->methodData - + priv(mobj->d.data)->methodCount * 5 + + priv(mobj->d.data)->methodCount * QMetaObjectPrivate::IntsPerMethod + QMetaMethodPrivate::get(this)->ownMethodIndex(); return mobj->d.data[offset]; } @@ -2120,7 +2150,7 @@ QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **si m->static_metacall(QMetaObject::IndexOfMethod, 0, args); if (i >= 0) { result.mobj = m; - result.handle = priv(m->d.data)->methodData + 5*i; + result.handle = priv(m->d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i; break; } } @@ -3712,10 +3742,10 @@ const char* QMetaClassInfo::value() const int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index) { Q_ASSERT(local_method_index < get(mobj)->methodCount); - int handle = get(mobj)->methodData + 5 * local_method_index; + int handle = get(mobj)->methodData + QMetaObjectPrivate::IntsPerMethod * local_method_index; while (mobj->d.data[handle + 4] & MethodCloned) { Q_ASSERT(local_method_index > 0); - handle -= 5; + handle -= QMetaObjectPrivate::IntsPerMethod; local_method_index--; } return local_method_index; diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index b0d6cb7446..67f5efe6f6 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -57,8 +57,10 @@ public: QByteArray name() const; const char *typeName() const; int returnType() const; + QMetaType returnMetaType() const; int parameterCount() const; int parameterType(int index) const; + QMetaType parameterMetaType(int index) const; void getParameterTypes(int *types) const; QList<QByteArray> parameterTypes() const; QList<QByteArray> parameterNames() const; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 49c43e3d79..b825c983f9 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -176,7 +176,9 @@ 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 - enum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbus + // revision 9 is Qt 6.0: It adds the metatype of properties and methods + enum { OutputRevision = 9 }; // Used by moc, qmetaobjectbuilder and qdbus + enum { IntsPerMethod = 6}; int revision; int className; diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index a2dedda0ad..7b9b06ed3e 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -1216,7 +1216,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 (buf) { - Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QMetaObjectBuilder should generate the same version as moc"); + Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 9, "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. @@ -1228,7 +1228,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, pmeta->methodCount = int(d->methods.size()); pmeta->methodData = dataIndex; - dataIndex += 5 * int(d->methods.size()); + dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->methods.size()); if (hasRevisionedMethods) dataIndex += int(d->methods.size()); paramsIndex = dataIndex; @@ -1248,10 +1248,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, pmeta->constructorCount = int(d->constructors.size()); pmeta->constructorData = dataIndex; - dataIndex += 5 * int(d->constructors.size()); + dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->constructors.size()); } else { dataIndex += 2 * int(d->classInfoNames.size()); - dataIndex += 5 * int(d->methods.size()); + dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->methods.size()); if (hasRevisionedMethods) dataIndex += int(d->methods.size()); paramsIndex = dataIndex; @@ -1262,7 +1262,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, if (hasRevisionedProperties) dataIndex += int(d->properties.size()); dataIndex += 5 * int(d->enumerators.size()); - dataIndex += 5 * int(d->constructors.size()); + dataIndex += QMetaObjectPrivate::IntsPerMethod * int(d->constructors.size()); } // Allocate space for the enumerator key names and values. @@ -1307,6 +1307,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, // Output the methods in the class. Q_ASSERT(!buf || dataIndex == pmeta->methodData); + int parameterMetaTypesIndex = d->properties.size(); for (const auto &method : d->methods) { int name = strings.enter(method.name()); int argc = method.parameterCount(); @@ -1318,11 +1319,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, data[dataIndex + 2] = paramsIndex; data[dataIndex + 3] = tag; data[dataIndex + 4] = attrs; + data[dataIndex + 5] = parameterMetaTypesIndex; if (method.methodType() == QMetaMethod::Signal) pmeta->signalCount++; } - dataIndex += 5; + dataIndex += QMetaObjectPrivate::IntsPerMethod; paramsIndex += 1 + argc * 2; + parameterMetaTypesIndex += 1 + argc; } if (hasRevisionedMethods) { for (const auto &method : d->methods) { @@ -1333,7 +1336,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, } // Output the method parameters in the class. - Q_ASSERT(!buf || dataIndex == pmeta->methodData + int(d->methods.size()) * 5 + Q_ASSERT(!buf || dataIndex == pmeta->methodData + int(d->methods.size()) * QMetaObjectPrivate::IntsPerMethod + (hasRevisionedMethods ? int(d->methods.size()) : 0)); for (int x = 0; x < 2; ++x) { const std::vector<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors; @@ -1446,9 +1449,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, data[dataIndex + 2] = paramsIndex; data[dataIndex + 3] = tag; data[dataIndex + 4] = attrs; + data[dataIndex + 5] = parameterMetaTypesIndex; } - dataIndex += 5; + dataIndex += QMetaObjectPrivate::IntsPerMethod; paramsIndex += 1 + argc * 2; + parameterMetaTypesIndex += argc; } size += strings.blobSize(); @@ -1474,7 +1479,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1); } - if (d->properties.size() > 0) { + if (d->properties.size() > 0 || d->methods.size() > 0 || d->constructors.size() > 0) { ALIGN(size, QtPrivate::QMetaTypeInterface *); auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size); if (buf) { @@ -1484,8 +1489,26 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt); types++; } + for (const auto &method: d->methods) { + QMetaType mt(QMetaType::type(method.returnType)); + *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt); + types++; + for (const auto ¶meterType: method.parameterTypes()) { + QMetaType mt(QMetaType::type(parameterType)); + *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt); + types++; + } + } + for (const auto &constructor: d->constructors) { + for (const auto ¶meterType: constructor.parameterTypes()) { + QMetaType mt(QMetaType::type(parameterType)); + *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt); + types++; + } + } } - size += static_cast<int>(sizeof(QMetaType) * d->properties.size()); + // parameterMetaTypesIndex is equal to the total number of metatypes + size += static_cast<int>(sizeof(QMetaType) * parameterMetaTypesIndex); } // Align the final size and return it. diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 05fe4450df..60192e4131 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -2796,6 +2796,35 @@ constexpr QMetaTypeInterface *qMetaTypeInterfaceForType() } } +namespace detail { + +template <typename T, typename ODR_VIOLATION_PREVENTER> +struct is_complete_helper { + template <typename U> + static auto check(U*) -> std::integral_constant<bool, sizeof(U) != 0>; + static auto check(...) -> std::false_type; + using type = decltype(check(static_cast<T*>(nullptr))); +}; + +} + +template <typename T, typename ODR_VIOLATION_PREVENTER> +struct is_complete : detail::is_complete_helper<T, ODR_VIOLATION_PREVENTER>::type {}; + +template<typename Unique, typename T> +constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType() +{ + using Ty = std::remove_cv_t<std::remove_reference_t<T>>; + using Tz = std::remove_pointer_t<Ty>; + if constexpr (!is_complete<Tz, Unique>::value) { + return nullptr; + } else if constexpr (std::is_same_v<Ty, void>) { + return nullptr; + } else { + return &QMetaTypeForType<Ty>::metaType; + } +} + } // namespace QtPrivate template<typename T> @@ -2809,6 +2838,11 @@ QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = { QtPrivate::qMetaTypeInterfaceForType<T>()... }; +template<typename Unique,typename... T> +QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = { + QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()... +}; + QT_END_NAMESPACE #endif // QMETATYPE_H diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ad810c8b26..11ec534434 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2562,7 +2562,7 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal, "QObject::isSignalConnected" , "the parameter must be a signal member of the object"); - uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/5; + uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/QMetaObjectPrivate::IntsPerMethod; if (signal.mobj->d.data[signal.handle + 4] & MethodCloned) signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex); @@ -2610,7 +2610,7 @@ void QMetaObjectPrivate::memberIndexes(const QObject *obj, m = m->d.superdata; if (!m) return; - *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5; + *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/QMetaObjectPrivate::IntsPerMethod; int signalOffset; int methodOffset; diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 412b428bdc..409be08ff0 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -76,25 +76,6 @@ static void preventDllUnload(); Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) -struct QDBusConnectionManager::ConnectionRequestData -{ - enum RequestType { - ConnectToStandardBus, - ConnectToBusByAddress, - ConnectToPeerByAddress - } type; - - union { - QDBusConnection::BusType busType; - const QString *busAddress; - }; - const QString *name; - - QDBusConnectionPrivate *result; - - bool suspendedDelivery; -}; - QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::BusType type) { Q_STATIC_ASSERT(int(QDBusConnection::SessionBus) + int(QDBusConnection::SystemBus) == 1); diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h index 1361fc5035..7304f2a8a2 100644 --- a/src/dbus/qdbusconnection.h +++ b/src/dbus/qdbusconnection.h @@ -77,6 +77,8 @@ class QDBusConnectionPrivate; class Q_DBUS_EXPORT QDBusConnection { Q_GADGET + Q_MOC_INCLUDE(<QtDBus/qdbuspendingcall.h>) + public: enum BusType { SessionBus, SystemBus, ActivationBus }; Q_ENUM(BusType) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 9bedbcc3a5..ce83270ac2 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -70,6 +70,7 @@ #include <qdbusmessage.h> #include <qdbusservicewatcher.h> // for the WatchMode enum +Q_MOC_INCLUDE(<QtDBus/private/qdbuspendingcall_p.h>) #ifndef QT_NO_DBUS diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index ac49683cee..e080abca5e 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -100,6 +100,26 @@ private: QString senderName; // internal; will probably change }; +// TODO: move into own header and use Q_MOC_INCLUDE +struct QDBusConnectionManager::ConnectionRequestData +{ + enum RequestType { + ConnectToStandardBus, + ConnectToBusByAddress, + ConnectToPeerByAddress + } type; + + union { + QDBusConnection::BusType busType; + const QString *busAddress; + }; + const QString *name; + + QDBusConnectionPrivate *result; + + bool suspendedDelivery; +}; + QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index 50538b395b..8964f20415 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -141,6 +141,9 @@ Q_DBUS_EXPORT QDebug operator<<(QDebug, const QDBusError &); QT_END_NAMESPACE Q_DECLARE_METATYPE(QDBusError) - +#else +QT_BEGIN_NAMESPACE +class Q_DBUS_EXPORT QDBusError {}; // dummy class for moc +QT_END_NAMESPACE #endif // QT_NO_DBUS #endif diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h index 33a706abd2..cd8f74d8bc 100644 --- a/src/dbus/qdbusmessage.h +++ b/src/dbus/qdbusmessage.h @@ -139,6 +139,8 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QDBusMessage) +#else +class Q_DBUS_EXPORT QDBusMessage {}; // dummy class for moc #endif // QT_NO_DBUS #endif diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 01eb1aee3f..265d0eacfa 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -416,7 +416,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) - methods.count(); // ditto QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data()); - Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QtDBus meta-object generator should generate the same version as moc"); + Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 9, "QtDBus meta-object generator should generate the same version as moc"); header->revision = QMetaObjectPrivate::OutputRevision; header->className = 0; header->classInfoCount = 0; @@ -424,7 +424,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) header->methodCount = signals_.count() + methods.count(); header->methodData = idata.size(); header->propertyCount = properties.count(); - header->propertyData = header->methodData + header->methodCount * 5 + methodParametersDataSize; + header->propertyData = header->methodData + header->methodCount * QMetaObjectPrivate::IntsPerMethod + methodParametersDataSize; header->enumeratorCount = 0; header->enumeratorData = 0; header->constructorCount = 0; @@ -436,7 +436,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty; int data_size = idata.size() + - (header->methodCount * (5+intsPerMethod)) + methodParametersDataSize + + (header->methodCount * (QMetaObjectPrivate::IntsPerMethod+intsPerMethod)) + methodParametersDataSize + (header->propertyCount * (3+intsPerProperty)); for (const Method &mm : qAsConst(signals_)) data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count(); @@ -447,12 +447,23 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) QMetaStringTable strings(className.toLatin1()); int offset = header->methodData; - int parametersOffset = offset + header->methodCount * 5; + int parametersOffset = offset + header->methodCount * QMetaObjectPrivate::IntsPerMethod; int signatureOffset = header->methodDBusData; int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod; idata[typeidOffset++] = 0; // eod + int totalMetaTypeCount = properties.count(); + for (const auto& methodContainer: {signals_, methods}) { + for (const auto& method: methodContainer) { + int argc = method.inputTypes.size() + qMax(qsizetype(0), method.outputTypes.size() - 1); + totalMetaTypeCount += argc + 1; + } + } + QMetaType *metaTypes = new QMetaType[totalMetaTypeCount]; + int propertyId = 0; + // add each method: + int currentMethodMetaTypeOffset = properties.count(); 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; @@ -467,6 +478,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) idata[offset++] = parametersOffset; idata[offset++] = strings.enter(mm.tag); idata[offset++] = mm.flags; + idata[offset++] = currentMethodMetaTypeOffset; // Parameter types for (int i = -1; i < argc; ++i) { @@ -496,6 +508,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) typeInfo = IsUnresolvedType | strings.enter(typeName); else typeInfo = type; + metaTypes[currentMethodMetaTypeOffset++] = QMetaType (type); idata[parametersOffset++] = typeInfo; } // Parameter names @@ -514,16 +527,13 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) } } - Q_ASSERT(offset == header->methodData + header->methodCount * 5); + Q_ASSERT(offset == header->methodData + header->methodCount * QMetaObjectPrivate::IntsPerMethod); Q_ASSERT(parametersOffset == header->propertyData); Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod); Q_ASSERT(typeidOffset == idata.size()); offset += methodParametersDataSize; Q_ASSERT(offset == header->propertyData); - QMetaType *metaTypes = new QMetaType[properties.count()]; - int propertyId = 0; - // add each property signatureOffset = header->propertyDBusData; for (QMap<QByteArray, Property>::ConstIterator it = properties.constBegin(); diff --git a/src/gui/kernel/qoffscreensurface.h b/src/gui/kernel/qoffscreensurface.h index 1b9e7c00ca..cfdcd758ec 100644 --- a/src/gui/kernel/qoffscreensurface.h +++ b/src/gui/kernel/qoffscreensurface.h @@ -43,6 +43,7 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/QObject> #include <QtGui/qsurface.h> +Q_MOC_INCLUDE(<QScreen>) QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index ba800a696f..fa58177a2d 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -58,6 +58,8 @@ #include <QtCore/QDir> #include <QtCore/QUrl> #include <QtGui/QRgb> +Q_MOC_INCLUDE(<QFont>) +Q_MOC_INCLUDE(<QColor>) QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qplatformnativeinterface.h b/src/gui/kernel/qplatformnativeinterface.h index 95d6a03dbb..58c8f6b414 100644 --- a/src/gui/kernel/qplatformnativeinterface.h +++ b/src/gui/kernel/qplatformnativeinterface.h @@ -66,6 +66,7 @@ class QBackingStore; class Q_GUI_EXPORT QPlatformNativeInterface : public QObject { Q_OBJECT + Q_MOC_INCLUDE(<qpa/qplatformwindow.h>) public: virtual void *nativeResourceForIntegration(const QByteArray &resource); virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context); diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h index 948a6c099d..bd74a2cc0a 100644 --- a/src/gui/kernel/qplatformsystemtrayicon.h +++ b/src/gui/kernel/qplatformsystemtrayicon.h @@ -57,6 +57,7 @@ class QRect; class Q_GUI_EXPORT QPlatformSystemTrayIcon : public QObject { Q_OBJECT + Q_MOC_INCLUDE(<qpa/qplatformscreen.h>) public: enum ActivationReason { Unknown, diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index b34175994d..175a34313c 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -47,6 +47,7 @@ #include <QtCore/qvariant.h> #include <QtGui/qfont.h> #include <QtCore/qurl.h> +Q_MOC_INCLUDE(<QtGui/qtextcursor.h>) QT_BEGIN_NAMESPACE diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 59010606b9..f8b45a8adc 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -75,6 +75,11 @@ struct z_stream_s; #include <private/qringbuffer_p.h> #include <private/qbytedata_p.h> +#ifndef QT_NO_NETWORKPROXY +Q_MOC_INCLUDE(<QtNetwork/QNetworkProxy>) +#endif +Q_MOC_INCLUDE(<QtNetwork/QAuthenticator>) + QT_REQUIRE_CONFIG(http); QT_BEGIN_NAMESPACE diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 4b5422ce29..b18f30c287 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -54,10 +54,11 @@ #include <QtNetwork/private/qtnetworkglobal_p.h> #include "qnetworkreplyimpl_p.h" #include "QtCore/qobject.h" +Q_MOC_INCLUDE(<QAuthenticator>) +Q_MOC_INCLUDE(<QtNetwork/QSslError>) QT_BEGIN_NAMESPACE -class QAuthenticator; class QNetworkProxy; class QNetworkProxyQuery; class QNetworkRequest; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 1c5e29f8ac..351eca43df 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1532,17 +1532,15 @@ void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &err #endif } +#ifndef QT_NO_SSL void QNetworkAccessManagerPrivate::_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator) { -#ifndef QT_NO_SSL Q_Q(QNetworkAccessManager); QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender()); if (reply) emit q->preSharedKeyAuthenticationRequired(reply, authenticator); -#else - Q_UNUSED(authenticator); -#endif } +#endif QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply) { diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 3a08c30a21..cbc9a0b660 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -49,6 +49,7 @@ #include <QtNetwork/QSslConfiguration> #include <QtNetwork/QSslPreSharedKeyAuthenticator> #endif +Q_MOC_INCLUDE(<QtNetwork/QSslError>) QT_BEGIN_NAMESPACE @@ -178,7 +179,9 @@ private: #endif Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>)) +#ifndef QT_NO_SSL Q_PRIVATE_SLOT(d_func(), void _q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)) +#endif Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) }; diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index a25adb668c..1dded7096d 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -71,6 +71,8 @@ #include <QtNetwork/QSslConfiguration> #endif +Q_MOC_INCLUDE(<QtNetwork/QAuthenticator>) + QT_REQUIRE_CONFIG(http); QT_BEGIN_NAMESPACE diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 46d25d5677..f76467b2a6 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -60,6 +60,8 @@ class QAuthenticator; class Q_NETWORK_EXPORT QAbstractSocket : public QIODevice { Q_OBJECT + Q_MOC_INCLUDE(<QtNetwork/qauthenticator.h>) + public: enum SocketType { TcpSocket, diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index 112e7032d6..3d9ce96cb3 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -83,6 +83,7 @@ public: class Q_AUTOTEST_EXPORT QAbstractSocketEngine : public QObject { Q_OBJECT + Q_MOC_INCLUDE(<QtNetwork/qauthenticator.h>) public: static QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent); diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h index d057eadf19..fe1da23409 100644 --- a/src/network/ssl/qdtls.h +++ b/src/network/ssl/qdtls.h @@ -48,6 +48,8 @@ #include <QtCore/qcryptographichash.h> #include <QtCore/qobject.h> +Q_MOC_INCLUDE(<QtNetwork/QSslPreSharedKeyAuthenticator>) + #ifndef Q_CLANG_QDOC QT_REQUIRE_CONFIG(dtls); #endif diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index 834684cd9d..6c4dabde96 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -131,7 +131,8 @@ class QDebug; Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslError &error); Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslError::SslError &error); #endif - +#else +class Q_NETWORK_EXPORT QSslError {}; // dummy class so that moc has a complete type #endif // QT_NO_SSL QT_END_NAMESPACE diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 7fd2b1cb08..238928e108 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -109,6 +109,7 @@ class QSslSocketPrivate; class Q_NETWORK_EXPORT QSslSocket : public QTcpSocket { Q_OBJECT + Q_MOC_INCLUDE(<QtNetwork/qsslpresharedkeyauthenticator.h>) public: enum SslMode { UnencryptedMode, diff --git a/src/platformsupport/linuxaccessibility/application_p.h b/src/platformsupport/linuxaccessibility/application_p.h index e980232bbf..6a8786dc07 100644 --- a/src/platformsupport/linuxaccessibility/application_p.h +++ b/src/platformsupport/linuxaccessibility/application_p.h @@ -56,6 +56,7 @@ #include <QtCore/QQueue> #include <QtDBus/QDBusConnection> #include <QtGui/QAccessibleInterface> +Q_MOC_INCLUDE(<QtDBus/QDBusMessage>) QT_REQUIRE_CONFIG(accessibility); diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h index 860c18ca05..dde3bbb98f 100644 --- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h +++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h @@ -55,6 +55,7 @@ #include <QtCore/QString> #include <QtDBus/QDBusConnection> #include <QtDBus/QDBusVariant> +Q_MOC_INCLUDE(<QtDBus/QDBusError>) QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h index f484795fbb..bbdaad1e89 100644 --- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h +++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h @@ -56,6 +56,7 @@ #include <QtDBus/QDBusVariant> #include <QtGui/qtgui-config.h> +Q_MOC_INCLUDE(<QtDBus/QDBusError>) QT_BEGIN_NAMESPACE diff --git a/src/plugins/generic/tuiotouch/qtuiohandler_p.h b/src/plugins/generic/tuiotouch/qtuiohandler_p.h index 2e444f2a0d..eb68baa915 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler_p.h +++ b/src/plugins/generic/tuiotouch/qtuiohandler_p.h @@ -59,6 +59,7 @@ class QTuioToken; class QTuioHandler : public QObject { Q_OBJECT + Q_MOC_INCLUDE("qoscmessage_p.h") public: explicit QTuioHandler(const QString &specification); diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h index b1de1b1094..29e862ecc1 100644 --- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h @@ -45,6 +45,7 @@ #include <xkbcommon/xkbcommon-compose.h> +Q_DECLARE_OPAQUE_POINTER(xkb_context *) QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcXkbCompose) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 6b97eb710b..13a4b0301b 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -524,6 +524,6 @@ void QCocoaIntegration::focusWindowChanged(QWindow *focusWindow) setApplicationIcon(focusWindow->icon()); } -#include "moc_qcocoaintegration.cpp" - QT_END_NAMESPACE + +#include "moc_qcocoaintegration.cpp" diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 70d25e345a..c30297c8ca 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -44,6 +44,9 @@ #include <qpa/qplatformnativeinterface.h> #include <QtGui/qpixmap.h> +Q_MOC_INCLUDE(<QWindow>) +Q_MOC_INCLUDE(<qpa/qplatformprintersupport.h>) +Q_MOC_INCLUDE(<QPrintEngine>) QT_BEGIN_NAMESPACE diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h index 97692c573e..90cddd7b61 100644 --- a/src/sql/models/qsqltablemodel.h +++ b/src/sql/models/qsqltablemodel.h @@ -58,6 +58,7 @@ class Q_SQL_EXPORT QSqlTableModel: public QSqlQueryModel { Q_OBJECT Q_DECLARE_PRIVATE(QSqlTableModel) + Q_MOC_INCLUDE(<QtSql/qsqlrecord.h>) public: enum EditStrategy {OnFieldChange, OnRowChange, OnManualSubmit}; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 976d49ad20..849e25b76d 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -80,9 +80,9 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING) return nullptr; } -Generator::Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile) +Generator::Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile, bool requireCompleteTypes) : out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses) - , knownGadgets(knownGadgets) + , knownGadgets(knownGadgets), requireCompleteTypes(requireCompleteTypes) { if (cdef->superclassList.size()) purestSuperClass = cdef->superclassList.constFirst().first; @@ -350,7 +350,7 @@ void Generator::generateCode() int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); - index += methodCount * 5; + index += methodCount * QMetaObjectPrivate::IntsPerMethod; if (cdef->revisionedMethods) index += methodCount; int paramsIndex = index; @@ -391,20 +391,22 @@ void Generator::generateCode() // generateClassInfos(); + int initialMetaTypeOffset = cdef->propertyList.count(); + // // Build signals array first, otherwise the signal indices would be wrong // - generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex); + generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex, initialMetaTypeOffset); // // Build slots array // - generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex); + generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex, initialMetaTypeOffset); // // Build method array // - generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex); + generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex, initialMetaTypeOffset); // // Build method version arrays @@ -438,7 +440,7 @@ void Generator::generateCode() // Build constructors array // if (isConstructible) - generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex); + generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex, initialMetaTypeOffset); // // Terminate data array @@ -553,14 +555,48 @@ void Generator::generateCode() else fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData()); - if (cdef->propertyList.isEmpty()) { + 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"); } else { - fprintf(out, "qt_metaTypeArray<\n"); + bool needsComma = false; + if (!requireCompleteTypes) { + 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, "%s%s", i == 0 ? "" : ", ", p.type.data()); + fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data()); + needsComma = true; + } + for (const QVector<FunctionDef> &methodContainer: {cdef->signalList, cdef->slotList, cdef->methodList} ) { + for (int i = 0; i< methodContainer.count(); ++i) { + const FunctionDef& fdef = methodContainer.at(i); + fprintf(out, "%s%s", needsComma ? ", " : "", fdef.type.name.data()); + needsComma = true; + for (const auto &argument: fdef.arguments) { + fprintf(out, ", %s", argument.type.name.data()); + } + } + 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) { + fprintf(out, "%s%s", needsComma ? ", " : "", argument.type.name.data()); + needsComma = true; + } } + fprintf(out, "\n"); fprintf(out, ">,\n"); } @@ -572,6 +608,7 @@ void Generator::generateCode() fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;\n}\n", cdef->qualified.constData()); + // // Generate smart cast function // @@ -688,11 +725,11 @@ void Generator::registerByteArrayVector(const QVector<QByteArray> &list) strreg(ba); } -void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int ¶msIndex) +void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int ¶msIndex, int &initialMetatypeOffset) { if (list.isEmpty()) return; - fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype); + fprintf(out, "\n // %ss: name, argc, parameters, tag, flags, initial metatype offsets\n", functype); for (int i = 0; i < list.count(); ++i) { const FunctionDef &f = list.at(i); @@ -727,10 +764,12 @@ void Generator::generateFunctions(const QVector<FunctionDef>& list, const char * } int argc = f.arguments.count(); - fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x /* %s */,\n", - stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, comment.constData()); + fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x, %4d /* %s */,\n", + stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, initialMetatypeOffset, comment.constData()); paramsIndex += 1 + argc * 2; + // constructors don't have a return type + initialMetatypeOffset += (f.isConstructor ? 0 : 1) + argc; } } diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index e92b9d1208..f3d3b40349 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -39,7 +39,7 @@ class Generator ClassDef *cdef; QVector<uint> meta_data; public: - Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr); + Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr, bool requireCompleteTypes = false); void generateCode(); private: bool registerableMetaType(const QByteArray &propertyType); @@ -47,7 +47,7 @@ private: void generateClassInfos(); void registerFunctionStrings(const QVector<FunctionDef> &list); void registerByteArrayVector(const QVector<QByteArray> &list); - void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int ¶msIndex); + void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int ¶msIndex, int &initialMetatypeOffset); void generateFunctionRevisions(const QVector<FunctionDef> &list, const char *functype); void generateFunctionParameters(const QVector<FunctionDef> &list, const char *functype); void generateTypeInfo(const QByteArray &typeName, bool allowEmptyName = false); @@ -70,6 +70,7 @@ private: QVector<QByteArray> metaTypes; QHash<QByteArray, QByteArray> knownQObjectClasses; QHash<QByteArray, QByteArray> knownGadgets; + bool requireCompleteTypes; }; QT_END_NAMESPACE diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index b8c2d7f594..61f3666b16 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -367,6 +367,10 @@ int runMoc(int argc, char **argv) depFileRuleNameOption.setValueName(QStringLiteral("rule name")); parser.addOption(depFileRuleNameOption); + QCommandLineOption requireCompleTypesOption(QStringLiteral("require-complete-types")); + requireCompleTypesOption.setDescription(QStringLiteral("Require complete types for better performance")); + parser.addOption(requireCompleTypesOption); + parser.addPositionalArgument(QStringLiteral("[header-file]"), QStringLiteral("Header file to read from, otherwise stdin.")); parser.addPositionalArgument(QStringLiteral("[@option-file]"), @@ -398,6 +402,8 @@ int runMoc(int argc, char **argv) moc.noInclude = true; autoInclude = false; } + if (parser.isSet(requireCompleTypesOption)) + moc.requireCompleteTypes = true; if (!ignoreConflictingOptions) { if (parser.isSet(forceIncludeOption)) { moc.noInclude = false; diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index f04f4c5d0d..0ffbe7bb13 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1125,7 +1125,7 @@ void Moc::generate(FILE *out, FILE *jsonOutput) fputs("", out); for (i = 0; i < classList.size(); ++i) { - Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out); + Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out, requireCompleteTypes); generator.generateCode(); } fputs("", out); diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 486d033049..84ddf47a89 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -224,13 +224,14 @@ class Moc : public Parser { public: Moc() - : noInclude(false), mustIncludeQPluginH(false) + : noInclude(false), mustIncludeQPluginH(false), requireCompleteTypes(false) {} QByteArray filename; bool noInclude; bool mustIncludeQPluginH; + bool requireCompleteTypes; QByteArray includePath; QVector<QByteArray> includeFiles; QVector<ClassDef> classList; |