diff options
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 3 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h | 6 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp | 14 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 30 |
5 files changed, 54 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index bb4090129f..ac792a2f27 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -422,6 +422,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry) \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit \omitvalue PointerToGadget \omitvalue IsQmlList + \value IsConst Indicates that values of this types are immutable; for instance because they are pointers to const objects. */ /*! diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index c1567a7990..bdea0b2879 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -398,6 +398,7 @@ public: PointerToGadget = 0x400, IsPointer = 0x800, IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T> + IsConst = 0x2000, }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) @@ -827,6 +828,7 @@ namespace QtPrivate #ifndef QT_NO_QOBJECT static yes_type checkType(QObject* ); + static yes_type checkType(const QObject* ); #endif static no_type checkType(...); static_assert(sizeof(T), "Type argument of Q_PROPERTY or Q_DECLARE_METATYPE(T*) must be fully defined"); @@ -1157,6 +1159,7 @@ namespace QtPrivate { | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0) | (IsUnsignedEnum<T> ? QMetaType::IsUnsignedEnumeration : 0) | (IsQmlListType<T> ? QMetaType::IsQmlList : 0) + | (std::is_const_v<std::remove_pointer_t<T>> ? QMetaType::IsConst : 0) }; }; diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h index 2a0e177be1..fecd5d75c6 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h @@ -31,6 +31,11 @@ #include "tst_qmetatype_common.h" #include "tst_qvariant_common.h" +struct Derived : QObject +{ + Q_OBJECT +}; + struct MessageHandlerCustom : public MessageHandler { MessageHandlerCustom(const int typeId) @@ -118,6 +123,7 @@ private slots: void constRefs(); void convertCustomType_data(); void convertCustomType(); + void convertConstNonConst(); void compareCustomEqualOnlyType(); void customDebugStream(); void unknownType(); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp index 3c097ad0d8..856b56941a 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp @@ -278,6 +278,20 @@ void tst_QMetaType::convertCustomType() QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo); } +void tst_QMetaType::convertConstNonConst() +{ + auto mtConstObj = QMetaType::fromType<QObject const*>(); + auto mtObj = QMetaType::fromType<QObject *>(); + auto mtConstDerived = QMetaType::fromType<Derived const*>(); + auto mtDerived = QMetaType::fromType<Derived *>(); + + QVERIFY(QMetaType::canConvert(mtConstObj, mtObj)); + QVERIFY(QMetaType::canConvert(mtObj, mtConstObj)); // casting const away is allowed (but can lead to UB) + QVERIFY(QMetaType::canConvert(mtConstDerived, mtObj)); + QVERIFY(QMetaType::canConvert(mtDerived, mtConstObj)); + QVERIFY(QMetaType::canConvert(mtObj, mtConstDerived)); +} + void tst_QMetaType::compareCustomEqualOnlyType() { QMetaType type = QMetaType::fromType<CustomEqualsOnlyType>(); diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 23ee85ee46..2883a47852 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -59,6 +59,7 @@ #include <QEasingCurve> #include <QSequentialIterable> #include <QAssociativeIterable> +#include <QScopeGuard> #include "qnumeric.h" #include <private/qlocale_p.h> @@ -253,6 +254,7 @@ private slots: void convertByteArrayToBool() const; void convertByteArrayToBool_data() const; void convertIterables() const; + void convertConstNonConst() const; void toIntFromQString() const; void toIntFromDouble() const; void setValue(); @@ -3136,6 +3138,34 @@ void tst_QVariant::convertIterables() const } } +struct Derived : QObject +{ + Q_OBJECT +}; + +void tst_QVariant::convertConstNonConst() const +{ + Derived *derived = new Derived; + QObject *obj = derived; + QObject const *unrelatedConstObj = new QObject; + auto cleanUp = qScopeGuard([&] { + delete unrelatedConstObj; + delete derived; + }); + QObject const *constObj = obj; + Derived const *constDerived = derived; + QCOMPARE(QVariant::fromValue(constObj).value<QObject *>(), obj); + QCOMPARE(QVariant::fromValue(obj).value<QObject const *>(), constObj); + + QCOMPARE(QVariant::fromValue(constDerived).value<QObject *>(), derived); + QCOMPARE(QVariant::fromValue(derived).value<QObject const *>(), derived); + + QObject const *derivedAsConstObject = derived; + // up cast and remove const is possible, albeit dangerous + QCOMPARE(QVariant::fromValue(derivedAsConstObject).value<Derived *>(), derived); + QCOMPARE(QVariant::fromValue(unrelatedConstObj).value<Derived *>(), nullptr); +} + /*! We verify that: 1. Converting the string "9.9" to int fails. This is the behavior of |