diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2022-05-17 16:48:13 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2022-05-23 12:50:02 +0200 |
commit | 560a47590fc0c22c18ca91fee56176e2501561f6 (patch) | |
tree | feaf171f02fc9b2e916adce5f4078a6f0b5bb10c | |
parent | 69cd8c2779d18e82d9872c9f55c45caa029365b0 (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.h | 3 | ||||
-rw-r--r-- | src/qmlintegration/qqmlintegration.h | 18 |
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) |