summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-07-15 14:02:03 -0700
committerThiago Macieira <thiago.macieira@intel.com>2022-07-28 11:50:17 -0700
commitb73ab954dffffc462b6f6efe5a2dd97efeab0038 (patch)
tree95139a007a1090facccc473fb2c9097d0203ac8e /src/corelib
parent0f76e55bc440a70f5d9530a192c9ce6334a8f069 (diff)
QMetaObject: rewrite newInstance()
Like in the previous commit, use QMetaMethodPrivate::invokeImpl() to avoid having to reconstruct the method signature. Change-Id: I36b24183fbd041179f2ffffd17021c7a0bfa48c0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/kernel/qmetaobject.cpp95
1 files changed, 57 insertions, 38 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index afcdebc4ec..07f3e88870 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -185,6 +185,7 @@ public:
inline QList<QByteArray> parameterNames() const;
inline QByteArray tag() const;
inline int ownMethodIndex() const;
+ inline int ownConstructorIndex() const;
// shadows the public function
enum class InvokeFailReason : int {
@@ -194,6 +195,8 @@ public:
DeadLockDetected = -2,
CallViaVirtualFailed = -3, // no warning
ConstructorCallOnObject = -4,
+ ConstructorCallWithoutResult = -5,
+ ConstructorCallFailed = -6, // no warning
CouldNotQueueParameter = -0x1000,
@@ -213,6 +216,8 @@ private:
QMetaMethodPrivate();
};
+enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
+
/*!
\since 4.5
@@ -243,48 +248,42 @@ QObject *QMetaObject::newInstance(QGenericArgument val0,
return nullptr;
}
- QByteArray constructorName = className();
- {
- int idx = constructorName.lastIndexOf(':');
- if (idx != -1)
- constructorName.remove(0, idx+1); // remove qualified part
- }
- QVarLengthArray<char, 512> sig;
- sig.append(constructorName.constData(), constructorName.length());
- sig.append('(');
+ QObject *returnValue = nullptr;
+ QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
- enum { MaximumParamCount = 10 };
- const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
- val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
+ const char *typeNames[] = {
+ returnValueMetaType.name(),
+ val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
+ val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
+ };
+ const void *parameters[] = {
+ &returnValue,
+ val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
+ val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
+ };
int paramCount;
- for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
int len = int(qstrlen(typeNames[paramCount]));
if (len <= 0)
break;
- sig.append(typeNames[paramCount], len);
- sig.append(',');
}
- if (paramCount == 0)
- sig.append(')'); // no parameters
- else
- sig[sig.size() - 1] = ')';
- sig.append('\0');
- int idx = indexOfConstructor(sig.constData());
- if (idx < 0) {
- QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
- idx = indexOfConstructor(norm.constData());
- }
- if (idx < 0)
- return nullptr;
+ // find the constructor
+ auto priv = QMetaObjectPrivate::get(this);
+ for (int i = 0; i < priv->constructorCount; ++i) {
+ QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(this, i);
- QObject *returnValue = nullptr;
- void *param[] = {&returnValue, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
- val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
+ // attempt to call
+ QMetaMethodPrivate::InvokeFailReason r =
+ QMetaMethodPrivate::invokeImpl(m, nullptr, Qt::DirectConnection, paramCount,
+ parameters, typeNames);
+ if (r == QMetaMethodPrivate::InvokeFailReason::None)
+ return returnValue;
+ if (int(r) < 0)
+ return nullptr;
+ }
- if (static_metacall(CreateInstance, idx, param) >= 0)
- return nullptr;
return returnValue;
}
@@ -1341,8 +1340,6 @@ QByteArray QMetaObject::normalizedSignature(const char *method)
return result;
}
-enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
-
/*
Returns the signatures of all methods whose name matches \a nonExistentMember,
or an empty QByteArray if there are no matches.
@@ -1877,10 +1874,18 @@ QByteArray QMetaMethodPrivate::tag() const
int QMetaMethodPrivate::ownMethodIndex() const
{
- // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
+ Q_ASSERT(methodType() != Constructor);
return ( data.d - mobj->d.data - priv(mobj->d.data)->methodData)/Data::Size;
}
+int QMetaMethodPrivate::ownConstructorIndex() const
+{
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
+ Q_ASSERT(methodType() == Constructor);
+ return ( data.d - mobj->d.data - priv(mobj->d.data)->constructorData)/Data::Size;
+}
+
/*!
\since 5.0
@@ -2410,14 +2415,28 @@ auto QMetaMethodPrivate::invokeImpl(QMetaMethod self, void *target,
return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
}
- // regular type - check return type
- if (parameters[0]) {
- if (self.methodType() == Constructor) {
+ // handle constructors first
+ if (self.methodType() == Constructor) {
+ if (object) {
qWarning("QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
self.methodSignature().constData(), object);
return InvokeFailReason::ConstructorCallOnObject;
}
+ if (!parameters[0]) {
+ qWarning("QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
+ self.methodSignature().constData());
+ return InvokeFailReason::ConstructorCallWithoutResult;
+ }
+
+ int idx = priv->ownConstructorIndex();
+ if (priv->mobj->static_metacall(QMetaObject::CreateInstance, idx, param) >= 0)
+ return InvokeFailReason::ConstructorCallFailed;
+ return {};
+ }
+
+ // regular type - check return type
+ if (parameters[0]) {
if (!checkTypesAreCompatible(0)) {
qWarning("QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
" cannot convert from %s to %s during invocation",