summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetaobject.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-03-19 10:47:29 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2020-06-02 22:42:15 +0200
commitfa987d44417528856d5e80ed7b48ba99e19fa307 (patch)
tree50cd74c1a9dd3c2197f7de2ac0d431a5b16b0a42 /src/corelib/kernel/qmetaobject.cpp
parent5306fdabc1ceb09875f791526553b3665017f7ce (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/corelib/kernel/qmetaobject.cpp')
-rw-r--r--src/corelib/kernel/qmetaobject.cpp80
1 files changed, 55 insertions, 25 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;