diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-17 14:40:00 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-06-01 15:06:06 +0200 |
commit | c41fe1592fea0afa805d6b1ed07791acc5113379 (patch) | |
tree | 64729e596943a19db5fb31410cf48431bdd46105 | |
parent | ec1dc0ed933a8270ec59ff69c41987862398ea2d (diff) |
QmlCompiler: Detect non-integral values when accessing QQmlListProperty
Fixes: QTBUG-103560
Change-Id: Ifcc73baf7f79e30f6e83ff3e500dd39f95790bfe
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
(cherry picked from commit 4a10e1d84ac948fb9a50cd2e44fcbeaef972e5ea)
-rw-r--r-- | src/qml/common/qjsnumbercoercion.h | 4 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 22 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/listIndices.qml | 8 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 4 |
6 files changed, 39 insertions, 5 deletions
diff --git a/src/qml/common/qjsnumbercoercion.h b/src/qml/common/qjsnumbercoercion.h index 2517442bb6..0e233747ff 100644 --- a/src/qml/common/qjsnumbercoercion.h +++ b/src/qml/common/qjsnumbercoercion.h @@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE class QJSNumberCoercion { public: + static constexpr bool isInteger(double d) { + return equals(d, d) && equals(static_cast<int>(d), d); + } + static constexpr int toInteger(double d) { if (!equals(d, d)) return 0; diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index cd325ae971..11fa085d0a 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -812,6 +812,15 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) const QString baseName = use(registerVariable(base)); const QString indexName = use(m_state.accumulatorVariableIn); + const QString voidAssignment = u" "_qs + m_state.accumulatorVariableOut + u" = "_qs + + conversion(m_typeResolver->globalType(m_typeResolver->voidType()), + m_state.accumulatorOut, QString()) + u";\n"_qs; + + if (!m_typeResolver->isIntegral(m_state.accumulatorIn)) { + m_body += u"if (!QJSNumberCoercion::isInteger("_qs + indexName + u"))\n"_qs + + voidAssignment + + u"else "_qs; + } // Our QQmlListProperty only keeps plain QObject*. const auto valueType = m_typeResolver->valueType(baseType); const auto elementType = m_typeResolver->globalType( @@ -824,9 +833,8 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) conversion(elementType, m_state.accumulatorOut, baseName + u".at(&"_qs + baseName + u", "_qs + indexName + u')') + u";\n"_qs; - m_body += u"else\n"_qs; - m_body += u" "_qs + m_state.accumulatorVariableOut + u" = {}"_qs; - m_body += u";\n"_qs; + m_body += u"else\n"_qs + + voidAssignment; } void QQmlJSCodeGenerator::generate_StoreElement(int base, int index) @@ -837,6 +845,7 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index) m_body.setWriteRegister(QString()); const QQmlJSRegisterContent baseType = registerType(base); + const QQmlJSRegisterContent indexType = registerType(index); if (!m_typeResolver->isNumeric(registerType(index)) || !baseType.isList()) { reject(u"StoreElement with non-list base type or non-numeric arguments"_qs); @@ -855,8 +864,11 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index) const auto elementType = m_typeResolver->globalType(m_typeResolver->genericType( m_typeResolver->containedType(valueType))); - m_body += u"if ("_qs + indexName + u" >= 0 && "_qs + indexName - + u" < "_qs + baseName + u".count(&"_qs + baseName + m_body += u"if ("_qs; + if (!m_typeResolver->isIntegral(indexType)) + m_body += u"QJSNumberCoercion::isInteger("_qs + indexName + u") && "_qs; + m_body += indexName + u" >= 0 && "_qs + + indexName + u" < "_qs + baseName + u".count(&"_qs + baseName + u"))\n"_qs; m_body += u" "_qs + baseName + u".replace(&"_qs + baseName + u", "_qs + indexName + u", "_qs; diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index d1e1fa66f8..e38038d79a 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -255,6 +255,11 @@ bool QQmlJSTypeResolver::isNumeric(const QQmlJSRegisterContent &type) const return isNumeric(containedType(type)); } +bool QQmlJSTypeResolver::isIntegral(const QQmlJSRegisterContent &type) const +{ + return containedType(type) == m_intType; +} + bool QQmlJSTypeResolver::isPrimitive(const QQmlJSScope::ConstPtr &type) const { return type == m_intType || type == m_realType || type == m_floatType || type == m_boolType diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h index 491391f801..85daa35cb1 100644 --- a/src/qmlcompiler/qqmljstyperesolver_p.h +++ b/src/qmlcompiler/qqmljstyperesolver_p.h @@ -107,6 +107,7 @@ public: bool isPrimitive(const QQmlJSRegisterContent &type) const; bool isNumeric(const QQmlJSRegisterContent &type) const; + bool isIntegral(const QQmlJSRegisterContent &type) const; bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const; bool canConvertFromTo(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const; diff --git a/tests/auto/qml/qmlcppcodegen/data/listIndices.qml b/tests/auto/qml/qmlcppcodegen/data/listIndices.qml index b5fda4ef0d..9df172b2e6 100644 --- a/tests/auto/qml/qmlcppcodegen/data/listIndices.qml +++ b/tests/auto/qml/qmlcppcodegen/data/listIndices.qml @@ -5,10 +5,18 @@ QtObject { id: self property list<QtObject> items property int numItems: items.length + property QtObject fractional: items[2.25] + property QtObject negativeZero: items[-1 * 0] + property QtObject infinity: items[1 / 0] + property QtObject nan: items[1 - "a"] Component.onCompleted: { items.length = 3 for (var i = 0; i < 3; ++i) items[i] = self + + items[2.25] = null + items[1 / 0] = self + items[1 - "a"] = self } } diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index bd6fb37677..1e71eaad52 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -1553,6 +1553,10 @@ void tst_QmlCppCodegen::listIndices() for (int i = 0; i < 3; ++i) QCOMPARE(list.at(i), o.data()); QCOMPARE(o->property("numItems").toInt(), 3); + QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr); + QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data()); + QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr); + QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr); } void tst_QmlCppCodegen::jsMathObject() |