aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-07-04 17:00:15 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-07-07 19:33:27 +0200
commit3f3e961a5afe2e62f436f946c521ea4afab76dde (patch)
tree5025c3528580da614d1298d5bf594356d345a860
parent0e48d9d9387aeb39c8289f61f75d9c6fcd6c753f (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.cpp3
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp30
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp7
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumLookup.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp11
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