diff options
author | Ulf Hermann <[email protected]> | 2024-12-19 11:48:49 +0100 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2024-12-20 09:44:16 +0100 |
commit | daab238846a80b83b0dabb50a4244a7eb29955f4 (patch) | |
tree | 517e676fa19c6b51ff099819a29edbac4c790f1d | |
parent | bac4723a30988c6b5b0430b8a394bbcf0b604db1 (diff) |
QmlCompiler: Round towards 0 when coercing to 64bit integers
The regular int32 coercion doesn't apply here. We have our own logic for
this case.
Pick-to: 6.9 6.8
Task-number: QTBUG-132345
Change-Id: I96596567ce83fcaa714c8372171261e8dd876480
Reviewed-by: Fabian Kosmale <[email protected]>
-rw-r--r-- | src/qml/common/qjsnumbercoercion.cpp | 7 | ||||
-rw-r--r-- | src/qml/common/qjsnumbercoercion.h | 12 | ||||
-rw-r--r-- | src/qml/common/qv4staticvalue_p.h | 6 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/takenumber.qml | 27 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 103 |
6 files changed, 93 insertions, 67 deletions
diff --git a/src/qml/common/qjsnumbercoercion.cpp b/src/qml/common/qjsnumbercoercion.cpp index 8cd96a4e25..d92c404a7e 100644 --- a/src/qml/common/qjsnumbercoercion.cpp +++ b/src/qml/common/qjsnumbercoercion.cpp @@ -59,4 +59,11 @@ QT_BEGIN_NAMESPACE Returns the \c true if they are equal, or \c false if not. */ +/*! + \fn double QJSNumberCoercion::roundTowards0(double d) + \internal + + Rounds \a d towards 0 by JavaScript \e ToInteger rules and returns the result. +*/ + QT_END_NAMESPACE diff --git a/src/qml/common/qjsnumbercoercion.h b/src/qml/common/qjsnumbercoercion.h index 0023bff6e8..53c1ce5138 100644 --- a/src/qml/common/qjsnumbercoercion.h +++ b/src/qml/common/qjsnumbercoercion.h @@ -65,6 +65,18 @@ public: QT_WARNING_POP } + static constexpr double roundTowards0(double d) + { + // Check for NaN + if (!equals(d, d)) + return +0; + + if (equals(d, 0) || std::isinf(d)) + return d; + + return d >= 0 ? std::floor(d) : std::ceil(d); + } + private: constexpr QJSNumberCoercion(double dbl) { diff --git a/src/qml/common/qv4staticvalue_p.h b/src/qml/common/qv4staticvalue_p.h index 9b4f582c00..1bf7513aec 100644 --- a/src/qml/common/qv4staticvalue_p.h +++ b/src/qml/common/qv4staticvalue_p.h @@ -478,11 +478,7 @@ struct StaticValue static double toInteger(double d) { - if (std::isnan(d)) - return +0; - if (!d || std::isinf(d)) - return d; - return d >= 0 ? std::floor(d) : std::ceil(d); + return QJSNumberCoercion::roundTowards0(d); } static int toInt32(double d) diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 242bda185d..b64ff5978d 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -4109,6 +4109,11 @@ QString QQmlJSCodeGenerator::convertStored( }; if (from == m_typeResolver->realType() || from == m_typeResolver->floatType()) { + if (to == m_typeResolver->int64Type() || to == m_typeResolver->uint64Type()) { + return to->internalName() + u"(QJSNumberCoercion::roundTowards0("_s + + variable + u"))"_s; + } + if (m_typeResolver->isSignedInteger(to)) return u"QJSNumberCoercion::toInteger("_s + variable + u')'; if (m_typeResolver->isUnsignedInteger(to)) diff --git a/tests/auto/qml/qmlcppcodegen/data/takenumber.qml b/tests/auto/qml/qmlcppcodegen/data/takenumber.qml index 8acb38dffe..ac1edfb193 100644 --- a/tests/auto/qml/qmlcppcodegen/data/takenumber.qml +++ b/tests/auto/qml/qmlcppcodegen/data/takenumber.qml @@ -57,4 +57,31 @@ TakeNumber { foo.takeNumbers({i:a, n:-a, s:a, l:a}); foo.propertyNumbers = {i:a, n:-a, s:a, l:a}; } + + function literal3B() { + foo.takeInt(3000000000) + foo.propertyInt = 3000000000; + foo.takeNegativeInt(-3000000000) + foo.propertyNegativeInt = -3000000000; + foo.takeQSizeType(3000000000) + foo.propertyQSizeType = 3000000000; + foo.takeQLongLong(3000000000) + foo.propertyQLongLong = 3000000000; + foo.takeNumbers({i:3000000000, n:-3000000000, s:3000000000, l:3000000000}); + foo.propertyNumbers = {i:3000000000, n:-3000000000, s:3000000000, l:3000000000}; + } + + function variable3B() { + var a = 3000000000 + foo.takeInt(a) + foo.propertyInt = a; + foo.takeNegativeInt(-a) + foo.propertyNegativeInt = -a; + foo.takeQSizeType(a) + foo.propertyQSizeType = a; + foo.takeQLongLong(a) + foo.propertyQLongLong = a; + foo.takeNumbers({i:a, n:-a, s:a, l:a}); + foo.propertyNumbers = {i:a, n:-a, s:a, l:a}; + } } diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 50972dcb90..1a4433b793 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -241,6 +241,7 @@ private slots: void stringToByteArray(); void structuredValueType(); void takeNumbers(); + void takeNumbers_data(); void testIsnan(); void thisObject(); void throwObjectName(); @@ -4913,6 +4914,11 @@ void tst_QmlCppCodegen::structuredValueType() void tst_QmlCppCodegen::takeNumbers() { + QFETCH(QByteArray, method); + QFETCH(int, expectedInt); + QFETCH(qsizetype, expectedSizeType); + QFETCH(qlonglong, expectedLongLong); + QQmlEngine engine; QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/takenumber.qml"_s)); QVERIFY2(c.isReady(), qPrintable(c.errorString())); @@ -4922,70 +4928,43 @@ void tst_QmlCppCodegen::takeNumbers() TakeNumber *takeNumber = qobject_cast<TakeNumber *>(o.data()); QVERIFY(takeNumber != nullptr); - QCOMPARE(takeNumber->takenInt, 0); - QCOMPARE(takeNumber->takenNegativeInt, 0); - QCOMPARE(takeNumber->takenQSizeType, 0); - QCOMPARE(takeNumber->takenQLongLong, 0); - QCOMPARE(takeNumber->takenNumbers, (Numbers {0, 0, 0, 0})); - QCOMPARE(takeNumber->propertyInt, 0); - QCOMPARE(takeNumber->propertyNegativeInt, 0); - QCOMPARE(takeNumber->propertyQSizeType, 0); - QCOMPARE(takeNumber->propertyQLongLong, 0); - QCOMPARE(takeNumber->propertyNumbers, (Numbers {0, 0, 0, 0})); - - o->metaObject()->invokeMethod(o.data(), "literal56"); - - QCOMPARE(takeNumber->takenInt, 56); - QCOMPARE(takeNumber->takenNegativeInt, -56); - QCOMPARE(takeNumber->takenQSizeType, 56); - QCOMPARE(takeNumber->takenQLongLong, 56); - QCOMPARE(takeNumber->takenNumbers, (Numbers {56, -56, 56, 56})); - QCOMPARE(takeNumber->propertyInt, 56); - QCOMPARE(takeNumber->propertyNegativeInt, -56); - QCOMPARE(takeNumber->propertyQSizeType, 56); - QCOMPARE(takeNumber->propertyQLongLong, 56); - QCOMPARE(takeNumber->propertyNumbers, (Numbers {56, -56, 56, 56})); - - o->metaObject()->invokeMethod(o.data(), "variable0"); - - QCOMPARE(takeNumber->takenInt, 0); - QCOMPARE(takeNumber->takenNegativeInt, 0); - QCOMPARE(takeNumber->takenQSizeType, 0); - QCOMPARE(takeNumber->takenQLongLong, 0); - QCOMPARE(takeNumber->takenNumbers, (Numbers {0, 0, 0, 0})); - QCOMPARE(takeNumber->propertyInt, 0); - QCOMPARE(takeNumber->propertyNegativeInt, 0); - QCOMPARE(takeNumber->propertyQSizeType, 0); - QCOMPARE(takeNumber->propertyQLongLong, 0); - QCOMPARE(takeNumber->propertyNumbers, (Numbers {0, 0, 0, 0})); - - o->metaObject()->invokeMethod(o.data(), "variable484"); - - QCOMPARE(takeNumber->takenInt, 484); - QCOMPARE(takeNumber->takenNegativeInt, -484); - QCOMPARE(takeNumber->takenQSizeType, 484); - QCOMPARE(takeNumber->takenQLongLong, 484); - QCOMPARE(takeNumber->takenNumbers, (Numbers {484, -484, 484, 484})); - QCOMPARE(takeNumber->propertyInt, 484); - QCOMPARE(takeNumber->propertyNegativeInt, -484); - QCOMPARE(takeNumber->propertyQSizeType, 484); - QCOMPARE(takeNumber->propertyQLongLong, 484); - QCOMPARE(takeNumber->propertyNumbers, (Numbers {484, -484, 484, 484})); - - o->metaObject()->invokeMethod(o.data(), "literal0"); - - QCOMPARE(takeNumber->takenInt, 0); - QCOMPARE(takeNumber->takenNegativeInt, 0); - QCOMPARE(takeNumber->takenQSizeType, 0); - QCOMPARE(takeNumber->takenQLongLong, 0); - QCOMPARE(takeNumber->takenNumbers, (Numbers {0, 0, 0, 0})); - QCOMPARE(takeNumber->propertyInt, 0); - QCOMPARE(takeNumber->propertyNegativeInt, 0); - QCOMPARE(takeNumber->propertyQSizeType, 0); - QCOMPARE(takeNumber->propertyQLongLong, 0); - QCOMPARE(takeNumber->propertyNumbers, (Numbers {0, 0, 0, 0})); + o->metaObject()->invokeMethod(o.data(), method); + + QCOMPARE(takeNumber->takenInt, expectedInt); + QCOMPARE(takeNumber->takenNegativeInt, -expectedInt); + QCOMPARE(takeNumber->takenQSizeType, expectedSizeType); + QCOMPARE(takeNumber->takenQLongLong, expectedLongLong); + QCOMPARE(takeNumber->takenNumbers, + (Numbers {expectedInt, -expectedInt, expectedSizeType, expectedLongLong})); + QCOMPARE(takeNumber->propertyInt, expectedInt); + QCOMPARE(takeNumber->propertyNegativeInt, -expectedInt); + QCOMPARE(takeNumber->propertyQSizeType, expectedSizeType); + QCOMPARE(takeNumber->propertyQLongLong, expectedLongLong); + QCOMPARE(takeNumber->propertyNumbers, + (Numbers {expectedInt, -expectedInt, expectedSizeType, expectedLongLong})); +} + +void tst_QmlCppCodegen::takeNumbers_data() +{ + QTest::addColumn<QByteArray>("method"); + QTest::addColumn<int>("expectedInt"); + QTest::addColumn<qsizetype>("expectedSizeType"); + QTest::addColumn<qlonglong>("expectedLongLong"); + + QTest::addRow("literal0") << "literal0"_ba << 0 << qsizetype(0) << 0ll; + QTest::addRow("literal56") << "literal56"_ba << 56 << qsizetype(56) << 56ll; + + QTest::addRow("variable0") << "variable0"_ba << 0 << qsizetype(0) << 0ll; + QTest::addRow("variable484") << "variable484"_ba << 484 << qsizetype(484) << 484ll; + + QTest::addRow("literal3B") + << "literal3B"_ba << int(3000000000ll) << qsizetype(3000000000ll) << 3000000000ll; + QTest::addRow("variable3B") + << "variable3B"_ba << int(3000000000ll) << qsizetype(3000000000ll) << 3000000000ll; + } + void tst_QmlCppCodegen::testIsnan() { QQmlEngine engine; |