diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-07-04 17:00:15 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-07-07 19:33:27 +0200 |
commit | 3f3e961a5afe2e62f436f946c521ea4afab76dde (patch) | |
tree | 5025c3528580da614d1298d5bf594356d345a860 | |
parent | 0e48d9d9387aeb39c8289f61f75d9c6fcd6c753f (diff) |
QmlCompiler: Allow wrapping enums into int
This is what we do internally in the QML engine.
Pick-to: 6.4
Fixes: QTBUG-104683
Change-Id: I2f8712cb2cdc56b6c483500627fd8a218edbad81
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/qml/qqml.cpp | 3 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 30 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 7 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 6 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/enumLookup.qml | 11 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 11 |
7 files changed, 55 insertions, 14 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index cb5157a6e1..0fd0f9b5cd 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -921,6 +921,9 @@ 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 != lookupType) { return false; } diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index f5b4f1e9a4..5369c09681 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -1970,12 +1970,19 @@ QString QQmlJSCodeGenerator::contentPointer(const QQmlJSRegisterContent &content const QQmlJSScope::ConstPtr stored = content.storedType(); if (m_typeResolver->registerContains(content, stored)) return u'&' + var; - else if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->varType())) + + if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->varType())) return var + u".data()"_s; - else if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) + + if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) return u'&' + var; - else - reject(u"content pointer of non-QVariant wrapper type "_s + content.descriptiveName()); + + if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->intType()) + && m_typeResolver->containedType(content)->scopeType() == QQmlJSScope::EnumScope) { + return u'&' + var; + } + + reject(u"content pointer of non-QVariant wrapper type "_s + content.descriptiveName()); return QString(); } @@ -1986,12 +1993,19 @@ QString QQmlJSCodeGenerator::contentType(const QQmlJSRegisterContent &content, c m_typeResolver->containedType(content)); if (m_typeResolver->equals(contained, stored)) return metaTypeFromType(stored); - else if (m_typeResolver->equals(stored, m_typeResolver->varType())) + + if (m_typeResolver->equals(stored, m_typeResolver->varType())) return var + u".metaType()"_s; // We expect the QVariant to be initialized - else if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) + + if (stored->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) return metaTypeFromName(contained); - else - reject(u"content type of non-QVariant wrapper type "_s + content.descriptiveName()); + + if (m_typeResolver->registerIsStoredIn(content, m_typeResolver->intType()) + && m_typeResolver->containedType(content)->scopeType() == QQmlJSScope::EnumScope) { + return metaTypeFromType(m_typeResolver->intType()); + } + + reject(u"content type of non-QVariant wrapper type "_s + content.descriptiveName()); return QString(); } diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index c16fe32135..94a91ccd9b 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -1742,15 +1742,16 @@ void QQmlJSTypePropagator::recordEqualsType(int lhs) }; const auto isIntCompatible = [this](const QQmlJSRegisterContent &content) { - return content.isEnumeration() - || m_typeResolver->registerContains(content, m_typeResolver->intType()); + const QQmlJSScope::ConstPtr contained = m_typeResolver->containedType(content); + return contained->scopeType() == QQmlJSScope::EnumScope + || m_typeResolver->equals(contained, m_typeResolver->intType()); }; const auto accumulatorIn = m_state.accumulatorIn(); const auto lhsRegister = m_state.registers[lhs]; // If the types are primitive, we compare directly ... - if (m_typeResolver->isPrimitive(accumulatorIn)) { + if (m_typeResolver->isPrimitive(accumulatorIn) || accumulatorIn.isEnumeration()) { if (m_typeResolver->registerContains( accumulatorIn, m_typeResolver->containedType(lhsRegister))) { addReadRegister(lhs, accumulatorIn); diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 963485e89c..1c8feadaee 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -675,12 +675,12 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(const QQmlJSScope::ConstPt return type; } - if (isNumeric(type)) - return m_realType; - if (type->scopeType() == QQmlJSScope::EnumScope) return m_intType; + if (isNumeric(type)) + return m_realType; + if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence) { if (equals(type, m_listPropertyType)) return type; diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index f9b678d087..56c663eb5e 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -67,6 +67,7 @@ set(qml_files dialog.qml dynamicscene.qml enumInvalid.qml + enumLookup.qml enumScope.qml enumsInOtherObject.qml enumsUser.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/enumLookup.qml b/tests/auto/qml/qmlcppcodegen/data/enumLookup.qml new file mode 100644 index 0000000000..693f3e275f --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/enumLookup.qml @@ -0,0 +1,11 @@ +pragma Strict +import QML + +QtObject { + property Component c: Component { + id: cc + QtObject {} + } + + property bool ready: cc.status == Component.Ready +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index f96efacd3f..6d397f2060 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -130,6 +130,7 @@ private slots: void registerPropagation(); void argumentConversion(); void badSequence(); + void enumLookup(); }; void tst_QmlCppCodegen::simpleBinding() @@ -2402,6 +2403,16 @@ void tst_QmlCppCodegen::badSequence() QCOMPARE(self->barzles(), barzles); } +void tst_QmlCppCodegen::enumLookup() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumLookup.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + + QCOMPARE(o->property("ready").toBool(), true); +} + void tst_QmlCppCodegen::runInterpreted() { #ifdef Q_OS_ANDROID |