aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/ftw
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-06-23 17:11:35 +0200
committerMarc Mutz <marc.mutz@qt.io>2023-06-25 15:28:23 +0000
commit3f2183ce2c41c5a998fcc1f83ca5ad4adc82b795 (patch)
tree68d4c39bf3dab05ffc221aeb9c16030d9521dfe0 /src/qml/qml/ftw
parentf8c9fd6bfa5e6de4ac5d0176ebbc0292dbd031a2 (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.h22
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