diff options
14 files changed, 258 insertions, 281 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 89a9a80c0..b0b449f0c 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -184,11 +184,12 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentMod AbstractMetaClass *currentClass) { AbstractMetaClass *returned = nullptr; - AbstractMetaType type = translateType(argument->type(), currentClass); - if (type && type.typeEntry() && type.typeEntry()->isComplex()) { - const TypeEntry *entry = type.typeEntry(); + auto type = translateType(argument->type(), currentClass); + if (!type.has_value()) + return returned; + const TypeEntry *entry = type->typeEntry(); + if (entry && entry->isComplex()) returned = AbstractMetaClass::findClass(m_metaClasses, entry); - } return returned; } @@ -252,8 +253,8 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte baseoperandClass = argumentToClass(arguments.at(1), currentClass); firstArgumentIsSelf = false; } else { - AbstractMetaType type = translateType(item->type(), currentClass); - const TypeEntry *retType = type ? type.typeEntry() : nullptr; + auto type = translateType(item->type(), currentClass); + const TypeEntry *retType = type.has_value() ? type->typeEntry() : nullptr; AbstractMetaClass *otherArgClass = argumentToClass(arguments.at(1), currentClass); if (otherArgClass && retType && (retType->isValue() || retType->isObject()) @@ -1158,9 +1159,9 @@ std::optional<AbstractMetaField> metaField.setEnclosingClass(cls); TypeInfo fieldType = field->type(); - AbstractMetaType metaType = translateType(fieldType, cls); + auto metaType = translateType(fieldType, cls); - if (!metaType) { + if (!metaType.has_value()) { const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); if (cls->typeEntry()->generateCode()) { qCWarning(lcShiboken, "%s", @@ -1169,7 +1170,7 @@ std::optional<AbstractMetaField> return {}; } - metaField.setType(metaType); + metaField.setType(metaType.value()); AbstractMetaAttributes::Attributes attr; if (field->isStatic()) @@ -1500,8 +1501,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu { QString errorMessage; - AbstractMetaType returnType = translateType(addedFunc->returnType(), metaClass, {}, &errorMessage); - if (!returnType) { + auto returnType = translateType(addedFunc->returnType(), metaClass, {}, &errorMessage); + if (!returnType.has_value()) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidReturnType(addedFunc->name(), addedFunc->returnType().qualifiedName(), @@ -1511,14 +1512,14 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu } auto metaFunction = new AbstractMetaFunction(addedFunc); - metaFunction->setType(returnType); + metaFunction->setType(returnType.value()); const auto &args = addedFunc->arguments(); for (int i = 0; i < args.count(); ++i) { const AddedFunction::Argument &arg = args.at(i); - AbstractMetaType type = translateType(arg.typeInfo, metaClass, {}, &errorMessage); - if (Q_UNLIKELY(!type)) { + auto type = translateType(arg.typeInfo, metaClass, {}, &errorMessage); + if (Q_UNLIKELY(!type.has_value())) { qCWarning(lcShiboken, "%s", qPrintable(msgAddedFunctionInvalidArgType(addedFunc->name(), arg.typeInfo.qualifiedName(), i + 1, @@ -1527,12 +1528,12 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu delete metaFunction; return nullptr; } - type.decideUsagePattern(); + type->decideUsagePattern(); AbstractMetaArgument metaArg; if (!args.at(i).name.isEmpty()) metaArg.setName(args.at(i).name); - metaArg.setType(type); + metaArg.setType(type.value()); metaArg.setArgumentIndex(i); metaArg.setDefaultValueExpression(arg.defaultValue); metaArg.setOriginalDefaultValueExpression(arg.defaultValue); @@ -1806,8 +1807,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return nullptr; } - AbstractMetaType type = translateType(returnType, currentClass, {}, &errorMessage); - if (!type) { + auto type = translateType(returnType, currentClass, {}, &errorMessage); + if (!type.has_value()) { const QString reason = msgUnmatchedReturnType(functionItem, errorMessage); qCWarning(lcShiboken, "%s", qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); @@ -1816,7 +1817,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return nullptr; } - metaFunction->setType(type); + metaFunction->setType(type.value()); } break; } @@ -1839,8 +1840,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return nullptr; } - AbstractMetaType metaType = translateType(arg->type(), currentClass, {}, &errorMessage); - if (!metaType) { + auto metaTypeO = translateType(arg->type(), currentClass, {}, &errorMessage); + if (!metaTypeO.has_value()) { // If an invalid argument has a default value, simply remove it // unless the function is virtual (since the override in the // wrapper can then not correctly be generated). @@ -1851,7 +1852,6 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } break; } - Q_ASSERT(!metaType); const QString reason = msgUnmatchedParameterType(arg, i, errorMessage); qCWarning(lcShiboken, "%s", qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); @@ -1862,6 +1862,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return nullptr; } + auto metaType = metaTypeO.value(); // Add view substitution for simple view types of function arguments // std::string_view -> std::string for foo(std::string_view) auto viewOnTypeEntry = metaType.typeEntry()->viewOn(); @@ -1897,7 +1898,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio AbstractMetaArgument &metaArg = metaArguments[i]; const QString originalDefaultExpression = - fixDefaultValue(arg, metaArg.type(), metaFunction, currentClass, i); + fixDefaultValue(arg, metaArg.type(), currentClass, i); metaArg.setOriginalDefaultValueExpression(originalDefaultExpression); metaArg.setDefaultValueExpression(originalDefaultExpression); @@ -2060,10 +2061,11 @@ const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(co return nullptr; } -AbstractMetaType AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass, - TranslateTypeFlags flags, - QString *errorMessage) +std::optional<AbstractMetaType> + AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, + AbstractMetaClass *currentClass, + TranslateTypeFlags flags, + QString *errorMessage) { return translateTypeStatic(_typei, currentClass, this, flags, errorMessage); } @@ -2074,11 +2076,12 @@ static bool isNumber(const QString &s) [](QChar c) { return c.isDigit(); }); } -AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, - AbstractMetaClass *currentClass, - AbstractMetaBuilderPrivate *d, - TranslateTypeFlags flags, - QString *errorMessageIn) +std::optional<AbstractMetaType> + AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d, + TranslateTypeFlags flags, + QString *errorMessageIn) { if (_typei.isVoid()) return AbstractMetaType::createVoid(); @@ -2087,11 +2090,11 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo // type system const bool resolveType = !flags.testFlag(AbstractMetaBuilder::DontResolveType); if (resolveType) { - AbstractMetaType resolved = + auto resolved = translateTypeStatic(_typei, currentClass, d, flags | AbstractMetaBuilder::DontResolveType, errorMessageIn); - if (resolved) + if (resolved.has_value()) return resolved; } @@ -2150,8 +2153,8 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo newInfo.setReferenceType(typeInfo.referenceType()); newInfo.setVolatile(typeInfo.isVolatile()); - AbstractMetaType elementType = translateTypeStatic(newInfo, currentClass, d, flags, &errorMessage); - if (!elementType) { + auto elementType = translateTypeStatic(newInfo, currentClass, d, flags, &errorMessage); + if (!elementType.has_value()) { if (errorMessageIn) { errorMessage.prepend(QLatin1String("Unable to translate array element: ")); *errorMessageIn = msgUnableToTranslateType(_typei, errorMessage); @@ -2161,7 +2164,7 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) { AbstractMetaType arrayType; - arrayType.setArrayElementType(elementType); + arrayType.setArrayElementType(elementType.value()); const QString &arrayElement = typeInfo.arrayElements().at(i); if (!arrayElement.isEmpty()) { bool _ok; @@ -2171,7 +2174,7 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo if (_ok) arrayType.setArrayElementCount(int(elems)); } - auto elementTypeEntry = elementType.typeEntry(); + auto elementTypeEntry = elementType->typeEntry(); arrayType.setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(), elementTypeEntry->parent())); arrayType.decideUsagePattern(); @@ -2221,10 +2224,10 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo const auto &templateArguments = typeInfo.instantiations(); for (int t = 0, size = templateArguments.size(); t < size; ++t) { const TypeInfo &ti = templateArguments.at(t); - AbstractMetaType targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); + auto targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage); // For non-type template parameters, create a dummy type entry on the fly // as is done for classes. - if (!targType) { + if (!targType.has_value()) { const QString value = ti.qualifiedName().join(colonColon()); if (isNumber(value)) { TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry()); @@ -2237,7 +2240,7 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo return {}; } - metaType.addInstantiation(targType); + metaType.addInstantiation(targType.value()); } if (typeEntryType == TypeEntry::SmartPointerType) { @@ -2283,24 +2286,25 @@ AbstractMetaType AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo } } - Q_ASSERT(metaType.typeUsagePattern() != AbstractMetaType::InvalidPattern); return metaType; } -AbstractMetaType AbstractMetaBuilder::translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass, - TranslateTypeFlags flags, - QString *errorMessage) +std::optional<AbstractMetaType> + AbstractMetaBuilder::translateType(const TypeInfo &_typei, + AbstractMetaClass *currentClass, + TranslateTypeFlags flags, + QString *errorMessage) { return AbstractMetaBuilderPrivate::translateTypeStatic(_typei, currentClass, nullptr, flags, errorMessage); } -AbstractMetaType AbstractMetaBuilder::translateType(const QString &t, - AbstractMetaClass *currentClass, - TranslateTypeFlags flags, - QString *errorMessageIn) +std::optional<AbstractMetaType> + AbstractMetaBuilder::translateType(const QString &t, + AbstractMetaClass *currentClass, + TranslateTypeFlags flags, + QString *errorMessageIn) { QString errorMessage; TypeInfo typeInfo = TypeParser::parse(t, &errorMessage); @@ -2355,7 +2359,6 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &item, const AbstractMetaType &type, - AbstractMetaFunction *fnc, AbstractMetaClass *implementingClass, int /* argumentIndex */) { @@ -2363,85 +2366,76 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &ite if (expr.isEmpty()) return expr; - if (type) { - if (type.isPrimitive()) { - if (type.name() == QLatin1String("boolean")) { - if (expr != QLatin1String("false") && expr != QLatin1String("true")) { - bool ok = false; - int number = expr.toInt(&ok); - if (ok && number) - expr = QLatin1String("true"); - else - expr = QLatin1String("false"); - } - } else { - // This can be an enum or flag so I need to delay the - // translation untill all namespaces are completly - // processed. This is done in figureOutEnumValues() - } - } else if (type.isFlags() || type.isEnum()) { - bool isNumber; - expr.toInt(&isNumber); - if (!isNumber && expr.indexOf(colonColon()) < 0) { - // Add the enum/flag scope to default value, making it usable - // from other contexts beside its owner class hierarchy - static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch match = typeRegEx.match(type.minimalSignature()); - if (match.hasMatch()) - expr.prepend(match.captured(1)); + if (type.isPrimitive()) { + if (type.name() == QLatin1String("boolean")) { + if (expr != QLatin1String("false") && expr != QLatin1String("true")) { + bool ok = false; + int number = expr.toInt(&ok); + if (ok && number) + expr = QLatin1String("true"); + else + expr = QLatin1String("false"); } - } else if (type.isContainer() && expr.contains(QLatin1Char('<'))) { - static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature()); - static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); - Q_ASSERT(defaultRegEx.isValid()); - const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); - if (typeMatch.hasMatch() && defaultMatch.hasMatch()) - expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); } else { - // Here the default value is supposed to be a constructor, - // a class field, or a constructor receiving a class field - static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)")); - Q_ASSERT(defaultRegEx.isValid()); - const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); - QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString(); - if (defaultValueCtorName.endsWith(QLatin1Char('('))) - defaultValueCtorName.chop(1); - - // Fix the scope for constructor using the already - // resolved argument type as a reference. - // The following regular expression extracts any - // use of namespaces/scopes from the type string. - static const QRegularExpression typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$")); + // This can be an enum or flag so I need to delay the + // translation until all namespaces are completely + // processed. This is done in figureOutEnumValues() + } + } else if (type.isFlags() || type.isEnum()) { + bool isNumber; + expr.toInt(&isNumber); + if (!isNumber && expr.indexOf(colonColon()) < 0) { + // Add the enum/flag scope to default value, making it usable + // from other contexts beside its owner class hierarchy + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*")); Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature()); - - QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString(); - QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString(); - if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) - expr.prepend(typeNamespace); - - // Fix scope if the parameter is a field of the current class - if (implementingClass) { - const AbstractMetaFieldList &fields = implementingClass->fields(); - for (const AbstractMetaField &field : fields) { - if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field.name()) { - expr = defaultMatch.captured(1) + implementingClass->name() - + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3); - break; - } + const QRegularExpressionMatch match = typeRegEx.match(type.minimalSignature()); + if (match.hasMatch()) + expr.prepend(match.captured(1)); + } + } else if (type.isContainer() && expr.contains(QLatin1Char('<'))) { + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature()); + static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + if (typeMatch.hasMatch() && defaultMatch.hasMatch()) + expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); + } else { + // Here the default value is supposed to be a constructor, + // a class field, or a constructor receiving a class field + static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString(); + if (defaultValueCtorName.endsWith(QLatin1Char('('))) + defaultValueCtorName.chop(1); + + // Fix the scope for constructor using the already resolved argument + // type as a reference. The following regular expression extracts any + // use of namespaces/scopes from the type string. + static const QRegularExpression + typeRegEx(QLatin1String(R"(^(?:const[\s]+|)([\w:]*::|)([A-Za-z_]\w*)\s*[&\*]?$)")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature()); + + QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString(); + QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString(); + if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) + expr.prepend(typeNamespace); + + // Fix scope if the parameter is a field of the current class + if (implementingClass) { + const AbstractMetaFieldList &fields = implementingClass->fields(); + for (const AbstractMetaField &field : fields) { + if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field.name()) { + expr = defaultMatch.captured(1) + implementingClass->name() + + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3); + break; } } } - } else { - const QString className = implementingClass ? implementingClass->qualifiedCppName() : QString(); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("undefined type for default value '%3' of argument in function '%1', class '%2'") - .arg(fnc->name(), className, item->defaultValueExpression()); - - expr.clear(); } return expr; @@ -2526,11 +2520,10 @@ bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const Abstrac return false; } -AbstractMetaType AbstractMetaBuilderPrivate::inheritTemplateType(const AbstractMetaTypeList &templateTypes, - const AbstractMetaType &metaType) +std::optional<AbstractMetaType> + AbstractMetaBuilderPrivate::inheritTemplateType(const AbstractMetaTypeList &templateTypes, + const AbstractMetaType &metaType) { - Q_ASSERT(metaType); - auto returned = metaType; if (!metaType.typeEntry()->isTemplateArgument() && !metaType.hasInstantiations()) @@ -2544,7 +2537,7 @@ AbstractMetaType AbstractMetaBuilderPrivate::inheritTemplateType(const AbstractM // If the template is intantiated with void we special case this as rejecting the functions that use this // parameter from the instantiation. const AbstractMetaType &templateType = templateTypes.value(tae->ordinal()); - if (!templateType || templateType.typeEntry()->isVoid()) + if (templateType.typeEntry()->isVoid()) return {}; AbstractMetaType t = returned; @@ -2558,10 +2551,10 @@ AbstractMetaType AbstractMetaBuilderPrivate::inheritTemplateType(const AbstractM if (returned.hasInstantiations()) { AbstractMetaTypeList instantiations = returned.instantiations(); for (int i = 0; i < instantiations.count(); ++i) { - instantiations[i] = - inheritTemplateType(templateTypes, instantiations.at(i)); - if (!instantiations.at(i)) + auto ins = inheritTemplateType(templateTypes, instantiations.at(i)); + if (!ins.has_value()) return {}; + instantiations[i] = ins.value(); } returned.setInstantiations(instantiations); } @@ -2655,19 +2648,19 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub f->setArguments(AbstractMetaArgumentList()); if (!function->isVoid()) { - AbstractMetaType returnType = inheritTemplateType(templateTypes, function->type()); - if (!returnType) + auto returnType = inheritTemplateType(templateTypes, function->type()); + if (!returnType.has_value()) continue; - f->setType(returnType); + f->setType(returnType.value()); } const AbstractMetaArgumentList &arguments = function->arguments(); for (const AbstractMetaArgument &argument : arguments) { - AbstractMetaType argType = inheritTemplateType(templateTypes, argument.type()); - if (!argType) + auto argType = inheritTemplateType(templateTypes, argument.type()); + if (!argType.has_value()) break; AbstractMetaArgument arg = argument; - arg.setType(argType); + arg.setType(argType.value()); f->addArgument(arg); } @@ -2738,10 +2731,10 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub AbstractMetaField f = field; f.setEnclosingClass(subclass); - AbstractMetaType fieldType = inheritTemplateType(templateTypes, field.type()); - if (!fieldType) + auto fieldType = inheritTemplateType(templateTypes, field.type()); + if (!fieldType.has_value()) continue; - f.setType(fieldType); + f.setType(fieldType.value()); subclass->addField(f); } } diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h index a11f2ec4f..45459a16e 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.h @@ -99,15 +99,12 @@ public: }; Q_DECLARE_FLAGS(TranslateTypeFlags, TranslateTypeFlag); - static AbstractMetaType translateType(const TypeInfo &_typei, - AbstractMetaClass *currentClass = nullptr, - TranslateTypeFlags flags = {}, - QString *errorMessage = nullptr); - static AbstractMetaType translateType(const QString &t, - AbstractMetaClass *currentClass = nullptr, - TranslateTypeFlags flags = {}, - QString *errorMessage = nullptr); - + static std::optional<AbstractMetaType> + translateType(const TypeInfo &_typei, AbstractMetaClass *currentClass = nullptr, + TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); + static std::optional<AbstractMetaType> + translateType(const QString &t, AbstractMetaClass *currentClass = nullptr, + TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index b943ad628..2789c88bd 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -144,18 +144,15 @@ public: void setupFunctionDefaults(AbstractMetaFunction *metaFunction, AbstractMetaClass *metaClass); - QString fixDefaultValue(const ArgumentModelItem &item, const AbstractMetaType &type, - AbstractMetaFunction *fnc, AbstractMetaClass *, + QString fixDefaultValue(const ArgumentModelItem &item, const AbstractMetaType &type, AbstractMetaClass *, int argumentIndex); - AbstractMetaType translateType(const TypeInfo &type, - AbstractMetaClass *currentClass, - TranslateTypeFlags flags = {}, - QString *errorMessage = nullptr); - static AbstractMetaType translateTypeStatic(const TypeInfo &type, - AbstractMetaClass *current, - AbstractMetaBuilderPrivate *d = nullptr, - TranslateTypeFlags flags = {}, - QString *errorMessageIn = nullptr); + std::optional<AbstractMetaType> + translateType(const TypeInfo &type, AbstractMetaClass *currentClass, + TranslateTypeFlags flags = {}, QString *errorMessage = nullptr); + static std::optional<AbstractMetaType> + translateTypeStatic(const TypeInfo &type, AbstractMetaClass *current, + AbstractMetaBuilderPrivate *d = nullptr, TranslateTypeFlags flags = {}, + QString *errorMessageIn = nullptr); static TypeEntries findTypeEntriesHelper(const QString &qualifiedName, const QString &name, AbstractMetaClass *currentClass = nullptr, AbstractMetaBuilderPrivate *d = nullptr); @@ -176,8 +173,9 @@ public: const AbstractMetaClass *templateClass, const TypeInfo &info); void inheritTemplateFunctions(AbstractMetaClass *subclass); - AbstractMetaType inheritTemplateType(const AbstractMetaTypeList &templateTypes, - const AbstractMetaType &metaType); + std::optional<AbstractMetaType> + inheritTemplateType(const AbstractMetaTypeList &templateTypes, + const AbstractMetaType &metaType); bool isQObject(const FileModelItem &dom, const QString &qualifiedName); bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName); diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp index 9e515d4b4..362ae22ef 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp @@ -67,7 +67,7 @@ public: AbstractMetaTypeCPtr m_viewOn; AbstractMetaType::Indirections m_indirections; - AbstractMetaType::TypeUsagePattern m_pattern = AbstractMetaType::InvalidPattern; + AbstractMetaType::TypeUsagePattern m_pattern = AbstractMetaType::VoidPattern; uint m_constant : 1; uint m_volatile : 1; uint m_signaturesDirty : 1; @@ -104,11 +104,6 @@ AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) = default; AbstractMetaType::~AbstractMetaType() = default; -bool AbstractMetaType::isValid() const -{ - return d->m_pattern != AbstractMetaType::InvalidPattern; -} - QString AbstractMetaType::package() const { return d->m_typeEntry->targetLangPackage(); @@ -685,10 +680,6 @@ AbstractMetaType AbstractMetaType::createVoid() #ifndef QT_NO_DEBUG_STREAM void AbstractMetaType::formatDebug(QDebug &debug) const { - if (!isValid()) { - debug << "Invalid"; - return; - } debug << '"' << name() << '"'; if (debug.verbosity() > 2) { auto te = typeEntry(); diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.h b/sources/shiboken6/ApiExtractor/abstractmetatype.h index c92a7652a..e321ad546 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.h +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.h @@ -48,7 +48,6 @@ public: using Indirections = QVector<Indirection>; enum TypeUsagePattern { - InvalidPattern, PrimitivePattern, FlagsPattern, EnumPattern, @@ -75,9 +74,6 @@ public: AbstractMetaType &operator=(AbstractMetaType &&); ~AbstractMetaType(); - bool isValid() const; - operator bool() const { return isValid(); } - QString package() const; QString name() const; QString fullName() const; diff --git a/sources/shiboken6/ApiExtractor/propertyspec.cpp b/sources/shiboken6/ApiExtractor/propertyspec.cpp index fb45830b1..f66eeeaf6 100644 --- a/sources/shiboken6/ApiExtractor/propertyspec.cpp +++ b/sources/shiboken6/ApiExtractor/propertyspec.cpp @@ -272,8 +272,8 @@ std::optional<QPropertySpec> return {}; } - AbstractMetaType type = b->translateType(info, metaClass, {}, &typeError); - if (!type) { + auto type = b->translateType(info, metaClass, {}, &typeError); + if (!type.has_value()) { const QStringList qualifiedName = info.qualifiedName(); for (int j = scopes.size(); j >= 0 && !type; --j) { info.setQualifiedName(scopes.mid(0, j) + qualifiedName); @@ -281,11 +281,11 @@ std::optional<QPropertySpec> } } - if (!type) { + if (!type.has_value()) { *errorMessage = msgPropertyTypeParsingFailed(ts.name, ts.type, typeError); return {}; } - return QPropertySpec(ts, type); + return QPropertySpec(ts, type.value()); } // Convenience to create a QPropertySpec from a Q_PROPERTY macro diff --git a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp index 0fab1bf07..e65b0f214 100644 --- a/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testabstractmetatype.cpp @@ -77,7 +77,7 @@ void TestAbstractMetaType::testConstCharPtrType() AbstractMetaFunction *func = builder->globalFunctions().constFirst(); AbstractMetaType rtype = func->type(); // Test properties of const char* - QVERIFY(rtype); + QVERIFY(!rtype.isVoid()); QCOMPARE(rtype.package(), QLatin1String("Foo")); QCOMPARE(rtype.name(), QLatin1String("char")); QVERIFY(rtype.isConstant()); @@ -150,7 +150,7 @@ void TestAbstractMetaType::testCharType() AbstractMetaFunction *func = functions.constFirst(); AbstractMetaType rtype = func->type(); // Test properties of const char* - QVERIFY(rtype); + QVERIFY(!rtype.isVoid()); QCOMPARE(rtype.package(), QLatin1String("Foo")); QCOMPARE(rtype.name(), QLatin1String("char")); QVERIFY(!rtype.isConstant()); diff --git a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp index 515eb520e..3ee39e4ec 100644 --- a/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testcontainer.cpp @@ -94,7 +94,6 @@ void TestContainer::testListOfValueType() QCOMPARE(classA->templateBaseClassInstantiations().count(), 1); const AbstractMetaType templateInstanceType = classA->templateBaseClassInstantiations().constFirst(); - QVERIFY(templateInstanceType); QCOMPARE(templateInstanceType.indirections(), 0); QVERIFY(!templateInstanceType.typeEntry()->isObject()); diff --git a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp index 54984620b..d613074fe 100644 --- a/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testnumericaltypedef.cpp @@ -62,13 +62,11 @@ void TestNumericalTypedef::testNumericalTypedef() QCOMPARE(funcReal->minimalSignature(), QLatin1String("funcReal(real)")); const AbstractMetaType doubleType = funcDouble->arguments().constFirst().type(); - QVERIFY(doubleType); QCOMPARE(doubleType.cppSignature(), QLatin1String("double")); QVERIFY(doubleType.isPrimitive()); QVERIFY(doubleType.typeEntry()->isCppPrimitive()); const AbstractMetaType realType = funcReal->arguments().constFirst().type(); - QVERIFY(realType); QCOMPARE(realType.cppSignature(), QLatin1String("real")); QVERIFY(realType.isPrimitive()); QVERIFY(realType.typeEntry()->isCppPrimitive()); @@ -104,13 +102,11 @@ void TestNumericalTypedef::testUnsignedNumericalTypedef() QCOMPARE(funcUShort->minimalSignature(), QLatin1String("funcUShort(custom_ushort)")); const AbstractMetaType unsignedShortType = funcUnsignedShort->arguments().constFirst().type(); - QVERIFY(unsignedShortType); QCOMPARE(unsignedShortType.cppSignature(), QLatin1String("unsigned short")); QVERIFY(unsignedShortType.isPrimitive()); QVERIFY(unsignedShortType.typeEntry()->isCppPrimitive()); const AbstractMetaType ushortType = funcUShort->arguments().constFirst().type(); - QVERIFY(ushortType); QCOMPARE(ushortType.cppSignature(), QLatin1String("custom_ushort")); QVERIFY(ushortType.isPrimitive()); QVERIFY(ushortType.typeEntry()->isCppPrimitive()); diff --git a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp index 38199a869..2ddccc900 100644 --- a/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken6/ApiExtractor/tests/testtemplates.cpp @@ -79,7 +79,7 @@ namespace Internet { QVERIFY(classB); const AbstractMetaFunction* func = classB->findFunction(QLatin1String("list")); AbstractMetaType funcType = func->type(); - QVERIFY(funcType); + QVERIFY(!funcType.isVoid()); QCOMPARE(funcType.cppSignature(), QLatin1String("QList<Internet::Url >")); } @@ -397,7 +397,6 @@ typedef BaseTemplateClass<TypeOne> TypeOneClass; AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); QCOMPARE(instantiations.count(), 1); const AbstractMetaType &inst = instantiations.constFirst(); - QVERIFY(inst); QVERIFY(!inst.isEnum()); QVERIFY(!inst.typeEntry()->isEnum()); QVERIFY(inst.typeEntry()->isEnumValue()); @@ -446,7 +445,7 @@ typedef Vector<int> IntVector; const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod")); QVERIFY(otherMethod); QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()")); - QVERIFY(otherMethod->type()); + QVERIFY(!otherMethod->type().isVoid()); QCOMPARE(otherMethod->type().cppSignature(), QLatin1String("Vector<int >")); } diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index b3759df61..0fd59b1b7 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -90,7 +90,7 @@ static const char *typeNameOf(const T &t) // utility functions inline AbstractMetaType getTypeWithoutContainer(const AbstractMetaType &arg) { - if (arg && arg.typeEntry()->isContainer()) { + if (arg.typeEntry()->isContainer()) { // only support containers with 1 type if (arg.instantiations().size() == 1) return arg.instantiations().constFirst(); @@ -261,7 +261,8 @@ const AbstractMetaFunction *CppGenerator::boolCast(const AbstractMetaClass *meta && func->arguments().isEmpty() ? func : nullptr; } -AbstractMetaType CppGenerator::findSmartPointerInstantiation(const TypeEntry *entry) const +std::optional<AbstractMetaType> + CppGenerator::findSmartPointerInstantiation(const TypeEntry *entry) const { for (const auto &i : instantiatedSmartPointers()) { if (i.instantiations().at(0).typeEntry() == entry) @@ -574,11 +575,11 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo // @TODO: This possibly leaks, but there are a bunch of other places where this // is done, so this will be fixed in bulk with all the other cases, because the // ownership of the pointers is not clear at the moment. - AbstractMetaType pointerToInnerType = + auto pointerToInnerType = buildAbstractMetaTypeFromString(pointerToInnerTypeName); - + Q_ASSERT(pointerToInnerType.has_value()); AbstractMetaFunction *mutableRfunc = overloads.constFirst(); - mutableRfunc->setType(pointerToInnerType); + mutableRfunc->setType(pointerToInnerType.value()); } else if (smartPointerTypeEntry->refCountMethodName().isEmpty() || smartPointerTypeEntry->refCountMethodName() != rfunc->name()) { // Skip all public methods of the smart pointer except for the raw getter and @@ -834,7 +835,7 @@ static bool allArgumentsRemoved(const AbstractMetaFunction *func) QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunction *func) { - if (!func->type()) + if (func->type().isVoid()) return QLatin1String("\"\""); if (!func->typeReplaced(0).isEmpty()) @@ -1780,8 +1781,9 @@ void CppGenerator::writeSmartPointerConverterFunctions(QTextStream &s, const Abs for (auto k : classes) { if (smartPointerTypeEntry->matchesInstantiation(k->typeEntry())) { if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry())) { - s << INDENT << "// SmartPointer derived class: " << smartTargetType.cppSignature() << "\n"; - writePythonToCppConversionFunctions(s, smartPointerType, smartTargetType, {}, {}, {}); + s << INDENT << "// SmartPointer derived class: " + << smartTargetType->cppSignature() << "\n"; + writePythonToCppConversionFunctions(s, smartPointerType, smartTargetType.value(), {}, {}, {}); } } } @@ -2359,9 +2361,10 @@ void CppGenerator::writeTypeCheck(QTextStream &s, AbstractMetaType argType, AbstractMetaType metaType; // PYSIDE-795: Note: XML-Overrides are handled in this shibokengenerator function! // This enables iterables for QMatrix4x4 for instance. - customCheck = guessCPythonCheckFunction(customType, &metaType); - if (metaType) - argType = metaType; + auto customCheckResult = guessCPythonCheckFunction(customType); + customCheck = customCheckResult.checkFunction; + if (customCheckResult.type.has_value()) + argType = customCheckResult.type.value(); } // TODO-CONVERTER: merge this with the code below. @@ -2388,8 +2391,7 @@ void CppGenerator::writeTypeCheck(QTextStream &s, AbstractMetaType argType, static void checkTypeViability(const AbstractMetaFunction *func, const AbstractMetaType &type, int argIdx) { - if (!type - || type.isVoid() + if (type.isVoid() || !type.typeEntry()->isPrimitive() || type.indirections() == 0 || (type.indirections() == 1 && type.typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern) @@ -2467,7 +2469,8 @@ void CppGenerator::writeArgumentConversion(QTextStream &s, writeUnusedVariableCast(s, argName); } -const AbstractMetaType CppGenerator::getArgumentType(const AbstractMetaFunction *func, int argPos) +std::optional<AbstractMetaType> + CppGenerator::getArgumentType(const AbstractMetaFunction *func, int argPos) { if (argPos < 0 || argPos > func->arguments().size()) { qCWarning(lcShiboken).noquote().nospace() @@ -2484,7 +2487,7 @@ const AbstractMetaType CppGenerator::getArgumentType(const AbstractMetaFunction } auto argType = buildAbstractMetaTypeFromString(typeReplaced); - if (!argType && !m_knownPythonTypes.contains(typeReplaced)) { + if (!argType.has_value() && !m_knownPythonTypes.contains(typeReplaced)) { qCWarning(lcShiboken).noquote().nospace() << QString::fromLatin1("Unknown type '%1' used as argument type replacement "\ "in function '%2', the generated code may be broken.") @@ -2947,14 +2950,16 @@ void CppGenerator::writeSingleFunctionCall(QTextStream &s, } if (hasConversionRule) continue; - const AbstractMetaType argType = getArgumentType(func, argIdx + 1); - if (!argType || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx))) + auto argType = getArgumentType(func, argIdx + 1); + if (!argType.has_value() || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx))) continue; int argPos = argIdx - removedArgs; QString argName = QLatin1String(CPP_ARG) + QString::number(argPos); QString pyArgName = usePyArgs ? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG); QString defaultValue = guessScopeForDefaultValue(func, arg); - writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded()); + writeArgumentConversion(s, argType.value(), argName, pyArgName, + func->implementingClass(), defaultValue, + func->isUserAdded()); } s << Qt::endl; @@ -3329,18 +3334,15 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction *func, in } else { int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); AbstractMetaType argType = getTypeWithoutContainer(func->arguments().at(realIndex).type()); - - if (argType) { - *wrappedClass = AbstractMetaClass::findClass(classes(), argType.typeEntry()); - if (*wrappedClass == nullptr && errorMessage != nullptr) - *errorMessage = msgClassNotFound(argType.typeEntry()); - if (argIndex == 1 - && !func->isConstructor() - && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) - pyArgName = QLatin1String(PYTHON_ARG); - else - pyArgName = pythonArgsAt(argIndex - 1); - } + *wrappedClass = AbstractMetaClass::findClass(classes(), argType.typeEntry()); + if (*wrappedClass == nullptr && errorMessage != nullptr) + *errorMessage = msgClassNotFound(argType.typeEntry()); + if (argIndex == 1 + && !func->isConstructor() + && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) + pyArgName = QLatin1String(PYTHON_ARG); + else + pyArgName = pythonArgsAt(argIndex - 1); } return pyArgName; } @@ -4040,11 +4042,13 @@ void CppGenerator::writeSmartPointerConverterInitialization(QTextStream &s, cons s << Qt::endl; for (auto k : classes) { - if (auto smartTargetType = findSmartPointerInstantiation(k->typeEntry())) - { - s << INDENT << "// Convert to SmartPointer derived class: [" << smartTargetType.cppSignature() << "]\n"; - const QString converter = QLatin1String("Shiboken::Conversions::getConverter(\"%1\")").arg(smartTargetType.cppSignature()); - writeConversionRegister(type, fixedCppTypeName(smartTargetType), converter); + auto smartTargetType = findSmartPointerInstantiation(k->typeEntry()); + if (smartTargetType.has_value()) { + s << INDENT << "// Convert to SmartPointer derived class: [" + << smartTargetType->cppSignature() << "]\n"; + const QString converter = + QLatin1String("Shiboken::Conversions::getConverter(\"%1\")").arg(smartTargetType->cppSignature()); + writeConversionRegister(type, fixedCppTypeName(smartTargetType.value()), converter); } else { s << INDENT << "// Class not found:" << type.instantiations().at(0).cppSignature(); } @@ -4790,9 +4794,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, const GeneratorConte const AbstractMetaFunction *func = od->referenceFunction(); if (func->isStatic()) continue; - const AbstractMetaType argType = getArgumentType(func, 1); - if (!argType) + auto argTypeO = getArgumentType(func, 1); + if (!argTypeO.has_value()) continue; + auto argType = argTypeO.value(); if (!first) { s << " else "; } else { diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 276759f7f..22f93e12f 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -155,7 +155,8 @@ private: * \param newType It is set to true if the type returned is a new object that must be deallocated. * \return The type of the argument indicated by \p argPos. */ - const AbstractMetaType getArgumentType(const AbstractMetaFunction *func, int argPos); + std::optional<AbstractMetaType> + getArgumentType(const AbstractMetaFunction *func, int argPos); void writePythonToCppTypeConversion(QTextStream &s, const AbstractMetaType &type, @@ -380,7 +381,8 @@ private: bool hasBoolCast(const AbstractMetaClass *metaClass) const { return boolCast(metaClass) != nullptr; } - AbstractMetaType findSmartPointerInstantiation(const TypeEntry *entry) const; + std::optional<AbstractMetaType> + findSmartPointerInstantiation(const TypeEntry *entry) const; // Number protocol structure members names. static QHash<QString, QString> m_nbFuncs; diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index b8e31d8d5..aa2b551c7 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -1181,14 +1181,12 @@ bool ShibokenGenerator::isNullPtr(const QString &value) QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType, bool genericNumberType) { - QString customCheck; if (metaType.typeEntry()->isCustom()) { - AbstractMetaType type; - customCheck = guessCPythonCheckFunction(metaType.typeEntry()->name(), &type); - if (type) - metaType = type; - if (!customCheck.isEmpty()) - return customCheck; + auto customCheckResult = guessCPythonCheckFunction(metaType.typeEntry()->name()); + if (!customCheckResult.checkFunction.isEmpty()) + return customCheckResult.checkFunction; + if (customCheckResult.type.has_value()) + metaType = customCheckResult.type.value(); } if (isCppPrimitive(metaType)) { @@ -1246,15 +1244,12 @@ QString ShibokenGenerator::cpythonCheckFunction(AbstractMetaType metaType, bool QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type, bool genericNumberType) { - QString customCheck; if (type->isCustom()) { AbstractMetaType metaType; - customCheck = guessCPythonCheckFunction(type->name(), &metaType); - if (metaType) { - const QString result = cpythonCheckFunction(metaType, genericNumberType); - return result; - } - return customCheck; + auto customCheckResult = guessCPythonCheckFunction(type->name()); + if (customCheckResult.type.has_value()) + return cpythonCheckFunction(customCheckResult.type.value(), genericNumberType); + return customCheckResult.checkFunction; } if (type->isEnum() || type->isFlags() || isWrapperType(type)) @@ -1273,28 +1268,28 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry *type, bool gene return typeCheck; } -QString ShibokenGenerator::guessCPythonCheckFunction(const QString &type, AbstractMetaType *metaType) +ShibokenGenerator::CPythonCheckFunctionResult + ShibokenGenerator::guessCPythonCheckFunction(const QString &type) { - *metaType = {}; // PYSIDE-795: We abuse PySequence for iterables. // This part handles the overrides in the XML files. if (type == QLatin1String("PySequence")) - return QLatin1String("Shiboken::String::checkIterable"); + return {QLatin1String("Shiboken::String::checkIterable"), {}}; if (type == QLatin1String("PyTypeObject")) - return QLatin1String("PyType_Check"); + return {QLatin1String("PyType_Check"), {}}; if (type == QLatin1String("PyBuffer")) - return QLatin1String("Shiboken::Buffer::checkType"); + return {QLatin1String("Shiboken::Buffer::checkType"), {}}; if (type == QLatin1String("str")) - return QLatin1String("Shiboken::String::check"); - - *metaType = buildAbstractMetaTypeFromString(type); - if (*metaType && !metaType->typeEntry()->isCustom()) - return QString(); + return {QLatin1String("Shiboken::String::check"), {}}; - return type + QLatin1String("_Check"); + CPythonCheckFunctionResult result; + result.type = buildAbstractMetaTypeFromString(type); + if (!result.type.has_value() || result.type->typeEntry()->isCustom()) + result.checkFunction = type + QLatin1String("_Check"); + return result; } QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry *type, @@ -1316,14 +1311,12 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry *type, QString ShibokenGenerator::cpythonIsConvertibleFunction(AbstractMetaType metaType, bool /* genericNumberType */) { - QString customCheck; if (metaType.typeEntry()->isCustom()) { - AbstractMetaType type; - customCheck = guessCPythonCheckFunction(metaType.typeEntry()->name(), &type); - if (type) - metaType = type; - if (!customCheck.isEmpty()) - return customCheck; + auto customCheckResult = guessCPythonCheckFunction(metaType.typeEntry()->name()); + if (!customCheckResult.checkFunction.isEmpty()) + return customCheckResult.checkFunction; + if (customCheckResult.type.has_value()) + metaType = customCheckResult.type.value(); } QString result = QLatin1String("Shiboken::Conversions::"); @@ -1750,9 +1743,9 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl AbstractMetaType type = arg.type(); QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1); if (!typeReplaced.isEmpty()) { - AbstractMetaType builtType = buildAbstractMetaTypeFromString(typeReplaced); - if (builtType) - type = builtType; + auto builtType = buildAbstractMetaTypeFromString(typeReplaced); + if (builtType.has_value()) + type = builtType.value(); } if (type.typeEntry()->isCustom()) { argValue = usePyArgs @@ -1972,9 +1965,9 @@ void ShibokenGenerator::writeCodeSnips(QTextStream &s, AbstractMetaType type = arg.type(); QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1); if (!typeReplaced.isEmpty()) { - AbstractMetaType builtType = buildAbstractMetaTypeFromString(typeReplaced); - if (builtType) - type = builtType; + auto builtType = buildAbstractMetaTypeFromString(typeReplaced); + if (builtType.has_value()) + type = builtType.value(); } if (isWrapperType(type)) { QString replacement = pair.second; @@ -2098,12 +2091,13 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa QString conversionString = list.constFirst(); const QString &conversionTypeName = list.constLast(); QString message; - const AbstractMetaType conversionType = buildAbstractMetaTypeFromString(conversionTypeName, &message); - if (!conversionType) { + const auto conversionTypeO = buildAbstractMetaTypeFromString(conversionTypeName, &message); + if (!conversionTypeO.has_value()) { qFatal("%s", qPrintable(msgCannotFindType(conversionTypeName, m_typeSystemConvName[converterVariable], message))); } + const auto conversionType = conversionTypeO.value(); QString conversion; QTextStream c(&conversion); switch (converterVariable) { @@ -2397,8 +2391,9 @@ bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) return metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet; } -AbstractMetaType ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature, - QString *errorMessage) +std::optional<AbstractMetaType> + ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature, + QString *errorMessage) { typeSignature = typeSignature.trimmed(); if (typeSignature.startsWith(QLatin1String("::"))) @@ -2406,14 +2401,14 @@ AbstractMetaType ShibokenGenerator::buildAbstractMetaTypeFromString(QString type auto it = m_metaTypeFromStringCache.find(typeSignature); if (it == m_metaTypeFromStringCache.end()) { - AbstractMetaType metaType = + auto metaType = AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage); - if (Q_UNLIKELY(!metaType)) { + if (Q_UNLIKELY(!metaType.has_value())) { if (errorMessage) errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); return {}; } - it = m_metaTypeFromStringCache.insert(typeSignature, metaType); + it = m_metaTypeFromStringCache.insert(typeSignature, metaType.value()); } return it.value(); } @@ -2688,9 +2683,9 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString & start += offset; if (code.at(start) != QLatin1Char('%')) { QString typeString = code.mid(start, end - start); - if (AbstractMetaType type = - buildAbstractMetaTypeFromString(typeString, &errorMessage)) { - addInstantiatedContainersAndSmartPointers(type, type.originalTypeDescription()); + auto type = buildAbstractMetaTypeFromString(typeString, &errorMessage); + if (type.has_value()) { + addInstantiatedContainersAndSmartPointers(type.value(), type->originalTypeDescription()); } else { qFatal("%s: Cannot translate type \"%s\": %s", __FUNCTION__, qPrintable(typeString), qPrintable(errorMessage)); diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h index 55d8c00db..8384dbfcd 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.h +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h @@ -327,7 +327,12 @@ protected: * \return A custom check if \p type is a custom type, or an empty string if \p metaType * receives an existing type object. */ - QString guessCPythonCheckFunction(const QString &type, AbstractMetaType *metaType); + struct CPythonCheckFunctionResult + { + QString checkFunction; + std::optional<AbstractMetaType> type; + }; + CPythonCheckFunctionResult guessCPythonCheckFunction(const QString &type); QString cpythonIsConvertibleFunction(const TypeEntry *type, bool genericNumberType = false, bool checkExact = false); QString cpythonIsConvertibleFunction(AbstractMetaType metaType, bool genericNumberType = false); QString cpythonIsConvertibleFunction(const AbstractMetaArgument &metaArg, bool genericNumberType = false); @@ -408,8 +413,9 @@ protected: * \return A new AbstractMetaType object that must be deleted by the caller, * or a nullptr pointer in case of failure. */ - AbstractMetaType buildAbstractMetaTypeFromString(QString typeSignature, - QString *errorMessage = nullptr); + std::optional<AbstractMetaType> + buildAbstractMetaTypeFromString(QString typeSignature, + QString *errorMessage = nullptr); /// Creates an AbstractMetaType object from a TypeEntry. AbstractMetaType buildAbstractMetaTypeFromTypeEntry(const TypeEntry *typeEntry); |