diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-01-04 10:35:04 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-04-14 19:07:16 +0200 |
commit | da0f72ebb817bb9c92c7a183b281d8a4bf31a135 (patch) | |
tree | 072e6051b2464dba616634b94e1657d695a81715 /src/corelib | |
parent | ec59ae6189c2a0405cc50f548c95c7007603934f (diff) |
QEvent: start to de-inline copy ctor and clone() of all subclasses
There's no advantage to them being inline: Absent de-virtualisation,
clone() is only supposed to be called through the vtable, and the copy
ctor is only supposed to be used in the implementation of clone().
And when the compiler de-virtualises, we don't want the code
duplication associated with inlining.
Enforce this by introducing new macros to hide the boilerplate.
This fixes missing out-of-line dtors in:
- QSinglePointEvent
- QApplicationStateChangeEvent
- QFutureCallOutEvent
Wrong covariant return in:
- QFutureCallOutEvent
And missing clone() reimplementations in:
- QCloseEvent
- QIconDragEvent
- QShowEvent
- QHideEvent
- QDragEnterEvent
- QDragLeaveEvent
While these don't carry extra data or members, a dynamic_cast of the
result of clone() as well as using the expected covariant return value
would fail:
QShowEvent *e = ~~~;
QShowEvent *e2 = e->clone(); // ERROR: converting QEvent* to QShowEvent*
Check that reimplementing clone() is binary compatible (covariant
returns may change the numerical pointer value returned, cf.
https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B).
The copy-assignment operator stays inline for the time being, as the
goal is to = delete it in the future.
This patch covers, roughly, QtCore and QtGui.
[ChangeLog][QtGui][QEvent subclasses] Fixed missing clone()
reimplementations on QCloseEvent, QIconDragEvent, QShowEvent,
QHideEvent, QDragEnterEvent, and QDragLeaveEvent.
Task-number: QTBUG-45582
Task-number: QTBUG-97601
Change-Id: Ib8a0519dbe85a7a8da61050d48be338004dfa69a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qcoreevent.cpp | 27 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreevent.h | 44 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface_p.h | 9 |
4 files changed, 36 insertions, 46 deletions
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 34b57bb4f8..2289938d4b 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -559,12 +559,7 @@ QTimerEvent::QTimerEvent(int timerId) : QEvent(Timer), id(timerId) {} -/*! - \internal -*/ -QTimerEvent::~QTimerEvent() -{ -} +Q_IMPL_EVENT_COMMON(QTimerEvent) /*! \fn int QTimerEvent::timerId() const @@ -606,12 +601,7 @@ QChildEvent::QChildEvent(Type type, QObject *child) : QEvent(type), c(child) {} -/*! - \internal -*/ -QChildEvent::~QChildEvent() -{ -} +Q_IMPL_EVENT_COMMON(QChildEvent) /*! \fn QObject *QChildEvent::child() const @@ -663,12 +653,7 @@ QDynamicPropertyChangeEvent::QDynamicPropertyChangeEvent(const QByteArray &name) { } -/*! - \internal -*/ -QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent() -{ -} +Q_IMPL_EVENT_COMMON(QDynamicPropertyChangeEvent) /*! \fn QByteArray QDynamicPropertyChangeEvent::propertyName() const @@ -687,11 +672,7 @@ QDeferredDeleteEvent::QDeferredDeleteEvent() , level(0) { } -/*! - \internal -*/ -QDeferredDeleteEvent::~QDeferredDeleteEvent() -{ } +Q_IMPL_EVENT_COMMON(QDeferredDeleteEvent) /*! \fn int QDeferredDeleteEvent::loopLevel() const diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 4a4910e893..f737a55514 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -53,6 +53,29 @@ protected: \ Class &operator=(const Class &other) = default; \ Class &operator=(Class &&) = delete +#define Q_DECL_EVENT_COMMON(Class) \ + protected: \ + Class(const Class &); \ + Class(Class &&) = delete; \ + Class &operator=(const Class &other) = default; \ + Class &operator=(Class &&) = delete; \ + public: \ + Class* clone() const override; \ + ~Class() override; \ + private: + +#define Q_IMPL_EVENT_COMMON(Class) \ + Class::Class(const Class &) = default; \ + Class::~Class() = default; \ + Class* Class::clone() const \ + { \ + auto c = new Class(*this); \ + QEvent *e = c; \ + /* check that covariant return is safe to add */ \ + Q_ASSERT(reinterpret_cast<quintptr>(c) == reinterpret_cast<quintptr>(e)); \ + return c; \ + } + class QEventPrivate; class Q_CORE_EXPORT QEvent // event base class { @@ -367,14 +390,11 @@ private: class Q_CORE_EXPORT QTimerEvent : public QEvent { - Q_EVENT_DISABLE_COPY(QTimerEvent); + Q_DECL_EVENT_COMMON(QTimerEvent) public: explicit QTimerEvent(int timerId); - ~QTimerEvent(); int timerId() const { return id; } - QTimerEvent *clone() const override { return new QTimerEvent(*this); } - protected: int id; }; @@ -383,46 +403,38 @@ class QObject; class Q_CORE_EXPORT QChildEvent : public QEvent { - Q_EVENT_DISABLE_COPY(QChildEvent); + Q_DECL_EVENT_COMMON(QChildEvent) public: QChildEvent(Type type, QObject *child); - ~QChildEvent(); + QObject *child() const { return c; } bool added() const { return type() == ChildAdded; } bool polished() const { return type() == ChildPolished; } bool removed() const { return type() == ChildRemoved; } - QChildEvent *clone() const override { return new QChildEvent(*this); } - protected: QObject *c; }; class Q_CORE_EXPORT QDynamicPropertyChangeEvent : public QEvent { - Q_EVENT_DISABLE_COPY(QDynamicPropertyChangeEvent); + Q_DECL_EVENT_COMMON(QDynamicPropertyChangeEvent) public: explicit QDynamicPropertyChangeEvent(const QByteArray &name); - ~QDynamicPropertyChangeEvent(); inline QByteArray propertyName() const { return n; } - QDynamicPropertyChangeEvent *clone() const override { return new QDynamicPropertyChangeEvent(*this); } - private: QByteArray n; }; class Q_CORE_EXPORT QDeferredDeleteEvent : public QEvent { - Q_EVENT_DISABLE_COPY(QDeferredDeleteEvent); + Q_DECL_EVENT_COMMON(QDeferredDeleteEvent) public: explicit QDeferredDeleteEvent(); - ~QDeferredDeleteEvent(); int loopLevel() const { return level; } - QDeferredDeleteEvent *clone() const override { return new QDeferredDeleteEvent(*this); } - private: int level; friend class QCoreApplication; diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 0fde190bc0..71d6670538 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -74,6 +74,8 @@ const auto suspendingOrSuspended = QFutureCallOutInterface::~QFutureCallOutInterface() = default; +Q_IMPL_EVENT_COMMON(QFutureCallOutEvent) + QFutureInterfaceBase::QFutureInterfaceBase(State initialState) : d(new QFutureInterfaceBasePrivate(initialState)) { } diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h index 24902cbc9a..c6ea30b07f 100644 --- a/src/corelib/thread/qfutureinterface_p.h +++ b/src/corelib/thread/qfutureinterface_p.h @@ -65,9 +65,9 @@ QT_REQUIRE_CONFIG(future); QT_BEGIN_NAMESPACE -class QFutureCallOutEvent : public QEvent +class Q_CORE_EXPORT QFutureCallOutEvent : public QEvent { - Q_EVENT_DISABLE_COPY(QFutureCallOutEvent); + Q_DECL_EVENT_COMMON(QFutureCallOutEvent) public: enum CallOutType { Started, @@ -104,11 +104,6 @@ public: int index2; QString text; - QEvent *clone() const override - { - return new QFutureCallOutEvent(callOutType, index1, index2, text); - } - private: QFutureCallOutEvent(CallOutType callOutType, int index1, |