From 866d63f659edbcf96e08a791a70f4668e9c54ea3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 15 Jul 2022 22:31:56 -0700 Subject: [PATCH] QMetaType: fix QMetaTypes for non-const references Namely, they shouldn't be supported. Even trying to create such a type (as in QMetaType::fromType()) should fail, because for the purposes of the meta type, they are not the same. However, they were being registered in the meta objects' meta type list as a mistake since commit cb43aaca112c864a201b87037692cb8ae2e93b6d ("Introduce QMetaObject::metaType"), including for output parameters in D-Bus remote objects' meta objects. despite the comment saying "type id not available". [ChangeLog][Potentially Source-incompatible Changes] Made meta types for non-const references fail to compile. Previously, QMetaType::fromType allowed this to compile, but returned the meta type for the base type, which was incorrect. Const references are understood to be the same as the base type. [ChangeLog][Important Behavior Changes] The meta type for non-const reference parameters in extracted methods (signals, slots, etc.) is no longer available in QMetaMethod. This used to be the case in Qt 4.x and 5.x, but due to a mistake in Qt 6.0-6.3, QMetaMethod would incorrectly report the base (non-reference) type. Additionally, both the reference and the non-reference types may have been reported in different APIs. Change-Id: I36b24183fbd041179f2ffffd1702384d2b64a5f9 Reviewed-by: Volker Hilsheimer Reviewed-by: Qt CI Bot (cherry picked from commit 2d0c31e7d92a3e9df4ce2b9c1d41b94fb12735fc) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qmetatype.h | 28 +++++++++++++++++++--------- src/dbus/qdbusmetaobject.cpp | 2 +- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 32ddd7229c8..cdad83a4670 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -799,7 +799,11 @@ namespace QtPrivate } // namespace detail template - struct is_complete : detail::is_complete_helper::type {}; + struct is_complete : detail::is_complete_helper, ODR_VIOLATION_PREVENTER>::type {}; + + template struct MetatypeDecay { using type = T; }; + template struct MetatypeDecay { using type = T; }; + template struct MetatypeDecay { using type = T; }; template struct IsPointerToTypeDerivedFromQObject @@ -2409,12 +2413,6 @@ QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) #undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER #endif -template -constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType() -{ - using Ty = std::remove_cv_t>; - return &QMetaTypeInterfaceWrapper::metaType; -} template struct qRemovePointerLike @@ -2441,14 +2439,26 @@ struct TypeAndForceComplete using ForceComplete = ForceComplete_; }; +template +constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType() +{ + using Ty = typename MetatypeDecay::type; + return &QMetaTypeInterfaceWrapper::metaType; +} + template constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType() { using T = typename TypeCompletePair::type; using ForceComplete = typename TypeCompletePair::ForceComplete; - using Ty = std::remove_cv_t>; + using Ty = typename MetatypeDecay::type; using Tz = qRemovePointerLike_t; - if constexpr (!is_complete::value && !ForceComplete::value) { + + if constexpr (ForceComplete::value) { + return &QMetaTypeInterfaceWrapper::metaType; + } else if constexpr (std::is_reference_v) { + return nullptr; + } else if constexpr (!is_complete::value) { return nullptr; } else { return &QMetaTypeInterfaceWrapper::metaType; diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 79372484fb3..54c9389862b 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -477,8 +477,8 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) // Output parameters are references; type id not available typeName = QMetaType(type).name(); typeName.append('&'); + type = QMetaType::UnknownType; } - Q_ASSERT(type != QMetaType::UnknownType); int typeInfo; if (!typeName.isEmpty()) typeInfo = IsUnresolvedType | strings.enter(typeName);