aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-02-28 15:59:48 -0800
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-03-01 23:06:03 +0000
commitb8b828d5653636df36bdfb7313ec12f142fafd87 (patch)
tree41ad3fa39a9248e5a3430cdab9f50428a03fa846
parentf6d5dd093a33f8af71387129f5cd475825295c88 (diff)
Work around GCC 13 bogus warning about use-after-free
By simply adding std::move() to the variables we've received by value and aren't using again, thereby also improving performance slightly. The message was: In static member function ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’, inlined from ‘void QSharedPointer<T>::deref() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:440:12, inlined from ‘QSharedPointer<T>::~QSharedPointer() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:280:30, inlined from ‘QDeferredSharedPointer<const QQmlJSScope>::~QDeferredSharedPointer()’ at qdeferredpointer_p.h:45:7, inlined from ‘QString QmltcCodeGenerator::generate_typeCount(Predicate, const InlineComponentOrDocumentRootName&) const cc1plus: error: pointer may be used after ‘void operator delete(void*)’ [-Werror=use-after-free] In static member function ‘static void QtSharedPointer::ExternalRefCountData::operator delete(void*)’, inlined from ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:448:13, inlined from ‘static void QSharedPointer<T>::deref(Data*) [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:441:17, inlined from ‘void QSharedPointer<T>::deref() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:440:12, inlined from ‘QSharedPointer<T>::~QSharedPointer() [with T = const QQmlJSScope]’ at qsharedpointer_impl.h:280:30, inlined from ‘QDeferredSharedPointer<T>::operator QDeferredSharedPointer<const T>() const [with T = QQmlJSScope]’ at qdeferredpointer_p.h:75:83, inlined from ‘QString QmltcCodeGenerator::generate_typeCount(Predicate, const InlineComponentOrDocumentRootName&) const qsharedpointer_impl.h:130:67: note: call to ‘void operator delete(void*)’ here For reference: static void deref(Data *dd) noexcept { if (!dd) return; if (!dd->strongref.deref()) { dd->destroy(); } if (!dd->weakref.deref()) delete dd; } Note how there's one extra frame in the deletion sequence (QDeferredSharedPointer<T>::operator QDeferredSharedPointer<const T>()) compared to the use. The common source is if (t == visitor->result()) { // t is this document's root The variable `t` is a QDeferredSharedPointer<const QQmlJSScope>, but the right side is only QDeferredSharedPointer<QQmlJSScope>, which is why the conversion operator was called. operator QDeferredSharedPointer<const T>() const { return { m_data, m_factory }; } The above is calling the constructor QDeferredSharedPointer(QSharedPointer<T> data, QSharedPointer<Factory> factory) for T = const QQmlJSScope, which means it's calling template <class X, IfCompatible<X> = true> QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d) to construct the const version from m_data. This temporary is then moved into the QDeferredSharedPointer's argument because it's a prvalue by way of QSharedPointer's move constructor QSharedPointer(QSharedPointer &&other) noexcept : value(other.value), d(other.d) { other.d = nullptr; other.value = nullptr; } After the QDeferredSharedPointer's constructor returns, the temporary QSharedPointer is destroyed, which is where the compiler saw the call to operator delete. Except that it can't happen. The move constructor will have set the temporary's d pointer to null, so when deref() is called on that temporary, the check will match: if (!dd) return; Change-Id: I7f354474adce419ca6c2fffd17482074d5cdc9d5 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io> (cherry picked from commit fa7c03f92ea922ac20617c9e8b6da83d8c6665b6) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qmlcompiler/qdeferredpointer_p.h6
1 files changed, 3 insertions, 3 deletions
diff --git a/src/qmlcompiler/qdeferredpointer_p.h b/src/qmlcompiler/qdeferredpointer_p.h
index 481c0e27ae..f4d8696f69 100644
--- a/src/qmlcompiler/qdeferredpointer_p.h
+++ b/src/qmlcompiler/qdeferredpointer_p.h
@@ -50,15 +50,15 @@ public:
QDeferredSharedPointer() = default;
QDeferredSharedPointer(QSharedPointer<T> data)
- : m_data(data)
+ : m_data(std::move(data))
{}
QDeferredSharedPointer(QWeakPointer<T> data)
- : m_data(data)
+ : m_data(std::move(data))
{}
QDeferredSharedPointer(QSharedPointer<T> data, QSharedPointer<Factory> factory)
- : m_data(data), m_factory(factory)
+ : m_data(std::move(data)), m_factory(std::move(factory))
{
// You have to provide a valid pointer if you provide a factory. We cannot allocate the
// pointer for you because then two copies of the same QDeferredSharedPointer will diverge