aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/common/qjsnumbercoercion.cpp14
-rw-r--r--src/qml/common/qjsnumbercoercion.h36
-rw-r--r--src/qml/common/qv4staticvalue_p.h2
-rw-r--r--src/qml/compiler/qv4codegen.cpp2
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp4
-rw-r--r--src/qmlcompiler/qqmljslinter_p.h2
-rw-r--r--src/qmlcompiler/qqmlsa.cpp4
7 files changed, 54 insertions, 10 deletions
diff --git a/src/qml/common/qjsnumbercoercion.cpp b/src/qml/common/qjsnumbercoercion.cpp
index 986a3e97f2..ba76c12bb0 100644
--- a/src/qml/common/qjsnumbercoercion.cpp
+++ b/src/qml/common/qjsnumbercoercion.cpp
@@ -14,6 +14,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn bool QJSNumberCoercion::isInteger(double d)
+ \internal
+ \deprecated 6.7
+ */
+
+/*!
+ \fn bool QJSNumberCoercion::isArrayIndex(double d)
+ \internal
+
+ Checks whether \a d contains a value that can serve as an index into an array.
+ For that, \a d must be a non-negative value representable as an int.
+ */
+
+/*!
\fn int QJSNumberCoercion::toInteger(double d)
\internal
diff --git a/src/qml/common/qjsnumbercoercion.h b/src/qml/common/qjsnumbercoercion.h
index 03827f82f1..bc04794d2f 100644
--- a/src/qml/common/qjsnumbercoercion.h
+++ b/src/qml/common/qjsnumbercoercion.h
@@ -12,17 +12,43 @@ QT_BEGIN_NAMESPACE
class QJSNumberCoercion
{
public:
- static constexpr bool isInteger(double d) {
- return equals(d, d) && equals(static_cast<int>(d), d);
+
+#if QT_DEPRECATED_SINCE(6, 7)
+
+ QT_DEPRECATED_VERSION_6_7
+ static constexpr bool isInteger(double d)
+ {
+ // Comparing d with itself checks for NaN and comparing d with the min and max values
+ // for int also covers infinities.
+ if (!equals(d, d) || d < std::numeric_limits<int>::min()
+ || d > std::numeric_limits<int>::max()) {
+ return false;
+ }
+
+ return equals(static_cast<int>(d), d);
+ }
+
+#endif
+
+ static constexpr bool isArrayIndex(double d)
+ {
+ if (d < 0 || !equals(d, d) || d > std::numeric_limits<int>::max()) {
+ return false;
+ }
+
+ return equals(static_cast<int>(d), d);
}
static constexpr int toInteger(double d) {
+ // Check for NaN
if (!equals(d, d))
return 0;
- const int i = static_cast<int>(d);
- if (equals(i, d))
- return i;
+ if (d >= std::numeric_limits<int>::min() && d <= std::numeric_limits<int>::max()) {
+ const int i = static_cast<int>(d);
+ if (equals(i, d))
+ return i;
+ }
return QJSNumberCoercion(d).toInteger();
}
diff --git a/src/qml/common/qv4staticvalue_p.h b/src/qml/common/qv4staticvalue_p.h
index e9c3554104..9a88fccc04 100644
--- a/src/qml/common/qv4staticvalue_p.h
+++ b/src/qml/common/qv4staticvalue_p.h
@@ -393,7 +393,7 @@ struct StaticValue
}
QV4_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
- int i = int(d);
+ int i = QJSNumberCoercion::toInteger(d);
return (i == d && !(d == 0 && std::signbit(d)));
}
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index f9c4398490..c43bdd8387 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -4625,7 +4625,7 @@ QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty str
StaticValue p = StaticValue::fromReturnedValue(constant);
if (p.isNumber()) {
double d = p.asDouble();
- int i = static_cast<int>(d);
+ int i = QJSNumberCoercion::toInteger(d);
if (d == i && (d != 0 || !std::signbit(d))) {
if (!i) {
Instruction::LoadZero load;
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index e10d924e79..f67cf12974 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -681,7 +681,7 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base)
m_state.accumulatorOut(), QString()) + u";\n"_s;
if (!m_typeResolver->isIntegral(m_state.accumulatorIn())) {
- m_body += u"if (!QJSNumberCoercion::isInteger("_s + indexName + u"))\n"_s
+ m_body += u"if (!QJSNumberCoercion::isArrayIndex("_s + indexName + u"))\n"_s
+ voidAssignment
+ u"else "_s;
}
@@ -753,7 +753,7 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index)
m_body += u"if ("_s;
if (!m_typeResolver->isIntegral(indexType))
- m_body += u"QJSNumberCoercion::isInteger("_s + indexName + u") && "_s;
+ m_body += u"QJSNumberCoercion::isArrayIndex("_s + indexName + u") && "_s;
if (!m_typeResolver->isUnsignedInteger(m_typeResolver->containedType(indexType)))
m_body += indexName + u" >= 0 && "_s;
m_body += indexName + u" < "_s + baseName + u".count(&"_s + baseName
diff --git a/src/qmlcompiler/qqmljslinter_p.h b/src/qmlcompiler/qqmljslinter_p.h
index 5bef11c55b..33c72c3b96 100644
--- a/src/qmlcompiler/qqmljslinter_p.h
+++ b/src/qmlcompiler/qqmljslinter_p.h
@@ -98,7 +98,7 @@ public:
QList<QQmlJS::LoggerCategory> m_categories;
QQmlSA::LintPlugin *m_instance;
std::unique_ptr<QPluginLoader> m_loader;
- bool m_isBuiltin;
+ bool m_isBuiltin = false;
bool m_isInternal =
false; // Internal plugins are those developed and maintained inside the Qt project
bool m_isValid = false;
diff --git a/src/qmlcompiler/qqmlsa.cpp b/src/qmlcompiler/qqmlsa.cpp
index 59307fb812..4dcdedbed9 100644
--- a/src/qmlcompiler/qqmlsa.cpp
+++ b/src/qmlcompiler/qqmlsa.cpp
@@ -899,6 +899,10 @@ Element GenericPass::resolveAttachedInFileScope(QAnyStringView typeName)
{
const auto type = resolveTypeInFileScope(typeName);
const auto scope = QQmlJSScope::scope(type);
+
+ if (scope.isNull())
+ return QQmlJSScope::createQQmlSAElement(QQmlJSScope::ConstPtr(nullptr));
+
return QQmlJSScope::createQQmlSAElement(scope->attachedType());
}