From fa987d44417528856d5e80ed7b48ba99e19fa307 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 19 Mar 2020 10:47:29 +0100 Subject: 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 --- src/corelib/kernel/qmetaobject.cpp | 80 ++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 25 deletions(-) (limited to 'src/corelib/kernel/qmetaobject.cpp') 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; -- cgit v1.2.3