aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-12-08 13:40:32 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-12-11 14:48:21 +0000
commit6de894aea3db166dacf677431117dd7336cb6459 (patch)
tree225f6dab5892a70046365ca3142b76db5f5a462e /sources
parent820a12f45ae820f2857ae5a1ffbe3bcadae2a74f (diff)
shiboken6: Determine function types in the code model
Extend the _FunctionModelItem function type enumeration by operator types and determine them by name or from clang. Split the bitwise operators into shift and other bitwise operators for stresm operator detection. Similarly, add operator type values to AbstractMetaFunction::FunctionType and replace the isOperator() checks accordingly. Remove the unused isOtherOperator() function. Rename AbstractMetaFunction::isNormal() to needsReturnType() for clarity. Rewrite the binary operator search in AbstractMetaBuilder by checks based on enumeration value and rewrite traverseOperatorFunction to return a bool so that shift operators are found when stream operator is not applicable. Rewrite the function query functions of AbstractMetaClass to also use the enumeration values. Change-Id: I06cc2deefcd8a158f83c95513a7962de467f7f2a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit 6a1a08cfaf11ad38612e59cb1d56160160504ec8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp194
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.cpp131
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.h23
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp27
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang_enums.h6
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp16
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp99
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h25
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp14
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;
}