diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index b73c83bc49..a6b92f9f8f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1177,7 +1177,17 @@ static void customClear(QVariant::Private *d) static bool customIsNull(const QVariant::Private *d) { - return d->is_null; + if (d->is_null) + return true; + const char *const typeName = QMetaType::typeName(d->type); + if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(d->type))) + qFatal("QVariant::isNull: type %d unknown to QVariant.", d->type); + uint typeNameLen = qstrlen(typeName); + if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') { + const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data.ptr); + return *static_cast(d_ptr) == nullptr; + } + return false; } static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) @@ -3740,9 +3750,10 @@ void* QVariant::data() /*! Returns \c true if this is a null variant, false otherwise. A variant is - considered null if it contains no initialized value or it contains an instance - of built-in type that has an isNull method, in which case the result would be - the same as calling isNull on the wrapped object. + considered null if it contains no initialized value, or the contained value + is a null pointer or is an instance of a built-in type that has an isNull + method, in which case the result would be the same as calling isNull on the + wrapped object. \warning Null variants is not a single state and two null variants may easily return \c false on the == operator if they do not contain similar null values. diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 487949431c..75c269d710 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -187,6 +187,16 @@ public: } }; +template +struct PrimitiveIsNull +{ +public: + static bool isNull(const QVariant::Private *d) + { + return d->is_null || d->data.ptr == nullptr; + } +}; + template <> struct PrimitiveIsNull { diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 906587248e..a5973276f2 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -371,6 +371,8 @@ void tst_QVariant::copy_constructor() QVERIFY(var8.isNull()); } +Q_DECLARE_METATYPE(int*) + void tst_QVariant::isNull() { QVariant var; @@ -413,6 +415,18 @@ void tst_QVariant::isNull() QVERIFY(var9.isNull()); var9 = QVariant::fromValue(QJsonValue(QJsonValue::Null)); QVERIFY(var9.isNull()); + + QVariant var10(QMetaType::VoidStar, nullptr); + QVERIFY(var10.isNull()); + var10 = QVariant::fromValue(nullptr); + QVERIFY(var10.isNull()); + + QVariant var11(QMetaType::QObjectStar, nullptr); + QVERIFY(var11.isNull()); + var11 = QVariant::fromValue(nullptr); + QVERIFY(var11.isNull()); + + QVERIFY(QVariant::fromValue(nullptr).isNull()); } void tst_QVariant::swap() @@ -2650,7 +2664,7 @@ void tst_QVariant::qvariant_cast_QObject_data() QTest::newRow("null QObject") << QVariant::fromValue(0) << true << true; QTest::newRow("null derived QObject") << QVariant::fromValue(0) << true << true; QTest::newRow("null custom object") << QVariant::fromValue(0) << false << true; - QTest::newRow("null int") << QVariant::fromValue(0) << false << true; + QTest::newRow("zero int") << QVariant::fromValue(0) << false << false; } void tst_QVariant::qvariant_cast_QObject() @@ -2668,12 +2682,14 @@ void tst_QVariant::qvariant_cast_QObject() QVERIFY(data.canConvert(QMetaType::QObjectStar)); QVERIFY(data.canConvert(::qMetaTypeId())); QCOMPARE(data.value() == 0, isNull); + QCOMPARE(data.isNull(), isNull); QVERIFY(data.convert(QMetaType::QObjectStar)); QCOMPARE(data.userType(), int(QMetaType::QObjectStar)); } else { QVERIFY(!data.canConvert()); QVERIFY(!data.canConvert(QMetaType::QObjectStar)); QVERIFY(!data.canConvert(::qMetaTypeId())); + QCOMPARE(data.isNull(), isNull); QVERIFY(!data.value()); QVERIFY(!data.convert(QMetaType::QObjectStar)); QVERIFY(data.userType() != QMetaType::QObjectStar); @@ -3752,7 +3768,7 @@ void tst_QVariant::moreCustomTypes() { int i = 5; PLAY_WITH_VARIANT((void *)(&i), false, QString(), 0, false); - PLAY_WITH_VARIANT((void *)(0), false, QString(), 0, false); + PLAY_WITH_VARIANT((void *)(0), true, QString(), 0, false); } {