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
commitac23f4036527ed860b8fb5e9362b40be32128088 (patch)
treea0cb6cc02e6fff88953b30d89c2f4418791c83bb
parentcef48c0d723a804ecd1daf308681c9872a050190 (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