summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetatype.cpp1
-rw-r--r--src/corelib/kernel/qmetatype.h3
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h6
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp14
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp30
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