diff options
11 files changed, 348 insertions, 191 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index c6b50a94e..5e914a989 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ @@ -284,7 +284,6 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte metaFunction->setArguments(arguments); metaFunction->setReverseOperator(true); } - metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); metaFunction->setVisibility(AbstractMetaFunction::Public); metaFunction->setOriginalAttributes(metaFunction->attributes()); setupFunctionDefaults(metaFunction, baseoperandClass); @@ -296,57 +295,54 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } } -void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item, +bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item, AbstractMetaClass *currentClass) { - ArgumentList arguments = item->arguments(); - if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) { - AbstractMetaClass *streamClass = argumentToClass(arguments.at(0), currentClass); - AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1), currentClass); - - if (streamClass && streamedClass && (streamClass->isStream())) { - AbstractMetaFunction *streamFunction = traverseFunction(item, streamedClass); - - if (streamFunction) { - // Strip first argument, since that is the containing object - AbstractMetaArgumentList arguments = streamFunction->arguments(); - if (!streamClass->typeEntry()->generateCode()) - arguments.takeLast(); - else - arguments.takeFirst(); - - streamFunction->setArguments(arguments); - - *streamFunction += AbstractMetaAttributes::FinalInTargetLang; - *streamFunction += AbstractMetaAttributes::Public; - streamFunction->setOriginalAttributes(streamFunction->attributes()); - -// streamFunction->setType(0); - - AbstractMetaClass *funcClass; + ArgumentList itemArguments = item->arguments(); + if (itemArguments.size() != 2 || item->accessPolicy() != CodeModel::Public) + return false; + auto streamClass = argumentToClass(itemArguments.at(0), currentClass); + if (streamClass == nullptr || !streamClass->isStream()) + return false; + auto streamedClass = argumentToClass(itemArguments.at(1), currentClass); + if (streamedClass == nullptr) + return false; + + AbstractMetaFunction *streamFunction = traverseFunction(item, streamedClass); + if (!streamFunction) + return false; + + // Strip first argument, since that is the containing object + AbstractMetaArgumentList arguments = streamFunction->arguments(); + if (!streamClass->typeEntry()->generateCode()) + arguments.takeLast(); + else + arguments.takeFirst(); - if (!streamClass->typeEntry()->generateCode()) { - AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments()); - streamFunction->setArguments(reverseArgs); - streamFunction->setReverseOperator(true); - funcClass = streamedClass; - } else { - funcClass = streamClass; - } + streamFunction->setArguments(arguments); - setupFunctionDefaults(streamFunction, funcClass); - funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction)); - if (funcClass == streamClass) - funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include()); - else - funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); + *streamFunction += AbstractMetaAttributes::FinalInTargetLang; + *streamFunction += AbstractMetaAttributes::Public; + streamFunction->setOriginalAttributes(streamFunction->attributes()); - } else { - delete streamFunction; - } + AbstractMetaClass *funcClass; - } + if (!streamClass->typeEntry()->generateCode()) { + AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments()); + streamFunction->setArguments(reverseArgs); + streamFunction->setReverseOperator(true); + funcClass = streamedClass; + } else { + funcClass = streamClass; } + + setupFunctionDefaults(streamFunction, funcClass); + funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction)); + if (funcClass == streamClass) + funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include()); + else + funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); + return true; } void AbstractMetaBuilderPrivate::sortLists() @@ -542,39 +538,20 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) registerToStringCapabilityIn(dom); - { - FunctionList binaryOperators = dom->findFunctions(QStringLiteral("operator==")); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator!="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator<="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator>="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator<"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator+"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator/"))); - // Filter binary operators, skipping for example - // class Iterator { ... Value *operator*() ... }; - const FunctionList potentiallyBinaryOperators = - dom->findFunctions(QStringLiteral("operator*")) - + dom->findFunctions(QStringLiteral("operator&")); - for (const FunctionModelItem &item : potentiallyBinaryOperators) { - if (!item->arguments().isEmpty()) - binaryOperators.append(item); - } - binaryOperators.append(dom->findFunctions(QStringLiteral("operator-"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator&"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator|"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator^"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator~"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator>"))); - - for (const FunctionModelItem &item : qAsConst(binaryOperators)) - traverseOperatorFunction(item, nullptr); - } - - { - const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) - + dom->findFunctions(QLatin1String("operator>>")); - for (const FunctionModelItem &item : streamOperators) - traverseStreamOperator(item, nullptr); + for (const auto &func : dom->functions()) { + switch (func->functionType()) { + case CodeModel::ComparisonOperator: + case CodeModel::ArithmeticOperator: + case CodeModel::BitwiseOperator: + case CodeModel::LogicalOperator: + traverseOperatorFunction(func, nullptr); + break; + case CodeModel::ShiftOperator: + if (!traverseStreamOperator(func, nullptr)) + traverseOperatorFunction(func, nullptr); + default: + break; + } } ReportHandler::startProgress("Checking inconsistencies in function modifications..."); @@ -1553,12 +1530,13 @@ static void applyDefaultExpressionModifications(const FunctionModificationList & } } +static AbstractMetaFunction::FunctionType functionTypeFromName(const QString &); + bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunctionPtr &addedFunc) { AbstractMetaFunction *metaFunction = traverseAddedFunctionHelper(addedFunc); if (metaFunction == nullptr) return false; - metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); m_globalFunctions << AbstractMetaFunctionCPtr(metaFunction); return true; } @@ -1581,6 +1559,7 @@ AbstractMetaFunction * auto metaFunction = new AbstractMetaFunction(addedFunc); metaFunction->setType(returnType.value()); + metaFunction->setFunctionType(functionTypeFromName(addedFunc->name())); const auto &args = addedFunc->arguments(); @@ -1666,13 +1645,6 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction if (te->name() == metaFunction->name()) metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); } - } else { - auto type = AbstractMetaFunction::NormalFunction; - if (metaFunction->name() == QLatin1String("__getattro__")) - type = AbstractMetaFunction::GetAttroFunction; - else if (metaFunction->name() == QLatin1String("__setattro__")) - type = AbstractMetaFunction::SetAttroFunction; - metaFunction->setFunctionType(type); } metaFunction->setDeclaringClass(metaClass); @@ -1733,6 +1705,42 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM case CodeModel::Destructor: result = AbstractMetaFunction::DestructorFunction; break; + case CodeModel::AssignmentOperator: + result = AbstractMetaFunction::AssignmentOperatorFunction; + break; + case CodeModel::CallOperator: + result = AbstractMetaFunction::CallOperator; + break; + case CodeModel::ConversionOperator: + result = AbstractMetaFunction::ConversionOperator; + break; + case CodeModel::DereferenceOperator: + result = AbstractMetaFunction::DereferenceOperator; + break; + case CodeModel::ReferenceOperator: + result = AbstractMetaFunction::ReferenceOperator; + break; + case CodeModel::ArrowOperator: + result = AbstractMetaFunction::ArrowOperator; + break; + case CodeModel::ArithmeticOperator: + result = AbstractMetaFunction::ArithmeticOperator; + break; + case CodeModel::BitwiseOperator: + result = AbstractMetaFunction::BitwiseOperator; + break; + case CodeModel::LogicalOperator: + result = AbstractMetaFunction::LogicalOperator; + break; + case CodeModel::ShiftOperator: + result = AbstractMetaFunction::ShiftOperator; + break; + case CodeModel::SubscriptOperator: + result = AbstractMetaFunction::SubscriptOperator; + break; + case CodeModel::ComparisonOperator: + result = AbstractMetaFunction::ComparisonOperator; + break; case CodeModel::Normal: break; case CodeModel::Signal: @@ -1745,6 +1753,18 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM return result; } +static AbstractMetaFunction::FunctionType functionTypeFromName(const QString &name) +{ + if (name == u"__getattro__") + return AbstractMetaFunction::GetAttroFunction; + if (name == u"__setattro__") + return AbstractMetaFunction::SetAttroFunction; + const auto typeOpt = _FunctionModelItem::functionTypeFromName(name); + if (typeOpt.has_value()) + return functionTypeFromCodeModel(typeOpt.value()); + return AbstractMetaFunction::NormalFunction; +} + // Apply the <array> modifications of the arguments static bool applyArrayArgumentModifications(const FunctionModificationList &functionMods, AbstractMetaFunction *func, diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 2dc650ef9..4fd13adc9 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -103,7 +103,7 @@ public: void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); void applyFunctionModifications(AbstractMetaFunction* func); void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent); - void traverseStreamOperator(const FunctionModelItem &functionItem, + bool traverseStreamOperator(const FunctionModelItem &functionItem, AbstractMetaClass *currentClass); void traverseOperatorFunction(const FunctionModelItem &item, AbstractMetaClass *currentClass); diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp index f9e5dcaf4..5ccf36e00 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp @@ -31,6 +31,7 @@ #include "abstractmetalang.h" #include "abstractmetalang_helpers.h" #include "abstractmetatype.h" +#include <codemodel.h> #include "documentation.h" #include "messages.h" #include "modifications.h" @@ -551,9 +552,18 @@ bool AbstractMetaFunction::isConstructor() const || d->m_functionType == MoveConstructorFunction; } -bool AbstractMetaFunction::isNormal() const +bool AbstractMetaFunction::needsReturnType() const { - return functionType() == NormalFunction || isSlot() || isInGlobalScope(); + switch (d->m_functionType) { + case AbstractMetaFunction::ConstructorFunction: + case AbstractMetaFunction::CopyConstructorFunction: + case AbstractMetaFunction::MoveConstructorFunction: + case AbstractMetaFunction::DestructorFunction: + return false; + default: + break; + } + return true; } bool AbstractMetaFunction::isInGlobalScope() const @@ -936,7 +946,7 @@ bool AbstractMetaFunction::generateExceptionHandling() const bool AbstractMetaFunction::isConversionOperator() const { - return isConversionOperator(originalName()); + return d->m_functionType == ConversionOperator; } bool AbstractMetaFunction::isOperatorOverload(const QString &funcName) @@ -955,70 +965,34 @@ bool AbstractMetaFunction::isOperatorOverload(const QString &funcName) bool AbstractMetaFunction::isOperatorOverload() const { - return isOperatorOverload(originalName()); + return d->m_functionType == AssignmentOperatorFunction + || (d->m_functionType >= FirstOperator && d->m_functionType <= LastOperator); } bool AbstractMetaFunction::isArithmeticOperator() const { - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - - // It's a dereference operator! - if (name == QLatin1String("operator*") && d->m_arguments.isEmpty()) - return false; - - return name == QLatin1String("operator+") || name == QLatin1String("operator+=") - || name == QLatin1String("operator-") || name == QLatin1String("operator-=") - || name == QLatin1String("operator*") || name == QLatin1String("operator*=") - || name == QLatin1String("operator/") || name == QLatin1String("operator/=") - || name == QLatin1String("operator%") || name == QLatin1String("operator%=") - || name == QLatin1String("operator++") || name == QLatin1String("operator--"); + return d->m_functionType == ArithmeticOperator; } bool AbstractMetaFunction::isBitwiseOperator() const { - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<<") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator>>") || name == QLatin1String("operator>>=") - || name == QLatin1String("operator&") || name == QLatin1String("operator&=") - || name == QLatin1String("operator|") || name == QLatin1String("operator|=") - || name == QLatin1String("operator^") || name == QLatin1String("operator^=") - || name == QLatin1String("operator~"); + return d->m_functionType == BitwiseOperator + || d->m_functionType == ShiftOperator; } bool AbstractMetaFunction::isComparisonOperator() const { - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<") || name == QLatin1String("operator<=") - || name == QLatin1String("operator>") || name == QLatin1String("operator>=") - || name == QLatin1String("operator==") || name == QLatin1String("operator!="); + return d->m_functionType == ComparisonOperator; } bool AbstractMetaFunction::isLogicalOperator() const { - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator!") - || name == QLatin1String("operator&&") - || name == QLatin1String("operator||"); + return d->m_functionType == LogicalOperator; } bool AbstractMetaFunction::isSubscriptOperator() const { - if (!isOperatorOverload()) - return false; - - return originalName() == QLatin1String("operator[]"); + return d->m_functionType == SubscriptOperator; } bool AbstractMetaFunction::isAssignmentOperator() const @@ -1027,20 +1001,6 @@ bool AbstractMetaFunction::isAssignmentOperator() const || d->m_functionType == MoveAssignmentOperatorFunction; } -bool AbstractMetaFunction::isOtherOperator() const -{ - if (!isOperatorOverload()) - return false; - - return !isArithmeticOperator() - && !isBitwiseOperator() - && !isComparisonOperator() - && !isLogicalOperator() - && !isConversionOperator() - && !isSubscriptOperator() - && !isAssignmentOperator(); -} - int AbstractMetaFunction::arityOfOperator() const { if (!isOperatorOverload() || isCallOperator()) @@ -1060,15 +1020,14 @@ int AbstractMetaFunction::arityOfOperator() const bool AbstractMetaFunction::isInplaceOperator() const { - if (!isOperatorOverload()) - return false; + static const QSet<QStringView> inplaceOperators = + { + u"operator+=", u"operator&=", u"operator-=", u"operator|=", + u"operator*=", u"operator^=", u"operator/=", u"operator<<=", + u"operator%=", u"operator>>=" + }; - QString name = originalName(); - return name == QLatin1String("operator+=") || name == QLatin1String("operator&=") - || name == QLatin1String("operator-=") || name == QLatin1String("operator|=") - || name == QLatin1String("operator*=") || name == QLatin1String("operator^=") - || name == QLatin1String("operator/=") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator%=") || name == QLatin1String("operator>>="); + return isOperatorOverload() && inplaceOperators.contains(originalName()); } bool AbstractMetaFunction::isVirtual() const @@ -1107,6 +1066,38 @@ AbstractMetaFunction::find(const AbstractMetaFunctionCList &haystack, return {}; } +bool AbstractMetaFunction::matches(OperatorQueryOptions query) const +{ + bool result = false; + switch (d->m_functionType) { + case AbstractMetaFunction::AssignmentOperatorFunction: + result = query.testFlag(OperatorQueryOption::AssignmentOp); + break; + case AbstractMetaFunction::ConversionOperator: + result = query.testFlag(OperatorQueryOption::ConversionOp); + break; + case AbstractMetaFunction::ArithmeticOperator: + result = query.testFlag(OperatorQueryOption::ArithmeticOp); + break; + case AbstractMetaFunction::BitwiseOperator: + case AbstractMetaFunction::ShiftOperator: + result = query.testFlag(OperatorQueryOption::BitwiseOp); + break; + case AbstractMetaFunction::LogicalOperator: + result = query.testFlag(OperatorQueryOption::LogicalOp); + break; + case AbstractMetaFunction::SubscriptOperator: + result = query.testFlag(OperatorQueryOption::SubscriptionOp); + break; + case AbstractMetaFunction::ComparisonOperator: + result = query.testFlag(OperatorQueryOption::ComparisonOp); + break; + default: + break; + } + return result; +} + void AbstractMetaFunction::setAllowThreadModification(TypeSystem::AllowThread am) { d->m_allowThreadModification = am; @@ -1148,8 +1139,6 @@ TypeSystem::SnakeCase AbstractMetaFunction::snakeCase() const case AbstractMetaFunction::SignalFunction: case AbstractMetaFunction::EmptyFunction: case AbstractMetaFunction::SlotFunction: - if (isOperatorOverload()) - return TypeSystem::SnakeCase::Disabled; break; default: return TypeSystem::SnakeCase::Disabled; diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h index 9c33c93a4..1d5c8885a 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h +++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h @@ -29,6 +29,7 @@ #ifndef ABSTRACTMETAFUNCTION_H #define ABSTRACTMETAFUNCTION_H +#include "abstractmetalang_enums.h" #include "abstractmetalang_typedefs.h" #include "abstractmetaargument.h" #include "abstractmetaattributes.h" @@ -65,7 +66,20 @@ public: EmptyFunction, SlotFunction, GetAttroFunction, - SetAttroFunction + SetAttroFunction, + CallOperator, + FirstOperator = CallOperator, + ConversionOperator, + DereferenceOperator, // Iterator's operator * + ReferenceOperator, // operator & + ArrowOperator, + ArithmeticOperator, + BitwiseOperator, + LogicalOperator, + ShiftOperator, + SubscriptOperator, + ComparisonOperator, + LastOperator = ComparisonOperator }; Q_ENUM(FunctionType) @@ -135,12 +149,11 @@ public: bool isOperatorOverload() const; bool isArithmeticOperator() const; - bool isBitwiseOperator() const; + bool isBitwiseOperator() const; // Includes shift operator bool isComparisonOperator() const; bool isLogicalOperator() const; bool isSubscriptOperator() const; bool isAssignmentOperator() const; // Assignment or move assignment - bool isOtherOperator() const; /** * Informs the arity of the operator or -1 if the function is not @@ -190,7 +203,7 @@ public: bool isDeprecated() const; bool isDestructor() const { return functionType() == DestructorFunction; } bool isConstructor() const; - bool isNormal() const; + bool needsReturnType() const; bool isInGlobalScope() const; bool isSignal() const { return functionType() == SignalFunction; } bool isSlot() const { return functionType() == SlotFunction; } @@ -278,6 +291,8 @@ public: static AbstractMetaFunctionCPtr find(const AbstractMetaFunctionCList &haystack, const QString &needle); + bool matches(OperatorQueryOptions) const; + // for the meta builder only void setAllowThreadModification(TypeSystem::AllowThread am); void setExceptionHandlingModification(TypeSystem::ExceptionHandling em); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index b9705de02..32befc400 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -221,14 +221,7 @@ AbstractMetaFunctionCList AbstractMetaClass::operatorOverloads(OperatorQueryOpti | FunctionQueryOption::Visible); AbstractMetaFunctionCList returned; for (const auto &f : list) { - if ((query.testFlag(OperatorQueryOption::ArithmeticOp) && f->isArithmeticOperator()) - || (query.testFlag(OperatorQueryOption::BitwiseOp) && f->isBitwiseOperator()) - || (query.testFlag(OperatorQueryOption::ComparisonOp) && f->isComparisonOperator()) - || (query.testFlag(OperatorQueryOption::LogicalOp) && f->isLogicalOperator()) - || (query.testFlag(OperatorQueryOption::SubscriptionOp) && f->isSubscriptOperator()) - || (query.testFlag(OperatorQueryOption::AssignmentOp) && f->isAssignmentOperator()) - || (query.testFlag(OperatorQueryOption::ConversionOp) && f->isConversionOperator()) - || (query.testFlag(OperatorQueryOption::OtherOp) && f->isOtherOperator())) + if (f->matches(query)) returned += f; } @@ -1094,6 +1087,22 @@ static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, addExtraIncludeForType(metaClass, argument.type()); } +static bool addSuperFunction(const AbstractMetaFunctionCPtr &f) +{ + switch (f->functionType()) { + case AbstractMetaFunction::ConstructorFunction: + case AbstractMetaFunction::CopyConstructorFunction: + case AbstractMetaFunction::MoveConstructorFunction: + case AbstractMetaFunction::AssignmentOperatorFunction: + case AbstractMetaFunction::MoveAssignmentOperatorFunction: + case AbstractMetaFunction::DestructorFunction: + return false; + default: + break; + } + return true; +} + void AbstractMetaClass::fixFunctions() { if (d->m_functionsFixed) @@ -1139,7 +1148,7 @@ void AbstractMetaClass::fixFunctions() // we generally don't care about private functions, but we have to get the ones that are // virtual in case they override abstract functions. - bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction()); + bool add = addSuperFunction(sf); for (const auto &cf : qAsConst(nonRemovedFuncs)) { AbstractMetaFunctionPtr f(qSharedPointerConstCast<AbstractMetaFunction>(cf)); const AbstractMetaFunction::CompareResult cmp = cf->compareTo(sf.data()); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index 50bbdae08..2100f0eaa 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -114,7 +114,7 @@ public: * /return list of operator overload methods that meet the * query criteria */ - AbstractMetaFunctionCList operatorOverloads(OperatorQueryOptions query = OperatorQueryOption::AllOperators) const; + AbstractMetaFunctionCList operatorOverloads(OperatorQueryOptions query) const; bool hasArithmeticOperatorOverload() const; bool hasBitwiseOperatorOverload() const; diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h index 33c4a5aa8..fd8f158d3 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang_enums.h @@ -63,11 +63,7 @@ enum class OperatorQueryOption { LogicalOp = 0x08, // Logical: !, &&, || ConversionOp = 0x10, // Conversion: operator [const] TYPE() SubscriptionOp = 0x20, // Subscription: [] - AssignmentOp = 0x40, // Assignment: = - OtherOp = 0x80, // The remaining operators: call(), etc - AllOperators = ArithmeticOp | BitwiseOp | ComparisonOp - | LogicalOp | ConversionOp | SubscriptionOp - | AssignmentOp | OtherOp + AssignmentOp = 0x40 // Assignment: = }; Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption) diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp index 9006e2321..cf489eb2e 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp @@ -1235,13 +1235,25 @@ bool Builder::endToken(const CXCursor &cursor) break; case CXCursor_Constructor: d->qualifyConstructor(cursor); - d->m_currentFunction.clear(); + if (!d->m_currentFunction.isNull()) { + d->m_currentFunction->_determineType(); + d->m_currentFunction.clear(); + } break; case CXCursor_Destructor: case CXCursor_CXXMethod: case CXCursor_FunctionDecl: case CXCursor_FunctionTemplate: - d->m_currentFunction.clear(); + if (!d->m_currentFunction.isNull()) { + d->m_currentFunction->_determineType(); + d->m_currentFunction.clear(); + } + break; + case CXCursor_ConversionFunction: + if (!d->m_currentFunction.isNull()) { + d->m_currentFunction->setFunctionType(CodeModel::ConversionOperator); + d->m_currentFunction.clear(); + } break; case CXCursor_Namespace: d->popScope(); diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp index 5d1835c47..0f1e61a5b 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp @@ -34,6 +34,7 @@ #include <QtCore/QDebug> #include <QtCore/QDir> +#include <QtCore/QRegularExpression> #include <algorithm> #include <functional> @@ -903,6 +904,104 @@ QString _FunctionModelItem::typeSystemSignature() const // For dumping out type return result; } +using NameFunctionTypeHash = QHash<QStringView, CodeModel::FunctionType>; + +static const NameFunctionTypeHash &nameToOperatorFunction() +{ + static const NameFunctionTypeHash result = { + {u"operator=", CodeModel::AssignmentOperator}, + {u"operator+", CodeModel::ArithmeticOperator}, + {u"operator+=", CodeModel::ArithmeticOperator}, + {u"operator-", CodeModel::ArithmeticOperator}, + {u"operator-=", CodeModel::ArithmeticOperator}, + {u"operator*", CodeModel::ArithmeticOperator}, + {u"operator*=", CodeModel::ArithmeticOperator}, + {u"operator/", CodeModel::ArithmeticOperator}, + {u"operator/=", CodeModel::ArithmeticOperator}, + {u"operator%", CodeModel::ArithmeticOperator}, + {u"operator%=", CodeModel::ArithmeticOperator}, + {u"operator++", CodeModel::ArithmeticOperator}, + {u"operator--", CodeModel::ArithmeticOperator}, + {u"operator&", CodeModel::BitwiseOperator}, + {u"operator&=", CodeModel::BitwiseOperator}, + {u"operator|", CodeModel::BitwiseOperator}, + {u"operator|=", CodeModel::BitwiseOperator}, + {u"operator^", CodeModel::BitwiseOperator}, + {u"operator^=", CodeModel::BitwiseOperator}, + {u"operator~", CodeModel::BitwiseOperator}, + {u"operator<<", CodeModel::ShiftOperator}, + {u"operator<<=", CodeModel::ShiftOperator}, + {u"operator>>", CodeModel::ShiftOperator}, + {u"operator>>=", CodeModel::ShiftOperator}, + {u"operator<", CodeModel::ComparisonOperator}, + {u"operator<=", CodeModel::ComparisonOperator}, + {u"operator>", CodeModel::ComparisonOperator}, + {u"operator>=", CodeModel::ComparisonOperator}, + {u"operator==", CodeModel::ComparisonOperator}, + {u"operator!=", CodeModel::ComparisonOperator}, + {u"operator!", CodeModel::LogicalOperator}, + {u"operator&&", CodeModel::LogicalOperator}, + {u"operator||", CodeModel::LogicalOperator}, + {u"operator[]", CodeModel::SubscriptOperator}, + {u"operator()", CodeModel::CallOperator}, // Can be void + {u"operator->", CodeModel::ArrowOperator} + }; + return result; +} + +std::optional<CodeModel::FunctionType> _FunctionModelItem::functionTypeFromName(QStringView name) +{ + const auto it = nameToOperatorFunction().constFind(name); + if (it != nameToOperatorFunction().constEnd()) + return it.value(); + // This check is only for added functions. Clang detects this + // by cursor type CXCursor_ConversionFunction. + if (name.startsWith(u"operator ")) + return CodeModel::ConversionOperator; + return {}; +} + +// Check for operators, etc. unless it is a specific type like a constructor +CodeModel::FunctionType _FunctionModelItem::_determineTypeHelper() const +{ + switch (m_functionType) { + case CodeModel::Constructor: + case CodeModel::CopyConstructor: + case CodeModel::MoveConstructor: + case CodeModel::Destructor: + case CodeModel::Signal: + case CodeModel::Slot: + return m_functionType; // nothing to do here + default: + break; + } + const QString &functionName = name(); + const auto newTypeOpt = _FunctionModelItem::functionTypeFromName(functionName); + if (!newTypeOpt.has_value()) + return m_functionType; + + auto newType = newTypeOpt.value(); + // It's some sort of dereference operator?! + if (m_arguments.isEmpty()) { + switch (newType) { + case CodeModel::ArithmeticOperator: + if (functionName == u"operator*") + return CodeModel::DereferenceOperator; + case CodeModel::BitwiseOperator: + if (functionName == u"operator&") + return CodeModel::ReferenceOperator; + default: + break; + } + } + return newType; +} + +void _FunctionModelItem::_determineType() +{ + m_functionType = _determineTypeHelper(); +} + #ifndef QT_NO_DEBUG_STREAM void _FunctionModelItem::formatDebug(QDebug &d) const { diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h index d1703cb33..cb15e5985 100644 --- a/sources/shiboken6/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h @@ -43,6 +43,8 @@ #include <QtCore/QStringList> #include <QtCore/QList> +#include <optional> + QT_FORWARD_DECLARE_CLASS(QDebug) #define DECLARE_MODEL_NODE(k) \ @@ -70,7 +72,19 @@ public: MoveConstructor, Destructor, Signal, - Slot + Slot, + AssignmentOperator, + CallOperator, + ConversionOperator, + DereferenceOperator, // Iterator's operator * + ReferenceOperator, // operator & + ArrowOperator, + ArithmeticOperator, + BitwiseOperator, + LogicalOperator, + ShiftOperator, + SubscriptOperator, + ComparisonOperator }; Q_ENUM(FunctionType) @@ -190,7 +204,7 @@ public: ClassList classes() const { return m_classes; } EnumList enums() const { return m_enums; } - inline FunctionList functions() const { return m_functions; } + inline const FunctionList &functions() const { return m_functions; } TypeDefList typeDefs() const { return m_typeDefs; } TemplateTypeAliasList templateTypeAliases() const { return m_templateTypeAliases; } VariableList variables() const { return m_variables; } @@ -455,6 +469,8 @@ public: CodeModel::FunctionType functionType() const; void setFunctionType(CodeModel::FunctionType functionType); + static std::optional<CodeModel::FunctionType> functionTypeFromName(QStringView name); + bool isDeleted() const; void setDeleted(bool d); @@ -495,11 +511,16 @@ public: QString typeSystemSignature() const; // For dumping out type system files + // Private, for usage by the clang builder. + void _determineType(); + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif private: + CodeModel::FunctionType _determineTypeHelper() const; + ArgumentList m_arguments; CodeModel::FunctionType m_functionType; union { diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp index 9a7a3f12b..67584eff1 100644 --- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp +++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp @@ -1364,13 +1364,10 @@ QString ShibokenGenerator::functionSignature(const AbstractMetaFunctionCPtr &fun { StringStream s(TextStream::Language::Cpp); // The actual function - if (!(func->isEmptyFunction() || - func->isNormal() || - func->isSignal())) { - options |= Generator::SkipReturnType; - } else { + if (func->isEmptyFunction() || func->needsReturnType()) s << functionReturnType(func, options) << ' '; - } + else + options |= Generator::SkipReturnType; // name QString name(func->originalName()); @@ -2219,15 +2216,14 @@ static bool isGroupable(const AbstractMetaFunctionCPtr &func) case AbstractMetaFunction::SignalFunction: case AbstractMetaFunction::GetAttroFunction: case AbstractMetaFunction::SetAttroFunction: + case AbstractMetaFunction::ArrowOperator: // weird operator overloads + case AbstractMetaFunction::SubscriptOperator: return false; default: break; } if (func->isModifiedRemoved() && !func->isAbstract()) return false; - // weird operator overloads - if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? - return false; return true; } |