summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/imports/builtins/builtins.qmltypes5
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp2
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp2
-rw-r--r--src/qmlcompiler/qqmljsmetatypes_p.h6
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp2
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp9
-rw-r--r--src/qmlcompiler/qqmljstyperesolver_p.h2
-rw-r--r--tests/auto/qml/qmllint/data/nullBinding.qml5
-rw-r--r--tests/auto/qml/qmllint/data/nullBindingFunction.qml5
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp8
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()