aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqml.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-03-27 18:01:07 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-04-26 10:57:27 +0200
commitf10630aa035ae1ef4ad75be1107ab77fea0c7e29 (patch)
tree35080e7a0991f8819e5952fcc347d64503607848 /src/qml/qml/qqml.cpp
parent9088125f148d298837d830023f5da0172e1736b6 (diff)
QmlCompiler: Use actual type of enums, rather than int
Now that the type is available from qmltypes we can just use it. Task-number: QTBUG-112180 Change-Id: I315372da0925f19c209f676226f450863b0d3ea5 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/qml/qml/qqml.cpp')
-rw-r--r--src/qml/qml/qqml.cpp80
1 files changed, 72 insertions, 8 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 7bbfe39ae9..bdebba53d0 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -1020,9 +1020,41 @@ static bool isTypeCompatible(QMetaType lookupType, QMetaType propertyType)
if (!foundMetaObject)
return false;
- } else if (lookupType == QMetaType::fromType<int>()
- && propertyType.flags() & QMetaType::IsEnumeration) {
- return true;
+ } else if (propertyType.flags() & QMetaType::IsEnumeration) {
+ if (propertyType == lookupType)
+ return true;
+
+ // You can pass the underlying type of an enum.
+ // We don't want to check for the actual underlying type because
+ // moc and qmltyperegistrar are not very precise about it. Especially
+ // the long and longlong types can be ambiguous.
+
+ const bool isUnsigned = propertyType.flags() & QMetaType::IsUnsignedEnumeration;
+ switch (propertyType.sizeOf()) {
+ case 1:
+ return isUnsigned
+ ? lookupType == QMetaType::fromType<quint8>()
+ : lookupType == QMetaType::fromType<qint8>();
+ case 2:
+ return isUnsigned
+ ? lookupType == QMetaType::fromType<ushort>()
+ : lookupType == QMetaType::fromType<short>();
+ case 4:
+ // The default type, if moc doesn't know the actual enum type, is int.
+ // However, the compiler can still decide to encode the enum in uint.
+ // Therefore, we also accept int for uint enums.
+ // TODO: This is technically UB.
+ return isUnsigned
+ ? (lookupType == QMetaType::fromType<int>()
+ || lookupType == QMetaType::fromType<uint>())
+ : lookupType == QMetaType::fromType<int>();
+ case 8:
+ return isUnsigned
+ ? lookupType == QMetaType::fromType<qulonglong>()
+ : lookupType == QMetaType::fromType<qlonglong>();
+ }
+
+ return false;
} else if (propertyType != lookupType) {
return false;
}
@@ -1776,13 +1808,44 @@ void AOTCompiledContext::initGetValueLookup(
engine->handle()->throwTypeError();
}
-bool AOTCompiledContext::getEnumLookup(uint index, int *target) const
+bool AOTCompiledContext::getEnumLookup(uint index, void *target) const
{
QV4::Lookup *l = compilationUnit->runtimeLookups + index;
if (l->getter != QV4::QQmlTypeWrapper::lookupEnumValue)
return false;
- *target = l->qmlEnumValueLookup.encodedEnumValue;
- return true;
+ const bool isUnsigned
+ = l->qmlEnumValueLookup.metaType->flags & QMetaType::IsUnsignedEnumeration;
+ const QV4::ReturnedValue encoded = l->qmlEnumValueLookup.encodedEnumValue;
+ switch (l->qmlEnumValueLookup.metaType->size) {
+ case 1:
+ if (isUnsigned)
+ *static_cast<quint8 *>(target) = encoded;
+ else
+ *static_cast<qint8 *>(target) = encoded;
+ return true;
+ case 2:
+ if (isUnsigned)
+ *static_cast<quint16 *>(target) = encoded;
+ else
+ *static_cast<qint16 *>(target) = encoded;
+ return true;
+ case 4:
+ if (isUnsigned)
+ *static_cast<quint32 *>(target) = encoded;
+ else
+ *static_cast<qint32 *>(target) = encoded;
+ return true;
+ case 8:
+ if (isUnsigned)
+ *static_cast<quint64 *>(target) = encoded;
+ else
+ *static_cast<qint64 *>(target) = encoded;
+ return true;
+ default:
+ break;
+ }
+
+ return false;
}
void AOTCompiledContext::initGetEnumLookup(
@@ -1798,8 +1861,9 @@ void AOTCompiledContext::initGetEnumLookup(
return;
}
const int enumIndex = metaObject->indexOfEnumerator(enumerator);
- const int value = metaObject->enumerator(enumIndex).keyToValue(enumValue);
- l->qmlEnumValueLookup.encodedEnumValue = value;
+ const QMetaEnum metaEnum = metaObject->enumerator(enumIndex);
+ l->qmlEnumValueLookup.encodedEnumValue = metaEnum.keyToValue(enumValue);
+ l->qmlEnumValueLookup.metaType = metaEnum.metaType().iface();
l->getter = QV4::QQmlTypeWrapper::lookupEnumValue;
}