Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138246

Q{Shared,Weak}Pointer::IfCompatible cause accidental copy/move SMFs, causing FTBFS in qtdeclarative

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.13.2, 5.15.19, 6.10.0 Beta1

    Description

      (git blame fingers 014d7ac65417ed9b5ffb85cca24d16564ff5005a (https://codereview.qt-project.org/c/qt/qtbase/+/272844))

      The IfCompatible constraints do not exclude X == T, which is fine for the (X*) ctor, but causes the QSharedPointer<X> && and const QSharedPointer<X>& to be move/copy ctors; ditto assignment operators, ditto QWeakPointer.

      The problem is that some of these have additional constrains, e.g. QWeakPointer(QWeakPointer<X> &&), which also checks IfNotVirtualBase<X>, and that fails to compile when qxp::is_virtual_base is actually std::is_virtual_base, which requires X to be a complete type:

      In file included from /d/gcc/15/include/c++/15.1.1/bits/stl_pair.h:60,
                       from /d/gcc/15/include/c++/15.1.1/utility:71,
                       from /home/marc/Qt/qt5/qtbase/src/corelib/global/qcompilerdetection.h:879,
                       from /home/marc/Qt/qt5-build-2/qtbase/include/QtCore/qcompilerdetection.h:1,
                       from /home/marc/Qt/qt5-build-2/qtbase/include/QtQmlCompiler/qtqmlcompilerexports.h:7,
                       from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljslogger_p.h:18,
                       from /home/marc/Qt/qt5-build-2/qtbase/include/QtQmlCompiler/6.11.0/QtQmlCompiler/private/qqmljslogger_p.h:1,
                       from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljscompilepass_p.h:18,
                       from /home/marc/Qt/qt5-build-2/qtbase/include/QtQmlCompiler/6.11.0/QtQmlCompiler/private/qqmljscompilepass_p.h:1,
                       from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljsoptimizations_p.h:17,
                       from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljsoptimizations.cpp:4:
      /d/gcc/15/include/c++/15.1.1/type_traits: In instantiation of ‘constexpr const bool std::is_virtual_base_of_v<const QQmlJSScope, const QQmlJSScope>’:
      /home/marc/Qt/qt5/qtbase/src/corelib/tools/qsharedpointer_impl.h:601:54:   required by substitution of ‘template<class X, typename std::enable_if<std::is_convertible<_Up*, const QQmlJSScope*>::value, bool>::type <anonymous>, typename std::enable_if<(! is_virtual_base_of_v<const QQmlJSScope, X>), bool>::type <anonymous> > QWeakPointer<const QQmlJSScope>::QWeakPointer(QWeakPointer<T>&&) [with X = const QQmlJSScope; typename std::enable_if<std::is_convertible<_Up*, const QQmlJSScope*>::value, bool>::type <anonymous> = <missing>; typename std::enable_if<(! is_virtual_base_of_v<const QQmlJSScope, X>), bool>::type <anonymous> = <missing>]’
        601 |     using IfNotVirtualBase = typename std::enable_if<!qxp::is_virtual_base_of_v<T, X>, bool>::type;
            |                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljsmetatypes_p.h:145:11:   required from here
        145 |           m_type(type),
            |           ^~~~~~~~~~~~
      /d/gcc/15/include/c++/15.1.1/type_traits:3697:48: error: invalid use of incomplete type ‘const class QQmlJSScope’
       3697 |   inline constexpr bool is_virtual_base_of_v = __builtin_is_virtual_base_of(_Base, _Derived);
            |                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      In file included from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljsloggingutils_p.h:21,
                       from /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljslogger_p.h:21:
      /home/marc/Qt/qt5/qtdeclarative/src/qmlcompiler/qqmljsloggingutils.h:13:7: note: forward declaration of ‘class QQmlJSScope’
         13 | class QQmlJSScope;
            |       ^~~~~~~~~~~
      

      There are several layers of fixes here:

      • our impl of qxp::is_virtual_base should mandate that the arguments are complete types if C++26 std::is_virtual_base_of does
      • QSharedPointer and QWeakPointer should not be making accidental copy and move SMFs
      • also, there seems to be something fishy with the overload set, since QWeakPointer(QWeakPointer<X>&&) makes a distinction between virtual and non-virtual bases, but QWeakPointer(const QWeakPointer<X> &) does not, and neither do the assignment operators.

      Attachments

        For Gerrit Dashboard: QTBUG-138246
        # Subject Branch Project Status CR V

        Activity

          People

            thiago Thiago Macieira
            mmutz Marc Mutz
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There is 1 open Gerrit change