From 33a2bd9ca9ee3dc05e5f7cb48aa8f1d55f5368b2 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 19 May 2021 13:04:39 +0200 Subject: [PATCH] Q_DECLARE_METATYPE: Do not re-register types When Q_DECLARE_METATYPE is used, we often end up re-registering types as typedefs of themselves. This is because with Q_DECLARE_METATYPE, we set a legacy register operation which calls (after some indirection) QMetaType::registerNormalizedType. We still need to support this to preserve compatibility in the presence of typedefs and namespaced types. However, there is no reason to do the wasteful work of normalizing the typename at runtime and adding memory overhead to have a type registered as a typedef of itself. We can skip the type normalization work by checking whether the name in the metatype interface equals that of the typename. We still need to make sure that the converter and view functions are registered, though. Moreover, we can fix the check in qRegisterNormalizedMetaType to only call registerNormalizedTypedef if the new name doesn't match the name stored in the metatype. Fixes: QTBUG-93841 Change-Id: Icfe42c349b23add630fe3c761362b60e9e9aaa2b Reviewed-by: Ulf Hermann Reviewed-by: Qt CI Bot Reviewed-by: Andrei Golubev Reviewed-by: Lars Knoll --- src/corelib/kernel/qmetatype.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 1d039b6f18a..30f31f54f60 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1209,14 +1209,15 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz const QMetaType metaType = QMetaType::fromType(); const int id = metaType.id(); - if (id > 0) { + QtPrivate::SequentialContainerTransformationHelper::registerConverter(); + QtPrivate::SequentialContainerTransformationHelper::registerMutableView(); + QtPrivate::AssociativeContainerTransformationHelper::registerConverter(); + QtPrivate::AssociativeContainerTransformationHelper::registerMutableView(); + QtPrivate::MetaTypePairHelper::registerConverter(); + QtPrivate::MetaTypeSmartPointerHelper::registerConverter(); + + if (normalizedTypeName != metaType.name()) { QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType); - QtPrivate::SequentialContainerTransformationHelper::registerConverter(); - QtPrivate::SequentialContainerTransformationHelper::registerMutableView(); - QtPrivate::AssociativeContainerTransformationHelper::registerConverter(); - QtPrivate::AssociativeContainerTransformationHelper::registerMutableView(); - QtPrivate::MetaTypePairHelper::registerConverter(); - QtPrivate::MetaTypeSmartPointerHelper::registerConverter(); } return id; @@ -1348,6 +1349,12 @@ struct QMetaTypeIdQObject } QT_END_NAMESPACE \ /**/ +template +int qRegisterMetatypeIndirection() +{ + return qRegisterNormalizedMetaType(QMetaType::fromType().name()); +} + #ifndef Q_MOC_RUN #define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE) #define Q_DECLARE_METATYPE_IMPL(TYPE) \ @@ -1361,6 +1368,12 @@ struct QMetaTypeIdQObject static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ if (const int id = metatype_id.loadAcquire()) \ return id; \ + const auto mt = QMetaType::fromType(); \ + if (QByteArrayView(mt.name()) == (#TYPE)) { \ + qRegisterMetatypeIndirection(); \ + metatype_id.storeRelease(mt.id()); \ + return mt.id(); \ + } \ const int newId = qRegisterMetaType< TYPE >(#TYPE); \ metatype_id.storeRelease(newId); \ return newId; \