summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJędrzej Nowacki <jedrzej.nowacki@qt.io>2019-06-13 12:37:26 +0200
committerLars Knoll <lars.knoll@qt.io>2019-10-30 11:52:53 +0100
commitb76f66272692f39aaaaec7c398702f1585badf45 (patch)
tree65c45044bcf5385fa039b820e289dff61a5c8322
parent5357231c0a10eef558cc6aebfd172048dc010a96 (diff)
Fix all tst_qmetatype breakages after QList to QVector aliasing
In Qt6 QList is just a typedef to QVector. To keep Qt5 behavior compatibility we need to register aliases, otherwise some type name based operations would not work. The patch adds automatic registration of QList metatype alias for every QVector. The patch doesn't cover usage of already typedef'ed and aliased QList and QVector, but that should be quite esoteric, especially after introduction of automatic QList and QVector type registration. Change-Id: I84672dda2b159d94e76cdc6034861e7d7ef52533 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/corelib/kernel/qmetatype.cpp46
-rw-r--r--src/corelib/kernel/qmetatype.h18
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp6
3 files changed, 68 insertions, 2 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 356a675517..5c1e4b4ddd 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -37,6 +37,8 @@
**
****************************************************************************/
+#include <bitset>
+
#include "qmetatype.h"
#include "qmetatype_p.h"
#include "qobjectdefs.h"
@@ -2416,6 +2418,50 @@ const QMetaObject *metaObjectForQWidget()
return nullptr;
return qMetaObjectWidgetsHelper;
}
+
+void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName)
+{
+ // In Qt6 QList got typedef'ed to QVector. To keep runtime behavior compatibility
+ // with Qt5 we install corresponding aliases. For example if one register
+ // QVector<QVector<int>>
+ // we need to register the type plus all possible aliases:
+ // QVector<QList<int>>
+ // QList<QVector<int>>
+ // QList<QList<int>>
+ // ### Qt6 TODO This is slow, as it allocates couple of strings we would need to
+ // if def this call with something like QT_NO_QLIST
+ const char *vectorName = "QVector<";
+ const char *listName = "QList<";
+
+ auto isSubstringOfAType = [](char c) { return c != ' ' && c != ',' && c != '<'; };
+ QVarLengthArray<int> indexes;
+
+ for (auto containerName: {vectorName, listName}) {
+ for (int i = normalizedTypeName.indexOf(containerName, 0); i != -1; i = normalizedTypeName.indexOf(containerName, i + 1)) {
+ if (!i || (i > 0 && !isSubstringOfAType(normalizedTypeName[i - 1])))
+ indexes.append(i);
+ }
+ }
+ // To avoid problems with the constantly changing size we start replacements
+ // from the end of normalizedTypeName
+ std::sort(indexes.rbegin(), indexes.rend());
+
+ for (quint64 combination = 1; ; ++combination) {
+ std::bitset<64> bits(combination);
+ QByteArray name = normalizedTypeName;
+ for (auto j = 0; j < indexes.size(); ++j) {
+ if (bits.test(j)) {
+ auto i = indexes[j];
+ auto replaceFrom = normalizedTypeName[i + 1] == 'V' ? vectorName : listName;
+ auto replaceTo = normalizedTypeName[i + 1] == 'V' ? listName : vectorName;
+ name.replace(i, sizeof(replaceFrom), replaceTo);
+ }
+ }
+ QMetaType::registerNormalizedTypedef(name, id);
+ if (bits.count() >= size_t(indexes.size()))
+ break;
+ }
+}
}
namespace QtMetaTypePrivate {
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 7b985be9fd..f6fe62e164 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1645,6 +1645,23 @@ namespace QtPrivate
static bool registerConverter(int) { return false; }
};
+ template<class T>
+ struct Qt5CompatibilityHook
+ {
+ static inline void postRegister(int, const QByteArray &) {};
+ };
+
+ Q_CORE_EXPORT void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName);
+
+ template<class T>
+ struct Qt5CompatibilityHook<QVector<T>>
+ {
+ static inline void postRegister(int id, const QByteArray &normalizedTypeName)
+ {
+ qt5CompatibilityHookPostRegister(id, normalizedTypeName);
+ }
+ };
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@@ -1771,6 +1788,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
+ QtPrivate::Qt5CompatibilityHook<T>::postRegister(id, normalizedTypeName);
}
return id;
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 2a4ee55fa8..d300c31001 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -572,12 +572,14 @@ void tst_QMetaType::typeName_data()
QTest::newRow("124125534") << 124125534 << QString();
// automatic registration
- QTest::newRow("QList<int>") << ::qMetaTypeId<QList<int> >() << QString::fromLatin1("QList<int>");
QTest::newRow("QHash<int,int>") << ::qMetaTypeId<QHash<int, int> >() << QString::fromLatin1("QHash<int,int>");
QTest::newRow("QMap<int,int>") << ::qMetaTypeId<QMap<int, int> >() << QString::fromLatin1("QMap<int,int>");
- QTest::newRow("QVector<QList<int>>") << ::qMetaTypeId<QVector<QList<int> > >() << QString::fromLatin1("QVector<QList<int> >");
QTest::newRow("QVector<QMap<int,int>>") << ::qMetaTypeId<QVector<QMap<int, int> > >() << QString::fromLatin1("QVector<QMap<int,int> >");
+ // automatic registration with automatic QList to QVector aliasing
+ QTest::newRow("QList<int>") << ::qMetaTypeId<QList<int> >() << QString::fromLatin1("QVector<int>");
+ QTest::newRow("QVector<QList<int>>") << ::qMetaTypeId<QVector<QList<int> > >() << QString::fromLatin1("QVector<QVector<int> >");
+
QTest::newRow("CustomQObject*") << ::qMetaTypeId<CustomQObject*>() << QString::fromLatin1("CustomQObject*");
QTest::newRow("CustomGadget") << ::qMetaTypeId<CustomGadget>() << QString::fromLatin1("CustomGadget");
QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*");