aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2024-12-19 11:48:49 +0100
committerUlf Hermann <[email protected]>2024-12-20 09:44:16 +0100
commitdaab238846a80b83b0dabb50a4244a7eb29955f4 (patch)
tree517e676fa19c6b51ff099819a29edbac4c790f1d
parentbac4723a30988c6b5b0430b8a394bbcf0b604db1 (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.cpp7
-rw-r--r--src/qml/common/qjsnumbercoercion.h12
-rw-r--r--src/qml/common/qv4staticvalue_p.h6
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/takenumber.qml27
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp103
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;