From df1e8c4670c04f1c9b83845e21edaab98d34c5e8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 11 Dec 2019 14:35:57 +0100 Subject: shiboken: Handle smart pointers with const pointees Treat them equally to smart pointers with non-const pointees by searching for the pointee type entry in the instantiation search and stripping the const there. Create an additional type index equal to the non-const pointee index for the const pointee instantiation. This has the slight drawback that it is possible to invoke non-const calls on the pointee in Python, but this is nearly unfixable since the dispatch happens in the getattro method, where the information about constness is lost. Task-number: PYSIDE-454 Change-Id: Ib514816e408d727656b1599060e105ccd021bb07 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/generator/generator.cpp | 47 ++++++++++++++++------ .../generator/shiboken2/headergenerator.cpp | 12 +++++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index b14edfc4c..585102b01 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -159,7 +159,6 @@ struct Generator::GeneratorPrivate QString licenseComment; QString moduleName; QStringList instantiatedContainersNames; - QStringList instantiatedSmartPointerNames; QVector instantiatedContainers; QVector instantiatedSmartPointers; @@ -211,6 +210,31 @@ QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType *type) return typeName; } +// Strip a "const QSharedPtr &" or similar to "QSharedPtr" (PYSIDE-1016/454) +const AbstractMetaType *canonicalSmartPtrInstantiation(const AbstractMetaType *type) +{ + AbstractMetaTypeList instantiations = type->instantiations(); + Q_ASSERT(instantiations.size() == 1); + const bool needsFix = type->isConstant() || type->referenceType() != NoReference; + const bool pointeeNeedsFix = instantiations.constFirst()->isConstant(); + if (!needsFix && !pointeeNeedsFix) + return type; + auto fixedType = type->copy(); + fixedType->setReferenceType(NoReference); + fixedType->setConstant(false); + if (pointeeNeedsFix) { + auto fixedPointeeType = instantiations.constFirst()->copy(); + fixedPointeeType->setConstant(false); + fixedType->setInstantiations(AbstractMetaTypeList(1, fixedPointeeType)); + } + return fixedType; +} + +static inline const TypeEntry *pointeeTypeEntry(const AbstractMetaType *smartPtrType) +{ + return smartPtrType->instantiations().constFirst()->typeEntry(); +} + void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, const QString &context) { @@ -244,18 +268,15 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType m_d->instantiatedContainers.append(type); } } else { - // Is smart pointer. - if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { - m_d->instantiatedSmartPointerNames.append(typeName); - if (type->isConstant() || type->referenceType() != NoReference) { - // Strip a "const QSharedPtr &" or similar to "QSharedPtr" (PYSIDE-1016) - auto fixedType = type->copy(); - fixedType->setReferenceType(NoReference); - fixedType->setConstant(false); - type = fixedType; - } - m_d->instantiatedSmartPointers.append(type); - } + // Is smart pointer. Check if the (const?) pointee is already known + auto pt = pointeeTypeEntry(type); + const bool present = + std::any_of(m_d->instantiatedSmartPointers.cbegin(), m_d->instantiatedSmartPointers.cend(), + [pt] (const AbstractMetaType *t) { + return pointeeTypeEntry(t) == pt; + }); + if (!present) + m_d->instantiatedSmartPointers.append(canonicalSmartPtrInstantiation(type)); } } diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index cf96c8d5c..a565659de 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -401,9 +401,17 @@ bool HeaderGenerator::finishGeneration() int smartPointerCount = 0; const QVector &instantiatedSmartPtrs = instantiatedSmartPointers(); for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - _writeTypeIndexValue(macrosStream, getTypeIndexVariableName(metaType), - smartPointerCountIndex); + QString indexName = getTypeIndexVariableName(metaType); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); macrosStream << ", // " << metaType->cppSignature() << Qt::endl; + // Add a the same value for const pointees (shared_ptr). + const auto ptrName = metaType->typeEntry()->entryName(); + int pos = indexName.indexOf(ptrName, 0, Qt::CaseInsensitive); + if (pos >= 0) { + indexName.insert(pos + ptrName.size() + 1, QLatin1String("CONST")); + _writeTypeIndexValue(macrosStream, indexName, smartPointerCountIndex); + macrosStream << ", // (const)\n"; + } ++smartPointerCountIndex; ++smartPointerCount; } -- cgit v1.2.3