aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/cppgenerator.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-09-18 14:49:58 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-09-27 11:13:31 +0200
commitf6d11df9409da11e084f57633025c2806735e8b7 (patch)
tree7cfca13e4eb5109905227c11ffa978925840deab /sources/shiboken6/generator/shiboken/cppgenerator.cpp
parentadd66c6f981f7614ab35feedad7d5c58b54d6e94 (diff)
shiboken6: Split out smart pointer code from CppGenerator
Pick-to: 6.6 Task-number: PYSIDE-2462 Change-Id: Ida1d297f1f5fda53146cd967795bcce2d6f933f7 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/shiboken6/generator/shiboken/cppgenerator.cpp')
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp436
1 files changed, 6 insertions, 430 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 10c12f52a..69673b303 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -192,18 +192,6 @@ QString CppGenerator::fileNameForContext(const GeneratorContext &context) const
return fileNameForContextHelper(context, u"_wrapper.cpp"_s);
}
-std::optional<AbstractMetaType>
- CppGenerator::findSmartPointerInstantiation(const SmartPointerTypeEntryCPtr &pointer,
- const TypeEntryCPtr &pointee) const
-{
- for (const auto &smp : api().instantiatedSmartPointers()) {
- const auto &i = smp.type;
- if (i.typeEntry() == pointer && i.instantiations().at(0).typeEntry() == pointee)
- return i;
- }
- return {};
-}
-
void CppGenerator::clearTpFuncs()
{
// Functions that should not be registered under a name in PyMethodDef,
@@ -223,7 +211,7 @@ static const char includeQDebug[] =
"#endif\n"
"#include <QtCore/QDebug>\n";
-static QString chopType(QString s)
+QString CppGenerator::chopType(QString s)
{
if (s.endsWith(u"_Type"))
s.chop(5);
@@ -458,8 +446,8 @@ void CppGenerator::generateIncludes(TextStream &s, const GeneratorContext &class
}
// Write methods definition
-static void writePyMethodDefs(TextStream &s, const QString &className,
- const QString &methodsDefinitions, bool generateCopy)
+void CppGenerator::writePyMethodDefs(TextStream &s, const QString &className,
+ const QString &methodsDefinitions, bool generateCopy)
{
s << "static PyMethodDef " << className << "_methods[] = {\n" << indent
<< methodsDefinitions << '\n';
@@ -471,7 +459,7 @@ static void writePyMethodDefs(TextStream &s, const QString &className,
<< "};\n\n";
}
-static bool hasHashFunction(const AbstractMetaClassCPtr &c)
+bool CppGenerator::hasHashFunction(const AbstractMetaClassCPtr &c)
{
return !c->typeEntry()->hashFunction().isEmpty()
|| c->hasHashFunction();
@@ -794,143 +782,6 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
}
}
-static bool hasParameterPredicate(const AbstractMetaFunctionCPtr &f)
-{
- return !f->arguments().isEmpty();
-}
-
-void CppGenerator::generateSmartPointerClass(TextStream &s, const GeneratorContext &classContext)
-{
- s.setLanguage(TextStream::Language::Cpp);
- AbstractMetaClassCPtr metaClass = classContext.metaClass();
- const auto typeEntry = std::static_pointer_cast<const SmartPointerTypeEntry>(metaClass->typeEntry());
- const bool hasPointeeClass = classContext.pointeeClass() != nullptr;
- const auto smartPointerType = typeEntry->smartPointerType();
- const bool isValueHandle = smartPointerType ==TypeSystem::SmartPointerType::ValueHandle;
-
- IncludeGroup includes{u"Extra includes"_s, typeEntry->extraIncludes()};
- if (hasPointeeClass)
- includes.append(classContext.pointeeClass()->typeEntry()->include());
- generateIncludes(s, classContext, {includes});
-
- s << '\n';
-
- // class inject-code native/beginning
- if (!typeEntry->codeSnips().isEmpty()) {
- writeClassCodeSnips(s, typeEntry->codeSnips(),
- TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode,
- classContext);
- s << '\n';
- }
-
- StringStream smd(TextStream::Language::Cpp);
- StringStream md(TextStream::Language::Cpp);
- StringStream signatureStream(TextStream::Language::Cpp);
-
- s << openTargetExternC;
-
- const auto &functionGroups = getFunctionGroups(metaClass);
-
- // Skip all public methods of the smart pointer except for the special
- // methods declared in the type entry.
-
- auto ctors = metaClass->queryFunctions(FunctionQueryOption::Constructors);
- if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
- auto end = std::remove_if(ctors.begin(), ctors.end(), hasParameterPredicate);
- ctors.erase(end, ctors.end());
- }
-
- if (!ctors.isEmpty()) {
- OverloadData overloadData(ctors, api());
- writeConstructorWrapper(s, overloadData, classContext);
- writeSignatureInfo(signatureStream, overloadData);
- }
-
- if (!typeEntry->resetMethod().isEmpty()) {
- auto it = functionGroups.constFind(typeEntry->resetMethod());
- if (it == functionGroups.cend())
- throw Exception(msgCannotFindSmartPointerMethod(typeEntry, typeEntry->resetMethod()));
- AbstractMetaFunctionCList resets = it.value();
- if (!hasPointeeClass && !isValueHandle) { // Cannot generate "int*"
- auto end = std::remove_if(resets.begin(), resets.end(), hasParameterPredicate);
- resets.erase(end, resets.end());
- }
- if (!resets.isEmpty())
- writeMethodWrapper(s, md, signatureStream, resets, classContext);
- }
-
- auto it = functionGroups.constFind(typeEntry->getter());
- if (it == functionGroups.cend() || it.value().size() != 1)
- throw Exception(msgCannotFindSmartPointerGetter(typeEntry));
-
- writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
-
- QStringList optionalMethods;
- if (!typeEntry->refCountMethodName().isEmpty())
- optionalMethods.append(typeEntry->refCountMethodName());
- const QString valueCheckMethod = typeEntry->valueCheckMethod();
- if (!valueCheckMethod.isEmpty() && !valueCheckMethod.startsWith(u"operator"))
- optionalMethods.append(valueCheckMethod);
- if (!typeEntry->nullCheckMethod().isEmpty())
- optionalMethods.append(typeEntry->nullCheckMethod());
-
- for (const QString &optionalMethod : optionalMethods) {
- auto it = functionGroups.constFind(optionalMethod);
- if (it == functionGroups.cend() || it.value().size() != 1)
- throw Exception(msgCannotFindSmartPointerMethod(typeEntry, optionalMethod));
- writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
- }
-
- const QString methodsDefinitions = md.toString();
- const QString singleMethodDefinitions = smd.toString();
-
- const QString className = chopType(cpythonTypeName(typeEntry));
-
- writeCopyFunction(s, classContext);
- signatureStream << fullPythonClassName(metaClass) << ".__copy__()\n";
-
- // Write single method definitions
- s << singleMethodDefinitions;
-
- // Write methods definition
- writePyMethodDefs(s, className, methodsDefinitions, true /* ___copy__ */);
-
- // Write tp_s/getattro function
- const auto boolCastOpt = boolCast(metaClass);
- writeSmartPointerGetattroFunction(s, classContext, boolCastOpt);
- writeSmartPointerSetattroFunction(s, classContext);
-
- if (boolCastOpt.has_value())
- writeNbBoolFunction(classContext, boolCastOpt.value(), s);
-
- if (smartPointerType == TypeSystem::SmartPointerType::Shared)
- writeSmartPointerRichCompareFunction(s, classContext);
-
- s << closeExternC;
-
- if (hasHashFunction(metaClass))
- writeHashFunction(s, classContext);
-
- // Write tp_traverse and tp_clear functions.
- writeTpTraverseFunction(s, metaClass);
- writeTpClearFunction(s, metaClass);
-
- writeClassDefinition(s, metaClass, classContext);
-
- s << '\n';
-
- writeConverterFunctions(s, metaClass, classContext);
- writeClassRegister(s, metaClass, classContext, signatureStream);
-
- // class inject-code native/end
- if (!typeEntry->codeSnips().isEmpty()) {
- writeClassCodeSnips(s, typeEntry->codeSnips(),
- TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode,
- classContext);
- s << '\n';
- }
-}
-
void CppGenerator::writeMethodWrapper(TextStream &s, TextStream &definitionStream,
TextStream &signatureStream,
const AbstractMetaFunctionCList &overloads,
@@ -1996,45 +1847,6 @@ void CppGenerator::writeContainerConverterFunctions(TextStream &s,
writePythonToCppConversionFunctions(s, containerType);
}
-// Helpers to collect all smart pointer pointee base classes
-static AbstractMetaClassCList findSmartPointeeBaseClasses(const ApiExtractorResult &api,
- const AbstractMetaType &smartPointerType)
-{
- AbstractMetaClassCList result;
- auto instantiationsTe = smartPointerType.instantiations().at(0).typeEntry();
- auto targetClass = AbstractMetaClass::findClass(api.classes(), instantiationsTe);
- if (targetClass != nullptr)
- result = targetClass->allTypeSystemAncestors();
- return result;
-}
-
-void CppGenerator::writeSmartPointerConverterFunctions(TextStream &s,
- const AbstractMetaType &smartPointerType) const
-{
- const auto baseClasses = findSmartPointeeBaseClasses(api(), smartPointerType);
- if (baseClasses.isEmpty())
- return;
-
- auto smartPointerTypeEntry =
- std::static_pointer_cast<const SmartPointerTypeEntry>(smartPointerType.typeEntry());
-
- // TODO: Missing conversion to smart pointer pointer type:
-
- s << "// Register smartpointer conversion for all derived classes\n";
- for (const auto &base : baseClasses) {
- auto baseTe = base->typeEntry();
- if (smartPointerTypeEntry->matchesInstantiation(baseTe)) {
- if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
- const auto smartTargetType = opt.value();
- s << "// SmartPointer derived class: "
- << smartTargetType.cppSignature() << "\n";
- writePythonToCppConversionFunctions(s, smartPointerType,
- smartTargetType, {}, {}, {});
- }
- }
- }
-}
-
bool CppGenerator::needsArgumentErrorHandling(const OverloadData &overloadData)
{
if (overloadData.maxArgs() > 0)
@@ -2457,15 +2269,8 @@ void CppGenerator::writeCppSelfConversion(TextStream &s, const GeneratorContext
s << ')';
}
-void CppGenerator::writeSmartPointerCppSelfConversion(TextStream &s,
- const GeneratorContext &context)
-{
- Q_ASSERT(context.forSmartPointer());
- s << cpythonWrapperCPtr(context.preciseType(), u"self"_s);
-}
-
-static inline void writeCppSelfVarDef(TextStream &s,
- CppGenerator::CppSelfDefinitionFlags flags = {})
+void CppGenerator::writeCppSelfVarDef(TextStream &s,
+ CppSelfDefinitionFlags flags)
{
if (flags.testFlag(CppGenerator::CppSelfAsReference))
s << "auto &" << CPP_SELF_VAR << " = *";
@@ -2473,18 +2278,6 @@ static inline void writeCppSelfVarDef(TextStream &s,
s << "auto *" << CPP_SELF_VAR << " = ";
}
-void CppGenerator::writeSmartPointerCppSelfDefinition(TextStream &s,
- const GeneratorContext &context,
- ErrorReturn errorReturn,
- CppSelfDefinitionFlags flags)
-{
- Q_ASSERT(context.forSmartPointer());
- writeInvalidPyObjectCheck(s, u"self"_s, errorReturn);
- writeCppSelfVarDef(s, flags);
- writeSmartPointerCppSelfConversion(s, context);
- s << ";\n";
-}
-
void CppGenerator::writeCppSelfDefinition(TextStream &s,
const GeneratorContext &context,
ErrorReturn errorReturn,
@@ -4339,44 +4132,6 @@ QString CppGenerator::writeContainerConverterInitialization(TextStream &s,
return converter;
}
-void CppGenerator::writeSmartPointerConverterInitialization(TextStream &s, const AbstractMetaType &type) const
-{
- const QByteArray cppSignature = type.cppSignature().toUtf8();
- auto writeConversionRegister = [&s](const AbstractMetaType &sourceType, const QString &targetTypeName, const QString &targetConverter)
- {
- const QString sourceTypeName = fixedCppTypeName(sourceType);
- const QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
- const QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName);
-
- writeAddPythonToCppConversion(s, targetConverter, toCpp, isConv);
- };
-
- const auto classes = findSmartPointeeBaseClasses(api(), type);
- if (classes.isEmpty())
- return;
-
- auto smartPointerTypeEntry = std::static_pointer_cast<const SmartPointerTypeEntry>(type.typeEntry());
-
- s << "// Register SmartPointer converter for type '" << cppSignature << "'." << '\n'
- << "///////////////////////////////////////////////////////////////////////////////////////\n\n";
-
- for (const auto &base : classes) {
- auto baseTe = base->typeEntry();
- if (auto opt = findSmartPointerInstantiation(smartPointerTypeEntry, baseTe)) {
- const auto smartTargetType = opt.value();
- s << "// Convert to SmartPointer derived class: ["
- << smartTargetType.cppSignature() << "]\n";
- const QString converter = u"Shiboken::Conversions::getConverter(\""_s
- + smartTargetType.cppSignature() + u"\")"_s;
- writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter);
- } else {
- s << "// Class not found:" << type.instantiations().at(0).cppSignature();
- }
- }
-
- s << "///////////////////////////////////////////////////////////////////////////////////////" << '\n' << '\n';
-}
-
void CppGenerator::writeExtendedConverterInitialization(TextStream &s,
const TypeEntryCPtr &externalType,
const AbstractMetaClassCList &conversions)
@@ -5153,113 +4908,6 @@ void CppGenerator::writeRichCompareFunction(TextStream &s,
<< "}\n\n";
}
-using ComparisonOperatorList = QList<AbstractMetaFunction::ComparisonOperatorType>;
-
-// Return the available comparison operators for smart pointers
-static ComparisonOperatorList smartPointeeComparisons(const GeneratorContext &context)
-{
- Q_ASSERT(context.forSmartPointer());
- auto te = context.preciseType().instantiations().constFirst().typeEntry();
- if (isExtendedCppPrimitive(te)) { // Primitive pointee types have all
- return {AbstractMetaFunction::OperatorEqual,
- AbstractMetaFunction::OperatorNotEqual,
- AbstractMetaFunction::OperatorLess,
- AbstractMetaFunction::OperatorLessEqual,
- AbstractMetaFunction::OperatorGreater,
- AbstractMetaFunction::OperatorGreaterEqual};
- }
-
- const auto pointeeClass = context.pointeeClass();
- if (!pointeeClass)
- return {};
-
- ComparisonOperatorList result;
- const auto &comparisons =
- pointeeClass->operatorOverloads(OperatorQueryOption::SymmetricalComparisonOp);
- for (const auto &f : comparisons) {
- const auto ct = f->comparisonOperatorType().value();
- if (!result.contains(ct))
- result.append(ct);
- }
- return result;
-}
-
-void CppGenerator::writeSmartPointerRichCompareFunction(TextStream &s,
- const GeneratorContext &context) const
-{
- static const char selfPointeeVar[] = "cppSelfPointee";
- static const char cppArg0PointeeVar[] = "cppArg0Pointee";
-
- const auto metaClass = context.metaClass();
- QString baseName = cpythonBaseName(metaClass);
- writeRichCompareFunctionHeader(s, baseName, context);
-
- s << "if (";
- writeTypeCheck(s, context.preciseType(), PYTHON_ARG);
- s << ") {\n" << indent;
- writeArgumentConversion(s, context.preciseType(), CPP_ARG0,
- PYTHON_ARG, ErrorReturn::Default, metaClass);
-
- const auto te = context.preciseType().typeEntry();
- Q_ASSERT(te->isSmartPointer());
- const auto ste = std::static_pointer_cast<const SmartPointerTypeEntry>(te);
-
- s << "const auto *" << selfPointeeVar << " = " << CPP_SELF_VAR
- << '.' << ste->getter() << "();\n";
- s << "const auto *" << cppArg0PointeeVar << " = " << CPP_ARG0
- << '.' << ste->getter() << "();\n";
-
- // If we have an object without any comparisons, only generate a simple
- // equality check by pointee address
- auto availableOps = smartPointeeComparisons(context);
- const bool comparePointeeAddressOnly = availableOps.isEmpty();
- if (comparePointeeAddressOnly) {
- availableOps << AbstractMetaFunction::OperatorEqual
- << AbstractMetaFunction::OperatorNotEqual;
- } else {
- // For value types with operators, we complain about nullptr
- s << "if (" << selfPointeeVar << " == nullptr || " << cppArg0PointeeVar
- << " == nullptr) {\n" << indent
- << "PyErr_SetString(PyExc_NotImplementedError, \"nullptr passed to comparison.\");\n"
- << ErrorReturn::Default << '\n' << outdent << "}\n";
- }
-
- s << "bool " << CPP_RETURN_VAR << "= false;\n"
- << "switch (op) {\n";
- for (auto op : availableOps) {
- s << "case " << AbstractMetaFunction::pythonRichCompareOpCode(op) << ":\n"
- << indent << CPP_RETURN_VAR << " = ";
- if (comparePointeeAddressOnly) {
- s << selfPointeeVar << ' ' << AbstractMetaFunction::cppComparisonOperator(op)
- << ' ' << cppArg0PointeeVar << ";\n";
- } else {
- // Shortcut for equality: Check pointee address
- if (op == AbstractMetaFunction::OperatorEqual
- || op == AbstractMetaFunction::OperatorLessEqual
- || op == AbstractMetaFunction::OperatorGreaterEqual) {
- s << selfPointeeVar << " == " << cppArg0PointeeVar << " || ";
- }
- // Generate object's comparison
- s << "*" << selfPointeeVar << ' '
- << AbstractMetaFunction::cppComparisonOperator(op) << " *"
- << cppArg0PointeeVar << ";\n";
- }
- s << "break;\n" << outdent;
-
- }
- if (availableOps.size() < 6) {
- s << "default:\n" << indent
- << richCompareComment
- << "return FallbackRichCompare(self, " << PYTHON_ARG << ", op);\n" << outdent;
- }
- s << "}\n" << PYTHON_RETURN_VAR << " = " << CPP_RETURN_VAR
- << " ? Py_True : Py_False;\n"
- << "Py_INCREF(" << PYTHON_RETURN_VAR << ");\n"
- << outdent << "}\n"
- << "return Shiboken::returnFromRichCompare(" << PYTHON_RETURN_VAR << ");\n"
- << outdent << "}\n\n";
-}
-
// Return a flag combination for PyMethodDef
QByteArrayList CppGenerator::methodDefinitionParameters(const OverloadData &overloadData) const
{
@@ -6048,33 +5696,6 @@ void CppGenerator::writeSetattroFunction(TextStream &s, AttroCheck attroCheck,
writeSetattroDefaultReturn(s);
}
-static const char smartPtrComment[] =
- "// Try to find the 'name' attribute, by retrieving the PyObject for "
- "the corresponding C++ object held by the smart pointer.\n";
-
-static QString smartPointerGetter(const GeneratorContext &context)
-{
- const auto te = context.metaClass()->typeEntry();
- Q_ASSERT(te->isSmartPointer());
- return std::static_pointer_cast<const SmartPointerTypeEntry>(te)->getter();
-}
-
-void CppGenerator::writeSmartPointerSetattroFunction(TextStream &s,
- const GeneratorContext &context)
-{
- Q_ASSERT(context.forSmartPointer());
- writeSetattroDefinition(s, context.metaClass());
- s << smartPtrComment
- << "if (auto *rawObj = PyObject_CallMethod(self, \""
- << smartPointerGetter(context)
- << "\", 0)) {\n" << indent
- << "if (PyObject_HasAttr(rawObj, name) != 0)\n" << indent
- << "return PyObject_GenericSetAttr(rawObj, name, value);\n" << outdent
- << "Py_DECREF(rawObj);\n" << outdent
- << "}\n";
- writeSetattroDefaultReturn(s);
-}
-
void CppGenerator::writeGetattroDefinition(TextStream &s, const AbstractMetaClassCPtr &metaClass)
{
s << "static PyObject *" << cpythonGetattroFunctionName(metaClass)
@@ -6156,51 +5777,6 @@ void CppGenerator::writeGetattroFunction(TextStream &s, AttroCheck attroCheck,
s << "return " << getattrFunc << ";\n" << outdent << "}\n\n";
}
-void CppGenerator::writeSmartPointerGetattroFunction(TextStream &s,
- const GeneratorContext &context,
- const BoolCastFunctionOptional &boolCast)
-{
- Q_ASSERT(context.forSmartPointer());
- const auto metaClass = context.metaClass();
- writeGetattroDefinition(s, metaClass);
- s << "PyObject *tmp = PyObject_GenericGetAttr(self, name);\n"
- << "if (tmp)\n" << indent << "return tmp;\n" << outdent
- << "if (PyErr_ExceptionMatches(PyExc_AttributeError) == 0)\n"
- << indent << "return nullptr;\n" << outdent
- << "PyErr_Clear();\n";
-
- if (boolCast.has_value()) {
- writeSmartPointerCppSelfDefinition(s, context);
- s << "if (";
- writeNbBoolExpression(s, boolCast.value(), true /* invert */);
- s << ") {\n" << indent
- << R"(PyTypeObject *tp = Py_TYPE(self);
-PyErr_Format(PyExc_AttributeError, "Attempt to retrieve '%s' from null object '%s'.",
- Shiboken::String::toCString(name), tp->tp_name);
-return nullptr;
-)" << outdent << "}\n";
- }
-
- // This generates the code which dispatches access to member functions
- // and fields from the smart pointer to its pointee.
- s << smartPtrComment
- << "if (auto *rawObj = PyObject_CallMethod(self, \""
- << smartPointerGetter(context)
- << "\", 0)) {\n" << indent
- << "if (auto *attribute = PyObject_GetAttr(rawObj, name))\n"
- << indent << "tmp = attribute;\n" << outdent
- << "Py_DECREF(rawObj);\n" << outdent
- << "}\n"
- << "if (!tmp) {\n" << indent
- << R"(PyTypeObject *tp = Py_TYPE(self);
-PyErr_Format(PyExc_AttributeError,
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, Shiboken::String::toCString(name));
-)" << outdent
- << "}\n"
- << "return tmp;\n" << outdent << "}\n\n";
-}
-
void CppGenerator::writeNbBoolExpression(TextStream &s, const BoolCastFunction &f,
bool invert)
{