diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 80 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobjectbuilder.cpp | 43 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 34 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 4 |
6 files changed, 129 insertions, 38 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; |