diff options
-rw-r--r-- | src/qml/common/qjsnumbercoercion.cpp | 14 | ||||
-rw-r--r-- | src/qml/common/qjsnumbercoercion.h | 36 | ||||
-rw-r--r-- | src/qml/common/qv4staticvalue_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 4 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslinter_p.h | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmlsa.cpp | 4 |
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()); } |