summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-01-04 10:35:04 +0100
committerMarc Mutz <marc.mutz@qt.io>2022-04-14 19:07:16 +0200
commitda0f72ebb817bb9c92c7a183b281d8a4bf31a135 (patch)
tree072e6051b2464dba616634b94e1657d695a81715 /src/corelib
parentec59ae6189c2a0405cc50f548c95c7007603934f (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.cpp27
-rw-r--r--src/corelib/kernel/qcoreevent.h44
-rw-r--r--src/corelib/thread/qfutureinterface.cpp2
-rw-r--r--src/corelib/thread/qfutureinterface_p.h9
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,