diff options
author | Marc Mutz <marc.mutz@qt.io> | 2023-06-23 17:11:35 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-06-25 15:28:23 +0000 |
commit | 3f2183ce2c41c5a998fcc1f83ca5ad4adc82b795 (patch) | |
tree | 68d4c39bf3dab05ffc221aeb9c16030d9521dfe0 /src/qml/qml/ftw | |
parent | f8c9fd6bfa5e6de4ac5d0176ebbc0292dbd031a2 (diff) |
QQmlRefCount: de-virtualize dtor
Now that QQmlRefCounted ensures no-one uses ~QQmlRefCount() directly
anymore, we can make it non-virtual, shrinking the
sizeof(QQmlRefCount) from 8/16 to 4/4 bytes (32/64 bit platforms).
This requires moving the release() function from QQmlRefCount down
into QQmlRefCounted<T>, and static_cast'ing *this to T before calling
delete.
We need to be careful, of course, that no derived class relied on the
implied virtualness of ~QQmlRefCount() making their dtors virtual, so
require that all classes that use QQmlRefCounted are either final or
have a virtual destructor.
Update the toolsupport test and the TypeInformationVersion, as
sizeof(QQmlRefCount) was one the items checked.
Fixes: QTBUG-114817
Change-Id: I69afd36ec5b63313842c1438e0244503603ed96f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml/ftw')
-rw-r--r-- | src/qml/qml/ftw/qqmlrefcount_p.h | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h index 2914e6279c..8cd1cbdaf1 100644 --- a/src/qml/qml/ftw/qqmlrefcount_p.h +++ b/src/qml/qml/ftw/qqmlrefcount_p.h @@ -30,11 +30,10 @@ class Q_QML_PRIVATE_EXPORT QQmlRefCount public: inline QQmlRefCount(); inline void addref() const; - inline void release() const; inline int count() const; private: - inline virtual ~QQmlRefCount(); + inline ~QQmlRefCount(); template <typename T> friend class QQmlRefCounted; private: @@ -44,8 +43,10 @@ private: template <typename T> class QQmlRefCounted : public QQmlRefCount { +public: + inline void release() const; protected: - ~QQmlRefCounted() = default; + inline ~QQmlRefCounted(); }; template<class T> @@ -130,11 +131,22 @@ void QQmlRefCount::addref() const refCount.ref(); } -void QQmlRefCount::release() const +template <typename T> +void QQmlRefCounted<T>::release() const { + static_assert(std::is_base_of_v<QQmlRefCounted, T>, + "QQmlRefCounted<T> must be a base of T (CRTP)"); Q_ASSERT(refCount.loadRelaxed() > 0); if (!refCount.deref()) - delete this; + delete static_cast<const T *>(this); +} + +template <typename T> +QQmlRefCounted<T>::~QQmlRefCounted() +{ + static_assert(std::is_final_v<T> || std::has_virtual_destructor_v<T>, + "T must either be marked final or have a virtual dtor, " + "lest release() runs into UB."); } int QQmlRefCount::count() const |