diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-19 15:50:31 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-24 15:44:16 +0200 |
commit | a75ddda71b9a1af2fccad85aca725798eb8aa8e4 (patch) | |
tree | 93dbfda1de45d147d2bee2c23ff024ce781664a0 | |
parent | dc77f7c71c532a1c51f7618765559937fd5d2eb3 (diff) |
QmlCompiler: Implement LoadElement for value type lists
Instead of the storedType hack in the type resolver, properly declare
the type LoadElement can return: A merge of undefined and the actual
type. This way we can choose the best concrete type to use for this
independently (and optimize it later).
Task-number: QTBUG-103529
Change-Id: I17b1f835f6a893ec843a90491e92f72ecb2e87fe
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 35 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 11 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/typedArray.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 7 |
6 files changed, 40 insertions, 23 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index b04bff000f..8568154e3c 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -627,11 +627,6 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) return; } - if (!m_typeResolver->registerIsStoredIn(baseType, m_typeResolver->listPropertyType())) { - reject(u"indirect LoadElement"_s); - return; - } - AccumulatorConverter registers(this); const QString baseName = registerVariable(base); @@ -646,18 +641,32 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) + voidAssignment + u"else "_s; } - // Our QQmlListProperty only keeps plain QObject*. - const auto valueType = m_typeResolver->valueType(baseType); - const auto elementType = m_typeResolver->globalType( - m_typeResolver->genericType(m_typeResolver->containedType(valueType))); + + if (m_typeResolver->registerIsStoredIn(baseType, m_typeResolver->listPropertyType())) { + // Our QQmlListProperty only keeps plain QObject*. + const auto valueType = m_typeResolver->valueType(baseType); + const auto elementType = m_typeResolver->globalType( + m_typeResolver->genericType(m_typeResolver->containedType(valueType))); + + m_body += u"if ("_s + indexName + u" >= 0 && "_s + indexName + + u" < "_s + baseName + u".count(&"_s + baseName + + u"))\n"_s; + m_body += u" "_s + m_state.accumulatorVariableOut + u" = "_s + + conversion(elementType, m_state.accumulatorOut(), + baseName + u".at(&"_s + baseName + u", "_s + + indexName + u')') + u";\n"_s; + m_body += u"else\n"_s + + voidAssignment; + return; + } + + const auto elementType = m_typeResolver->valueType(baseType); m_body += u"if ("_s + indexName + u" >= 0 && "_s + indexName - + u" < "_s + baseName + u".count(&"_s + baseName - + u"))\n"_s; + + u" < "_s + baseName + u".count())\n"_s; m_body += u" "_s + m_state.accumulatorVariableOut + u" = "_s + conversion(elementType, m_state.accumulatorOut(), - baseName + u".at(&"_s + baseName + u", "_s - + indexName + u')') + u";\n"_s; + baseName + u".at("_s + indexName + u')') + u";\n"_s; m_body += u"else\n"_s + voidAssignment; } diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 8aaa75aaa6..7f859061fa 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -667,7 +667,10 @@ void QQmlJSTypePropagator::generate_LoadElement(int base) addReadAccumulator(m_typeResolver->globalType(m_typeResolver->realType())); addReadRegister(base, baseRegister); - setAccumulator(m_typeResolver->valueType(baseRegister)); + // We can end up with undefined. + setAccumulator(m_typeResolver->merge( + m_typeResolver->valueType(baseRegister), + m_typeResolver->globalType(m_typeResolver->voidType()))); } void QQmlJSTypePropagator::generate_StoreElement(int base, int index) diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 654eeb7e02..c01cf5dfb3 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -1205,15 +1205,8 @@ QQmlJSRegisterContent QQmlJSTypeResolver::valueType(const QQmlJSRegisterContent property.setTypeName(value->internalName()); property.setType(value); - QQmlJSScope::ConstPtr stored; - - // Special handling of stored type here: List lookup can always produce undefined - if (isPrimitive(value)) - stored = jsPrimitiveType(); - else - stored = jsValueType(); - - return QQmlJSRegisterContent::create(stored, property, QQmlJSRegisterContent::ListValue, scope); + return QQmlJSRegisterContent::create( + storedType(value), property, QQmlJSRegisterContent::ListValue, scope); } QQmlJSRegisterContent QQmlJSTypeResolver::returnType( diff --git a/tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml b/tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml index 14933a0792..a9f6725a5a 100644 --- a/tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml +++ b/tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml @@ -2,5 +2,6 @@ import QtQuick Item { property var oob: children[12] + property QtObject oob2: children[123] Component.onCompleted: console.log("oob", children[11]) } diff --git a/tests/auto/qml/qmlcppcodegen/data/typedArray.qml b/tests/auto/qml/qmlcppcodegen/data/typedArray.qml index 5ec54572a9..f9a40f5584 100644 --- a/tests/auto/qml/qmlcppcodegen/data/typedArray.qml +++ b/tests/auto/qml/qmlcppcodegen/data/typedArray.qml @@ -10,4 +10,8 @@ QtObject { property list<date> values4: [aDate, aDate, aDate] property list<real> values5: [1, 2, 3.4, "30", undefined, null] property list<QtObject> values6: [self, self, self] + + property int inIntList: values3[1] + property date inDateList: values4[2] + property real inRealList: values5[3] } diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 1ccbd81745..b4993d1752 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -937,6 +937,9 @@ void tst_QmlCppCodegen::outOfBoundsArray() QVERIFY(!object.isNull()); QVERIFY(object->metaObject()->indexOfProperty("oob") > 0); QVERIFY(!object->property("oob").isValid()); + const QVariant oob2 = object->property("oob2"); + QCOMPARE(oob2.metaType(), QMetaType::fromType<QObject *>()); + QCOMPARE(oob2.value<QObject *>(), nullptr); } void tst_QmlCppCodegen::compositeSingleton() @@ -1948,6 +1951,10 @@ void tst_QmlCppCodegen::typedArray() QCOMPARE(values6.count(&values6), 3); for (int i = 0; i < 3; ++i) QCOMPARE(values6.at(&values6, i), o.data()); + + QCOMPARE(o->property("inIntList").toInt(), 2); + QCOMPARE(qvariant_cast<QDateTime>(o->property("inDateList")), date); + QCOMPARE(o->property("inRealList").toDouble(), 30.0); } void tst_QmlCppCodegen::prefixedType() |