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 <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Fabian Kosmale 2021-05-19 13:04:39 +02:00
parent bf0b2b24a7
commit 33a2bd9ca9

View File

@ -1209,14 +1209,15 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
const QMetaType metaType = QMetaType::fromType<T>();
const int id = metaType.id();
if (id > 0) {
QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
QtPrivate::MetaTypePairHelper<T>::registerConverter();
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
if (normalizedTypeName != metaType.name()) {
QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
}
return id;
@ -1348,6 +1349,12 @@ struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
} QT_END_NAMESPACE \
/**/
template <typename T>
int qRegisterMetatypeIndirection()
{
return qRegisterNormalizedMetaType<T>(QMetaType::fromType<T>().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<T, QMetaType::IsEnumeration>
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
const auto mt = QMetaType::fromType<TYPE>(); \
if (QByteArrayView(mt.name()) == (#TYPE)) { \
qRegisterMetatypeIndirection<TYPE>(); \
metatype_id.storeRelease(mt.id()); \
return mt.id(); \
} \
const int newId = qRegisterMetaType< TYPE >(#TYPE); \
metatype_id.storeRelease(newId); \
return newId; \