diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7c238af700..064a323507 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2850,6 +2850,13 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, Q_ASSERT(slotObj); + // Used as the signalID in the metacall event and only used to + // verify that we are not processing an unrelated event, not to + // emit the right signal. So using a value that can never clash + // with any signal index. Clang doesn't like this to be a static + // member of the PermissionReceiver. + static constexpr ushort PermissionReceivedID = 0xffff; + // If we have a context object, then we dispatch the permission response // asynchronously through a received object that lives in the same thread // as the context object. Otherwise we call the functor synchronously when @@ -2860,11 +2867,12 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, PermissionReceiver(QtPrivate::QSlotObjectBase *slotObject, const QObject *context) : slotObject(slotObject), context(context) {} + protected: bool event(QEvent *event) override { if (event->type() == QEvent::MetaCall) { auto metaCallEvent = static_cast(event); - if (metaCallEvent->id() == ushort(-1)) { + if (metaCallEvent->id() == PermissionReceivedID) { Q_ASSERT(slotObject); // only execute if context object is still alive if (context) @@ -2898,18 +2906,8 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, permission.m_status = status; if (receiver) { - const int nargs = 2; - auto metaCallEvent = new QMetaCallEvent(slotObj, qApp, ushort(-1), nargs); - Q_CHECK_PTR(metaCallEvent); - void **args = metaCallEvent->args(); - QMetaType *types = metaCallEvent->types(); - const auto voidType = QMetaType::fromType(); - const auto permissionType = QMetaType::fromType(); - types[0] = voidType; - types[1] = permissionType; - args[0] = nullptr; - args[1] = permissionType.create(&permission); - Q_CHECK_PTR(args[1]); + auto metaCallEvent = QMetaCallEvent::create(slotObj, qApp, + PermissionReceivedID, permission); qApp->postEvent(receiver, metaCallEvent); } else { void *argv[] = { nullptr, &permission }; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f9bb93f960..d56e9aa60c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -402,6 +402,26 @@ public: ~QMetaCallEvent() override; + template + static QMetaCallEvent *create(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, + int signal_index, Args ...argv) + { + auto metaCallEvent = std::make_unique(slotObj, sender, + signal_index, int(1 + sizeof...(Args))); + + void **args = metaCallEvent->args(); + QMetaType *types = metaCallEvent->types(); + const std::array argp{ nullptr, std::addressof(argv)... }; + const std::array metaTypes{ QMetaType::fromType(), QMetaType::fromType()... }; + for (size_t i = 0; i < sizeof...(Args) + 1; ++i) { + types[i] = metaTypes[i]; + args[i] = types[i].create(argp[i]); + Q_CHECK_PTR(!i || args[i]); + } + + return metaCallEvent.release(); + } + inline int id() const { return d.method_offset_ + d.method_relative_; } inline const void * const* args() const { return d.args_; } inline void ** args() { return d.args_; } diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 2283766b97..1631e97652 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -107,18 +107,8 @@ void QHostInfoResult::postResultsReady(const QHostInfo &info) auto result = new QHostInfoResult(this); Q_CHECK_PTR(result); - const int nargs = 2; - auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs); + auto metaCallEvent = QMetaCallEvent::create(slotObj, nullptr, signal_index, info); Q_CHECK_PTR(metaCallEvent); - void **args = metaCallEvent->args(); - QMetaType *types = metaCallEvent->types(); - auto voidType = QMetaType::fromType(); - auto hostInfoType = QMetaType::fromType(); - types[0] = voidType; - types[1] = hostInfoType; - args[0] = nullptr; - args[1] = hostInfoType.create(&info); - Q_CHECK_PTR(args[1]); qApp->postEvent(result, metaCallEvent); }