diff options
-rw-r--r-- | src/imports/builtins/builtins.qmltypes | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsmetatypes_p.h | 6 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 9 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/nullBinding.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/nullBindingFunction.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 8 |
10 files changed, 40 insertions, 6 deletions
diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes index 0bc89d8c9c..93f6019901 100644 --- a/src/imports/builtins/builtins.qmltypes +++ b/src/imports/builtins/builtins.qmltypes @@ -11,6 +11,11 @@ Module { } Component { + name: "std::nullptr_t" + accessSemantics: "none" + } + + Component { name: "QVariant" accessSemantics: "value" exports: ["QML/var 1.0", "QML/variant 1.0"] diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index e6efb9d649..1d52a2582b 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -473,7 +473,7 @@ void QQmlJSCodeGenerator::generate_LoadNull() INJECT_TRACE_INFO(generate_LoadNull); m_body += m_state.accumulatorVariableOut; - m_body += u" = QJSPrimitiveNull()"_qs; + m_body += u" = nullptr"_qs; m_body += u";\n"_qs; } diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 1530a6cc89..87e6b0d7e0 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -1412,7 +1412,7 @@ bool QQmlJSImportVisitor::parseLiteralBinding(const QString name, // QQmlJSMetaPropertyBinding::hasLiteral() value = QVariant::fromValue(nullptr); Q_ASSERT(value.isNull()); - literalType = u"var"_qs; // QTBUG-98409 + literalType = u"$anonymous$.std::nullptr_t"_qs; bindingType = QQmlJSMetaPropertyBinding::Null; break; case Node::Kind_NumericLiteral: diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h index 903ab1992d..c68010be30 100644 --- a/src/qmlcompiler/qqmljsmetatypes_p.h +++ b/src/qmlcompiler/qqmljsmetatypes_p.h @@ -503,7 +503,11 @@ public: QString valueSourceTypeName() const { return m_valueSourceTypeName; } QSharedPointer<const QQmlJSScope> valueSourceType() const { return m_valueSource; } - bool hasLiteral() const { return isLiteralBinding() && !m_literalValue.isNull(); } + bool hasLiteral() const + { + return isLiteralBinding() + && (!m_literalValue.isNull() || m_bindingType == QQmlJSMetaPropertyBinding::Null); + } bool hasObject() const { return m_bindingType == BindingType::Object && !m_value.isNull(); } bool hasInterceptor() const { diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 54cbf1e02b..900d642cff 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -139,7 +139,7 @@ void QQmlJSTypePropagator::generate_LoadFalse() void QQmlJSTypePropagator::generate_LoadNull() { - m_state.accumulatorOut = m_typeResolver->globalType(m_typeResolver->jsPrimitiveType()); + m_state.accumulatorOut = m_typeResolver->globalType(m_typeResolver->nullType()); } void QQmlJSTypePropagator::generate_LoadUndefined() diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 9c5264e68d..0cc4a83963 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -67,6 +67,7 @@ QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer) { const QHash<QString, QQmlJSScope::ConstPtr> builtinTypes = importer->builtinInternalNames(); m_voidType = builtinTypes[u"void"_qs]; + m_nullType = builtinTypes[u"std::nullptr_t"_qs]; m_realType = builtinTypes[u"double"_qs]; m_floatType = builtinTypes[u"float"_qs]; m_intType = builtinTypes[u"int"_qs]; @@ -291,7 +292,8 @@ bool QQmlJSTypeResolver::isNumeric(const QQmlJSRegisterContent &type) const bool QQmlJSTypeResolver::isPrimitive(const QQmlJSScope::ConstPtr &type) const { return type == m_intType || type == m_realType || type == m_floatType || type == m_boolType - || type == m_voidType || type == m_stringType || type == m_jsPrimitiveType; + || type == m_voidType || type == m_nullType || type == m_stringType + || type == m_jsPrimitiveType; } bool QQmlJSTypeResolver::isNumeric(const QQmlJSScope::ConstPtr &type) const @@ -386,8 +388,11 @@ bool QQmlJSTypeResolver::canConvertFromTo(const QQmlJSScope::ConstPtr &from, if (to.isNull()) return false; + if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) + return true; + if (from == m_jsPrimitiveType) { - // You can cast any primitive (in particular null) to a nullptr + // You can cast any primitive to a nullptr return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference; } diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h index a59ffd6e37..893d287170 100644 --- a/src/qmlcompiler/qqmljstyperesolver_p.h +++ b/src/qmlcompiler/qqmljstyperesolver_p.h @@ -68,6 +68,7 @@ public: void init(QQmlJSImportVisitor *visitor, QQmlJS::AST::Node *program); QQmlJSScope::ConstPtr voidType() const { return m_voidType; } + QQmlJSScope::ConstPtr nullType() const { return m_nullType; } QQmlJSScope::ConstPtr realType() const { return m_realType; } QQmlJSScope::ConstPtr floatType() const { return m_floatType; } QQmlJSScope::ConstPtr intType() const { return m_intType; } @@ -153,6 +154,7 @@ protected: QQmlJSRegisterContent lengthProperty(bool isWritable, const QQmlJSScope::ConstPtr &scope) const; QQmlJSScope::ConstPtr m_voidType; + QQmlJSScope::ConstPtr m_nullType; QQmlJSScope::ConstPtr m_numberPrototype; QQmlJSScope::ConstPtr m_realType; QQmlJSScope::ConstPtr m_floatType; diff --git a/tests/auto/qml/qmllint/data/nullBinding.qml b/tests/auto/qml/qmllint/data/nullBinding.qml new file mode 100644 index 0000000000..f185ce9eda --- /dev/null +++ b/tests/auto/qml/qmllint/data/nullBinding.qml @@ -0,0 +1,5 @@ +import QtQuick + +Item { + x: null +} diff --git a/tests/auto/qml/qmllint/data/nullBindingFunction.qml b/tests/auto/qml/qmllint/data/nullBindingFunction.qml new file mode 100644 index 0000000000..89142bd581 --- /dev/null +++ b/tests/auto/qml/qmllint/data/nullBindingFunction.qml @@ -0,0 +1,5 @@ +import QtQuick + +Item { + x: { return null } +} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index b1fe3fc103..1359264a10 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -829,6 +829,14 @@ void TestQmllint::dirtyQmlCode_data() << QStringLiteral("didYouMeanComponent.qml") << QStringLiteral("Itym was not found. Did you add all import paths?") << QString() << QStringLiteral("Item") << false; + QTest::newRow("nullBinding") + << QStringLiteral("nullBinding.qml") + << QStringLiteral("Cannot assign binding of type $anonymous$.std::nullptr_t to double") + << QString() << QString() << false; + QTest::newRow("nullBindingFunction") + << QStringLiteral("nullBindingFunction.qml") + << QStringLiteral("Cannot assign binding of type std::nullptr_t to double") << QString() + << QString() << false; } void TestQmllint::dirtyQmlCode() |