diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-04-23 14:17:15 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-04-24 10:20:16 +0200 |
commit | f34dcb84adf20e9f3428660636aa8d377d14fc3b (patch) | |
tree | e44f337979c036d2eb41e7e04b358a6b37bc8a56 /sources/shiboken6/generator | |
parent | c0674262fd7e859a8002e6e850b6ec0a4162b456 (diff) |
shiboken6: Fix leaking tuples in introduceWrapperType()
When calling introduceWrapperType(), the generated
code creates and leaks a tuple of base types if there
are base classes. When there are no base classes, a
tuple (containing SbkObjectType) is created and leaked
within introduceWrapperType().
To fix this, generate the complete tuple including
SbkObjectType in the generated code and remove the
base type parameter to introduceWrapperType().
Pick-to: 6.7
Task-number: PYSIDE-1617
Change-Id: Ib3bec8e6b94bea14a46df826667373d3f859dfd5
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken6/generator')
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 84 | ||||
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.h | 1 |
2 files changed, 48 insertions, 37 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index bfde1ff53..037209dfb 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -60,6 +60,8 @@ static const char shibokenErrorsOccurred[] = "Shiboken::Errors::occurred() != nu static constexpr auto virtualMethodStaticReturnVar = "result"_L1; +static constexpr auto sbkObjectTypeF = "SbkObject_TypeF()"_L1; + static QString mangleName(QString name) { if (name == u"None" || name == u"False" || name == u"True" || name == u"from") @@ -4356,7 +4358,6 @@ void CppGenerator::writeClassDefinition(TextStream &s, QString tp_hash; QString tp_call; const QString className = chopType(cpythonTypeName(metaClass)); - QString baseClassName; AbstractMetaFunctionCList ctors; const auto &allCtors = metaClass->queryFunctions(FunctionQueryOption::AnyConstructor); for (const auto &f : allCtors) { @@ -4366,9 +4367,6 @@ void CppGenerator::writeClassDefinition(TextStream &s, } } - if (!metaClass->baseClass()) - baseClassName = u"SbkObject_TypeF()"_s; - bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor(); const bool isQApp = usePySideExtensions() @@ -4702,7 +4700,7 @@ void CppGenerator::writeTpTraverseFunction(TextStream &s, const AbstractMetaClas s << "static int " << baseName << "_traverse(PyObject *self, visitproc visit, void *arg)\n{\n" << indent << "auto traverseProc = " - << pyTypeGetSlot("traverseproc", "SbkObject_TypeF()", "Py_tp_traverse") << ";\n" + << pyTypeGetSlot("traverseproc", sbkObjectTypeF, "Py_tp_traverse") << ";\n" << "return traverseProc(self, visit, arg);\n" << outdent << "}\n"; } @@ -4712,7 +4710,7 @@ void CppGenerator::writeTpClearFunction(TextStream &s, const AbstractMetaClassCP QString baseName = cpythonBaseName(metaClass); s << "static int " << baseName << "_clear(PyObject *self)\n{\n" << indent << "auto clearProc = " - << pyTypeGetSlot("inquiry", "SbkObject_TypeF()", "Py_tp_clear") << ";\n" + << pyTypeGetSlot("inquiry", sbkObjectTypeF, "Py_tp_clear") << ";\n" << "return clearProc(self);\n" << outdent << "}\n"; } @@ -5441,6 +5439,40 @@ QString CppGenerator::destructorClassName(const AbstractMetaClassCPtr &metaClass return metaClass->qualifiedCppName(); } +// Return the base type entries for introduceWrapperType() +static ComplexTypeEntryCList pyBaseTypeEntries(const AbstractMetaClassCPtr &metaClass) +{ + ComplexTypeEntryCList result; + if (metaClass->isNamespace()) { + if (auto extended = metaClass->extendedNamespace()) + result.append(extended->typeEntry()); + return result; + } + + const auto &baseClasses = metaClass->typeSystemBaseClasses(); + for (auto base : baseClasses) { + for (; base != nullptr; base = base->baseClass()) { // Find a type that is not disabled. + const auto ct = base->typeEntry()->codeGeneration(); + if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass) + break; + } + result.append(base->typeEntry()); + } + return result; +} + +// Return the base type strings for introduceWrapperType() +QStringList CppGenerator::pyBaseTypes(const AbstractMetaClassCPtr &metaClass) +{ + const auto &baseEntries = pyBaseTypeEntries(metaClass); + QStringList result; + for (const auto &baseEntry : baseEntries) + result.append("reinterpret_cast<PyObject *>("_L1 + cpythonTypeNameExt(baseEntry) + u')'); + if (result.isEmpty()) // no base classes -> SbkObjectType. + result.append(sbkObjectTypeF); + return result; +} + void CppGenerator::writeClassRegister(TextStream &s, const AbstractMetaClassCPtr &metaClass, const GeneratorContext &classContext, @@ -5467,18 +5499,15 @@ void CppGenerator::writeClassRegister(TextStream &s, // Multiple inheritance QString pyTypeBasesVariable = chopType(pyTypeName) + u"_Type_bases"_s; - const auto &baseClasses = metaClass->typeSystemBaseClasses(); - if (metaClass->baseClassNames().size() > 1) { - s << "PyObject *" << pyTypeBasesVariable - << " = PyTuple_Pack(" << baseClasses.size() << ',' << '\n' << indent; - for (qsizetype i = 0, size = baseClasses.size(); i < size; ++i) { - if (i) - s << ",\n"; - s << "reinterpret_cast<PyObject *>(" - << cpythonTypeNameExt(baseClasses.at(i)->typeEntry()) << ')'; - } - s << ");\n\n" << outdent; + const QStringList pyBases = pyBaseTypes(metaClass); + s << "Shiboken::AutoDecRef " << pyTypeBasesVariable << "(PyTuple_Pack(" + << pyBases.size() << ",\n" << indent; + for (qsizetype i = 0, size = pyBases.size(); i < size; ++i) { + if (i) + s << ",\n"; + s << pyBases.at(i); } + s << "));\n\n" << outdent; // Create type and insert it in the module or enclosing class. const QString typePtr = u"_"_s + chopType(pyTypeName) @@ -5513,27 +5542,8 @@ void CppGenerator::writeClassRegister(TextStream &s, s << "&Shiboken::callCppDestructor< " << globalScopePrefix(classContext) << dtorClassName << " >,\n"; - // 6:baseType: Find a type that is not disabled. - auto base = metaClass->isNamespace() - ? metaClass->extendedNamespace() : metaClass->baseClass(); - if (!metaClass->isNamespace()) { - for (; base != nullptr; base = base->baseClass()) { - const auto ct = base->typeEntry()->codeGeneration(); - if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass) - break; - } - } - if (base) { - s << cpythonTypeNameExt(base->typeEntry()) << ",\n"; - } else { - s << "nullptr,\n"; - } - // 7:baseTypes - if (metaClass->baseClassNames().size() > 1) - s << pyTypeBasesVariable << ',' << '\n'; - else - s << "nullptr,\n"; + s << pyTypeBasesVariable << ".object()," << '\n'; // 8:wrapperflags QByteArrayList wrapperFlags; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 1b4ebf803..6c20d9d78 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -400,6 +400,7 @@ private: const AbstractMetaClassCPtr &metaClass, const GeneratorContext &classContext, const QString &signatures) const; + static QStringList pyBaseTypes(const AbstractMetaClassCPtr &metaClass); static QString destructorClassName(const AbstractMetaClassCPtr &metaClass, const GeneratorContext &classContext); static void writeStaticFieldInitialization(TextStream &s, |