diff options
Diffstat (limited to 'sources/shiboken6_generator')
4 files changed, 70 insertions, 5 deletions
diff --git a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp index 7c5d34315..bf8d3246c 100644 --- a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder.cpp @@ -278,6 +278,15 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI } } +// Find "operator!=" matching an "operator==" in a scope. +static bool hasOperatorNotEqual(const ScopeModelItem &scopeItem, const FunctionModelItem &operatorEqual) +{ + auto pred = [&operatorEqual](const FunctionModelItem &f) { + return f->isOperatorNotEqual() && operatorEqual->hasEquivalentArguments(*f); + }; + return std::any_of(scopeItem->functions().cbegin(), scopeItem->functions().cend(), pred); +} + static ComparisonOperators synthesizedSpaceshipComparison(const AbstractMetaClassCPtr ¤tClass, const FunctionModelItem &item) { @@ -297,6 +306,7 @@ static ComparisonOperators synthesizedSpaceshipComparison(const AbstractMetaClas // Traverse free operator functions (global/namespace) void AbstractMetaBuilderPrivate::traverseFreeOperatorFunction(const FunctionModelItem &item, + const ScopeModelItem &scope, const AbstractMetaClassPtr ¤tClass) { Q_ASSERT(!currentClass || currentClass->isNamespace()); @@ -380,6 +390,17 @@ void AbstractMetaBuilderPrivate::traverseFreeOperatorFunction(const FunctionMode ops, flags); return; } + + // C++20: Synthesize "!=" from "==" + if (clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20 + && item->isOperatorEqual() + && !item->hasPointerArguments() && !hasOperatorNotEqual(scope, item)) { + AbstractMetaClass::addSynthesizedComparisonOperators( + baseoperandClass, metaFunction->arguments(), + ComparisonOperatorType::OperatorNotEqual, + flags | InternalFunctionFlag::OperatorCpp20NonEquality); + } + AbstractMetaClass::addFunction(baseoperandClass, metaFunction); ReportHandler::addGeneralMessage(msgSynthesizedFunction(metaFunction, item)); if (!metaFunction->arguments().isEmpty()) { @@ -697,11 +718,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, case CodeModel::ArithmeticOperator: case CodeModel::BitwiseOperator: case CodeModel::LogicalOperator: - traverseFreeOperatorFunction(func, {}); + traverseFreeOperatorFunction(func, dom, {}); break; case CodeModel::ShiftOperator: if (!traverseStreamOperator(func, {})) - traverseFreeOperatorFunction(func, {}); + traverseFreeOperatorFunction(func, dom, {}); default: break; } @@ -1486,7 +1507,7 @@ void AbstractMetaBuilderPrivate::traverseNameSpaceFunctions(const ScopeModelItem functions.reserve(scopeFunctionList.size()); for (const FunctionModelItem &function : scopeFunctionList) { if (function->isOperator()) { - traverseFreeOperatorFunction(function, currentClass); + traverseFreeOperatorFunction(function, scopeItem, currentClass); } else if (auto metaFunction = traverseFunction(function, currentClass)) { metaFunction->setCppAttribute(FunctionAttribute::Static); functions.append(metaFunction); @@ -1569,7 +1590,6 @@ void AbstractMetaBuilderPrivate::traverseClassFunction(const ScopeModelItem& sco const AbstractMetaFunctionPtr &metaFunction, const AbstractMetaClassPtr &metaClass) const { - Q_UNUSED(scopeItem) if (function->isSpaceshipOperator()) { // For spaceship, the traverse mechanism is only used to handle rejections // and get the argument type. @@ -1582,6 +1602,15 @@ void AbstractMetaBuilderPrivate::traverseClassFunction(const ScopeModelItem& sco return; } + // C++20: Synthesize "!=" from "==" + if (clang::emulatedCompilerLanguageLevel() >= LanguageLevel::Cpp20 + && function->isOperatorEqual() && !hasOperatorNotEqual(scopeItem, function)) { + AbstractMetaClass::addSynthesizedComparisonOperators( + metaClass, metaFunction->arguments(), + ComparisonOperatorType::OperatorNotEqual, + InternalFunctionFlag::OperatorCpp20NonEquality); + } + traverseClassFunction(metaFunction, metaClass); } diff --git a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h index b503f4b33..0890eb752 100644 --- a/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6_generator/ApiExtractor/abstractmetabuilder_p.h @@ -116,7 +116,7 @@ public: void traverseFields(const ScopeModelItem &item, const AbstractMetaClassPtr &parent); bool traverseStreamOperator(const FunctionModelItem &functionItem, const AbstractMetaClassPtr ¤tClass); - void traverseFreeOperatorFunction(const FunctionModelItem &item, + void traverseFreeOperatorFunction(const FunctionModelItem &item, const ScopeModelItem &scope, const AbstractMetaClassPtr ¤tClass); AbstractMetaFunctionPtr traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc, diff --git a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp index 8cbca7bc9..bfccacbac 100644 --- a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.cpp @@ -846,6 +846,13 @@ void _ArgumentModelItem::setScopeResolution(bool v) m_scopeResolution = v; } +bool _ArgumentModelItem::isEquivalent(const _ArgumentModelItem &rhs) const +{ + return m_scopeResolution == rhs.m_scopeResolution && m_defaultValue == rhs.m_defaultValue + && m_defaultValueExpression == rhs.m_defaultValueExpression + && m_type == rhs.m_type; +} + #ifndef QT_NO_DEBUG_STREAM void _ArgumentModelItem::formatDebug(QDebug &d) const { @@ -991,6 +998,16 @@ bool _FunctionModelItem::isOperator() const return result; } +static bool isPointerArgument(const ArgumentModelItem &a) +{ + return !a->type().indirectionsV().isEmpty(); +} + +bool _FunctionModelItem::hasPointerArguments() const +{ + return std::any_of(m_arguments.cbegin(), m_arguments.cend(), isPointerArgument); +} + ExceptionSpecification _FunctionModelItem::exceptionSpecification() const { return m_exceptionSpecification; @@ -1075,6 +1092,19 @@ QString _FunctionModelItem::typeSystemSignature() const // For dumping out type return result; } +static inline bool equivalentArguments(const ArgumentModelItem &lhs, + const ArgumentModelItem &rhs) +{ + return lhs->isEquivalent(*rhs); +} + +bool _FunctionModelItem::hasEquivalentArguments(const _FunctionModelItem &rhs) const +{ + return m_arguments.size() == rhs.m_arguments.size() + && std::equal(m_arguments.cbegin(), m_arguments.cend(), rhs.m_arguments.cbegin(), rhs.m_arguments.cend(), + equivalentArguments); +} + using NameFunctionTypeHash = QHash<QStringView, CodeModel::FunctionType>; static const NameFunctionTypeHash &nameToOperatorFunction() diff --git a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h index 8d757e635..7ff0a88e2 100644 --- a/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken6_generator/ApiExtractor/parser/codemodel.h @@ -380,6 +380,8 @@ public: bool scopeResolution() const; void setScopeResolution(bool v); + bool isEquivalent(const _ArgumentModelItem &rhs) const; // Compare all except name + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif @@ -502,6 +504,7 @@ public: bool isSpaceshipOperator() const; bool isOperatorEqual() const; bool isOperatorNotEqual() const; + bool hasPointerArguments() const; bool isSimilar(const FunctionModelItem &other) const; @@ -515,6 +518,9 @@ public: QString classQualifiedSignature() const; QString typeSystemSignature() const; // For dumping out type system files + // Compare all except names + bool hasEquivalentArguments(const _FunctionModelItem &rhs) const; + // Private, for usage by the clang builder. void _determineType(); |
