aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-05-19 15:50:31 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-05-24 15:44:16 +0200
commita75ddda71b9a1af2fccad85aca725798eb8aa8e4 (patch)
tree93dbfda1de45d147d2bee2c23ff024ce781664a0
parentdc77f7c71c532a1c51f7618765559937fd5d2eb3 (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.cpp35
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp5
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/outOfBounds.qml1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/typedArray.qml4
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp7
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()