QVariant: Fix conversion code
Fixes: QTBUG-86330 Change-Id: Ib89dcf1195e0081b4c4e2845f90c52c612e5911a Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
3ddffd2d8b
commit
19874d6a63
@ -2050,8 +2050,17 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
|
|||||||
// handle QObject conversion
|
// handle QObject conversion
|
||||||
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
|
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
|
||||||
QObject *fromObject = *static_cast<QObject * const *>(from);
|
QObject *fromObject = *static_cast<QObject * const *>(from);
|
||||||
*static_cast<QObject **>(to) = fromObject ? fromObject->metaObject()->cast(fromObject) : nullptr;
|
// use dynamic metatype of from if possible
|
||||||
return true;
|
if (fromObject && fromObject->metaObject()->inherits(toType.metaObject())) {
|
||||||
|
*static_cast<QObject **>(to) = toType.metaObject()->cast(fromObject);
|
||||||
|
return true;
|
||||||
|
} else if (!fromObject) {
|
||||||
|
// if fromObject is null, use static fromType to check if conversion works
|
||||||
|
*static_cast<void **>(to) = nullptr;
|
||||||
|
return fromType.metaObject()->inherits(toType.metaObject());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -221,6 +221,7 @@ private slots:
|
|||||||
void compareCustomTypes() const;
|
void compareCustomTypes() const;
|
||||||
void timeToDateTime() const;
|
void timeToDateTime() const;
|
||||||
void copyingUserTypes() const;
|
void copyingUserTypes() const;
|
||||||
|
void valueClassHierarchyConversion() const;
|
||||||
void convertBoolToByteArray() const;
|
void convertBoolToByteArray() const;
|
||||||
void convertBoolToByteArray_data() const;
|
void convertBoolToByteArray_data() const;
|
||||||
void convertByteArrayToBool() const;
|
void convertByteArrayToBool() const;
|
||||||
@ -2894,6 +2895,43 @@ void tst_QVariant::copyingUserTypes() const
|
|||||||
QCOMPARE(copiedType.myValue, 42);
|
QCOMPARE(copiedType.myValue, 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct NonQObjectBase {};
|
||||||
|
struct NonQObjectDerived : NonQObjectBase {};
|
||||||
|
|
||||||
|
void tst_QVariant::valueClassHierarchyConversion() const
|
||||||
|
{
|
||||||
|
|
||||||
|
{
|
||||||
|
// QVariant allows downcasting
|
||||||
|
QScopedPointer<CustomQObjectDerived> derived {new CustomQObjectDerived};
|
||||||
|
QVariant var = QVariant::fromValue(derived.get());
|
||||||
|
CustomQObject *object = var.value<CustomQObject *>();
|
||||||
|
QVERIFY(object);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// QVariant supports upcasting to the correct dynamic type for QObjects
|
||||||
|
QScopedPointer<CustomQObjectDerived> derived {new CustomQObjectDerived};
|
||||||
|
QVariant var = QVariant::fromValue<CustomQObject *>(derived.get());
|
||||||
|
CustomQObjectDerived *object = var.value<CustomQObjectDerived *>();
|
||||||
|
QVERIFY(object);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// QVariant forbids unsafe upcasting
|
||||||
|
QScopedPointer<CustomQObject> base {new CustomQObject};
|
||||||
|
QVariant var = QVariant::fromValue(base.get());
|
||||||
|
CustomQObjectDerived *object = var.value<CustomQObjectDerived *>();
|
||||||
|
QVERIFY(!object);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// QVariant does not support upcastingfor non-QObjects
|
||||||
|
QScopedPointer<NonQObjectDerived> derived {new NonQObjectDerived};
|
||||||
|
QVariant var = QVariant::fromValue<NonQObjectBase *>(derived.get());
|
||||||
|
NonQObjectDerived *object = var.value<NonQObjectDerived *>();
|
||||||
|
QVERIFY(!object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QVariant::convertBoolToByteArray() const
|
void tst_QVariant::convertBoolToByteArray() const
|
||||||
{
|
{
|
||||||
QFETCH(QByteArray, input);
|
QFETCH(QByteArray, input);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user