diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-04-12 10:09:04 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-04-12 10:42:13 +0000 |
commit | bd786b82c96bf491e01a227d4e2be3afcf34db03 (patch) | |
tree | d5a3c014e46b3fd6d0cc2405bd7850aeff27be92 | |
parent | 46ea5407a9b06dc89e81d35871d79e18df83ac53 (diff) |
shiboken6: Add a placeholder for the base class to polymorphic-id-expression
Add %B for base class in addition to %1 for the class itself, which
is not useful and may lead to undefined behavior.
As a drive-by fix up the hitherto unused "polymorphic-base" which
is a boolean indicating the base class.
Task-number: PYSIDE-2675
Change-Id: I078191dc7b4c686b196fe58d6df9a249cdf2b151
Reviewed-by: Christian Tismer <tismer@stackless.com>
(cherry picked from commit 4a04afc95d348c8f26919a2f084ee80fa404e7d9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
4 files changed, 46 insertions, 5 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 1c1565ac2..71e80cfa8 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -88,6 +88,7 @@ constexpr auto pyiTypeAttribute = "pyi-type"_L1; constexpr auto overloadNumberAttribute = "overload-number"_L1; constexpr auto ownershipAttribute = "owner"_L1; constexpr auto packageAttribute = "package"_L1; +constexpr auto polymorphicBaseAttribute = "polymorphic-base"_L1; constexpr auto positionAttribute = "position"_L1; constexpr auto preferredConversionAttribute = "preferred-conversion"_L1; constexpr auto preferredTargetLangTypeAttribute = "preferred-target-lang-type"_L1; @@ -1810,8 +1811,10 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setGenericClass(v); } else if (name == targetLangNameAttribute) { ctype->setTargetLangName(attributes->takeAt(i).value().toString()); - } else if (name == u"polymorphic-base") { - ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); + } else if (name == polymorphicBaseAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + polymorphicBaseAttribute, false); + ctype->setIsPolymorphicBase(v); } else if (name == u"polymorphic-name-function") { ctype->setPolymorphicNameFunction(attributes->takeAt(i).value().toString()); } else if (name == u"polymorphic-id-expression") { diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst index 7a1471b44..66e68ae2b 100644 --- a/sources/shiboken6/doc/typesystem_specifying_types.rst +++ b/sources/shiboken6/doc/typesystem_specifying_types.rst @@ -453,6 +453,7 @@ or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`, parent-management="yes | no" polymorphic-id-expression="..." polymorphic-name-function="..." + polymorphic-base="yes | no" private="yes | no" qt-metaobject="yes | no" qt-register-metatype = "yes | no | base" @@ -540,6 +541,21 @@ expression checking whether a base class pointer is of the matching type. For example, in a ``virtual eventHandler(BaseEvent *e)`` function, this is used to construct a Python wrapper matching the derived class (for example, a ``MouseEvent`` or similar). +The attribute value may contain placeholders: + +%1 + Fully qualified class name + +%B + Fully qualified name of the base class (found by base class + search or as indicated by **polymorphic-base**). + +To check for a class inheriting ``BaseEvent``, specify: + +.. code-block:: xml + + <object-type name="MouseEvent" + polymorphic-id-expression="%B->type() == BaseEvent::MouseEvent"/> The *optional* **polymorphic-name-function** specifies the name of a function returning the type name of a derived class on the base class @@ -548,6 +564,10 @@ However, this fails if the type hierarchy does not have virtual functions. In this case, a function is required which typically decides depending on some type enumeration. +The *optional* **polymorphic-base** attribute indicates +whether the class is the base class of a class hierarchy +(used for the *%B* placeholder in **polymorphic-id-expression**). + interface-type ^^^^^^^^^^^^^^ diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 05539eb55..329b48d1c 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -5718,6 +5718,24 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const Generato } } +void CppGenerator::replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass, + QString *id) +{ + if (id->contains("%1"_L1)) { + QString replacement = " reinterpret_cast< "_L1 + m_gsp + metaClass->qualifiedCppName() + + " *>(cptr)"_L1; + id->replace("%1"_L1, replacement); + } + if (id->contains("%B"_L1)) { + auto baseClass = metaClass; + while (!baseClass->typeEntry()->isPolymorphicBase() && baseClass->baseClass()) + baseClass = baseClass->baseClass(); + QString replacement = " reinterpret_cast< "_L1 + m_gsp + baseClass->qualifiedCppName() + + " *>(cptr)"_L1; + id->replace("%B"_L1, replacement); + } +} + void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass) { @@ -5729,9 +5747,7 @@ void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, << sbkUnusedVariableCast("instanceType"); if (!polymorphicExpr.isEmpty()) { - polymorphicExpr.replace(u"%1"_s, " reinterpret_cast< "_L1 - + m_gsp + metaClass->qualifiedCppName() - + " *>(cptr)"_L1); + replacePolymorphicIdPlaceHolders(metaClass, &polymorphicExpr); s << " if (" << polymorphicExpr << ")\n" << indent << "return cptr;\n" << outdent; } else if (metaClass->isPolymorphic()) { diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 94ad87bbe..7e87fd9f3 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -192,6 +192,8 @@ private: static void writeTypeCheck(TextStream& s, const std::shared_ptr<OverloadDataNode> &overloadData, const QString &argumentName); + static void replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass, + QString *id); static void writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass); |