aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-05-17 16:48:13 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2022-05-23 12:50:02 +0200
commit560a47590fc0c22c18ca91fee56176e2501561f6 (patch)
treefeaf171f02fc9b2e916adce5f4078a6f0b5bb10c
parent69cd8c2779d18e82d9872c9f55c45caa029365b0 (diff)
QML: Add markers corresponding to various QML attributes
QML attributes are transitive: a base type's attributes leak into derived type This causes issues in type registration since we cannot tell whether a type has a specific attribute is really present for it. For instance, things like QML_EXTENDED, QML_ATTACHED, QML_SINGLETON and a few others are the offenders The way to overcome this, in the lack of the own type, is to store a static meta object of the enclosing type as a marker when we encounter a particular attribute declaration. We can then attest whether the marker stored matches the static meta object of the type we assess: if so, it is the same type; if not, we are in a derived type. Consider: class X : public QObject { Q_OBJECT QML_EXTENDED //-> unpacks roughly in: // (old) using QmlExtendedType = ...; // (new) inline constexpr void marker() {} }; class Y : public X { Q_OBJECT }; Before: X::QmlExtendedType - exists Y::QmlExtendedType - exists (due to inheritance) After: X::QmlExtendedType - exists Y::QmlExtendedType - exists classType<decltype(X::marker)> == X // truly QmlExtendedType classType<decltype(Y::marker)> != Y // falsely QmlExtendedType Note that this commit does not use the markers, but only introduces them Change-Id: I22fdee056c2fc63bc64386dd5de62e6021f15a02 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/qml/qml/qqmlregistration.h3
-rw-r--r--src/qmlintegration/qqmlintegration.h18
2 files changed, 14 insertions, 7 deletions
diff --git a/src/qml/qml/qqmlregistration.h b/src/qml/qml/qqmlregistration.h
index edbae1c654..db387e09f3 100644
--- a/src/qml/qml/qqmlregistration.h
+++ b/src/qml/qml/qqmlregistration.h
@@ -51,7 +51,8 @@ QT_BEGIN_NAMESPACE
using QmlForeignType = FOREIGN_TYPE; \
template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlResolved; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_foreign() {}
#define QML_FOREIGN_NAMESPACE(FOREIGN_NAMESPACE) \
Q_CLASSINFO("QML.Foreign", #FOREIGN_NAMESPACE)
diff --git a/src/qmlintegration/qqmlintegration.h b/src/qmlintegration/qqmlintegration.h
index 5333ed9ce3..a70c49d8d8 100644
--- a/src/qmlintegration/qqmlintegration.h
+++ b/src/qmlintegration/qqmlintegration.h
@@ -92,7 +92,8 @@ QT_END_NAMESPACE
enum class QmlIsSingleton {yes = true}; \
template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSingleton; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_singleton() {}
#define QML_ADDED_IN_MINOR_VERSION(VERSION) \
Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(VERSION))
@@ -113,14 +114,16 @@ QT_END_NAMESPACE
Q_CLASSINFO("QML.Attached", #ATTACHED_TYPE) \
using QmlAttachedType = ATTACHED_TYPE; \
template<class, class, bool> friend struct QML_PRIVATE_NAMESPACE::QmlAttached; \
- template<class> friend struct QML_PRIVATE_NAMESPACE::QmlAttachedAccessor;
+ template<class> friend struct QML_PRIVATE_NAMESPACE::QmlAttachedAccessor; \
+ inline constexpr void qt_qmlMarker_attached() {}
#define QML_EXTENDED(EXTENDED_TYPE) \
Q_CLASSINFO("QML.Extended", #EXTENDED_TYPE) \
using QmlExtendedType = EXTENDED_TYPE; \
template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtended; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_extended() {}
#define QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE) \
Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE) \
@@ -128,7 +131,8 @@ QT_END_NAMESPACE
static constexpr const QMetaObject *qmlExtendedNamespace() { return &EXTENDED_NAMESPACE::staticMetaObject; } \
template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtendedNamespace; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_extendedNamespace() {}
#define QML_NAMESPACE_EXTENDED(EXTENDED_NAMESPACE) \
Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE)
@@ -138,7 +142,8 @@ QT_END_NAMESPACE
enum class QmlIsInterface {yes = true}; \
template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlInterface; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_interface() {}
#define QML_IMPLEMENTS_INTERFACES(INTERFACES) \
Q_INTERFACES(INTERFACES) \
@@ -151,7 +156,8 @@ QT_END_NAMESPACE
enum class QmlIsSequence {yes = true}; \
template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSequence; \
template<typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); \
+ inline constexpr void qt_qmlMarker_sequence() {}
#define QML_UNAVAILABLE \
QML_FOREIGN(QQmlTypeNotAvailable)