QVariants of null pointers should be null

Changes the QVariant::isNull() implementation for
pointer types so they return true if null.

[ChangeLog][QVariant] QVariants containing pointers will now return
true on isNull() if the contained pointer is null.

Change-Id: I8aa0dab482403837073fb2f376a46126cc3bc6b2
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Allan Sandfeld Jensen 2017-01-23 10:31:16 +01:00 committed by Simon Hausmann
parent 341bfcd1ea
commit f2c6e10ad5
3 changed files with 43 additions and 6 deletions

View File

@ -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<void *const *>(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.

View File

@ -187,6 +187,16 @@ public:
}
};
template <typename T>
struct PrimitiveIsNull<T*>
{
public:
static bool isNull(const QVariant::Private *d)
{
return d->is_null || d->data.ptr == nullptr;
}
};
template <>
struct PrimitiveIsNull<std::nullptr_t>
{

View File

@ -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(QJsonValue::Null));
QVERIFY(var9.isNull());
QVariant var10(QMetaType::VoidStar, nullptr);
QVERIFY(var10.isNull());
var10 = QVariant::fromValue<void*>(nullptr);
QVERIFY(var10.isNull());
QVariant var11(QMetaType::QObjectStar, nullptr);
QVERIFY(var11.isNull());
var11 = QVariant::fromValue<QObject*>(nullptr);
QVERIFY(var11.isNull());
QVERIFY(QVariant::fromValue<int*>(nullptr).isNull());
}
void tst_QVariant::swap()
@ -2650,7 +2664,7 @@ void tst_QVariant::qvariant_cast_QObject_data()
QTest::newRow("null QObject") << QVariant::fromValue<QObject*>(0) << true << true;
QTest::newRow("null derived QObject") << QVariant::fromValue<CustomQObject*>(0) << true << true;
QTest::newRow("null custom object") << QVariant::fromValue<CustomNonQObject*>(0) << false << true;
QTest::newRow("null int") << QVariant::fromValue<int>(0) << false << true;
QTest::newRow("zero int") << QVariant::fromValue<int>(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<QObject*>()));
QCOMPARE(data.value<QObject*>() == 0, isNull);
QCOMPARE(data.isNull(), isNull);
QVERIFY(data.convert(QMetaType::QObjectStar));
QCOMPARE(data.userType(), int(QMetaType::QObjectStar));
} else {
QVERIFY(!data.canConvert<QObject*>());
QVERIFY(!data.canConvert(QMetaType::QObjectStar));
QVERIFY(!data.canConvert(::qMetaTypeId<QObject*>()));
QCOMPARE(data.isNull(), isNull);
QVERIFY(!data.value<QObject*>());
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);
}
{