summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetaobject.cpp80
-rw-r--r--src/corelib/kernel/qmetaobject.h2
-rw-r--r--src/corelib/kernel/qmetaobject_p.h4
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp43
-rw-r--r--src/corelib/kernel/qmetatype.h34
-rw-r--r--src/corelib/kernel/qobject.cpp4
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 &parameterType: method.parameterTypes()) {
+ QMetaType mt(QMetaType::type(parameterType));
+ *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
+ types++;
+ }
+ }
+ for (const auto &constructor: d->constructors) {
+ for (const auto &parameterType: 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;