aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/shiboken/overloaddata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/generator/shiboken/overloaddata.cpp')
-rw-r--r--sources/shiboken6/generator/shiboken/overloaddata.cpp867
1 files changed, 413 insertions, 454 deletions
diff --git a/sources/shiboken6/generator/shiboken/overloaddata.cpp b/sources/shiboken6/generator/shiboken/overloaddata.cpp
index 468906d37..c28fcdc1a 100644
--- a/sources/shiboken6/generator/shiboken/overloaddata.cpp
+++ b/sources/shiboken6/generator/shiboken/overloaddata.cpp
@@ -1,79 +1,52 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt for Python.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <abstractmetafunction.h>
#include <apiextractorresult.h>
#include <abstractmetalang.h>
+#include <dotview.h>
#include <reporthandler.h>
-#include <typesystem.h>
+#include <complextypeentry.h>
+#include <containertypeentry.h>
+#include <primitivetypeentry.h>
#include <graph.h>
#include "overloaddata.h"
+#include "messages.h"
#include "ctypenames.h"
#include "pytypenames.h"
#include "textstream.h"
+#include "exception.h"
+
+#include "qtcompat.h"
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QTemporaryFile>
#include <algorithm>
+#include <utility>
-static const TypeEntry *getReferencedTypeEntry(const TypeEntry *typeEntry)
-{
- if (typeEntry->isPrimitive()) {
- auto pte = dynamic_cast<const PrimitiveTypeEntry *>(typeEntry);
- while (pte->referencedTypeEntry())
- pte = pte->referencedTypeEntry();
- typeEntry = pte;
- }
- return typeEntry;
-}
+using namespace Qt::StringLiterals;
static QString getTypeName(const AbstractMetaType &type)
{
- const TypeEntry *typeEntry = getReferencedTypeEntry(type.typeEntry());
+ TypeEntryCPtr typeEntry = type.typeEntry();
+ if (typeEntry->isPrimitive())
+ typeEntry = basicReferencedTypeEntry(typeEntry);
QString typeName = typeEntry->name();
if (typeEntry->isContainer()) {
QStringList types;
for (const auto &cType : type.instantiations()) {
- const TypeEntry *typeEntry = getReferencedTypeEntry(cType.typeEntry());
+ TypeEntryCPtr typeEntry = cType.typeEntry();
+ if (typeEntry->isPrimitive())
+ typeEntry = basicReferencedTypeEntry(typeEntry);
types << typeEntry->name();
}
- typeName += QLatin1Char('<') + types.join(QLatin1Char(',')) + QLatin1String(" >");
+ typeName += u'<' + types.join(u',') + u" >"_s;
}
return typeName;
}
-static QString getTypeName(const OverloadData *ov)
-{
- return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType());
-}
-
static bool typesAreEqual(const AbstractMetaType &typeA, const AbstractMetaType &typeB)
{
if (typeA.typeEntry() == typeB.typeEntry()) {
@@ -81,7 +54,7 @@ static bool typesAreEqual(const AbstractMetaType &typeA, const AbstractMetaType
if (typeA.instantiations().size() != typeB.instantiations().size())
return false;
- for (int i = 0; i < typeA.instantiations().size(); ++i) {
+ for (qsizetype i = 0; i < typeA.instantiations().size(); ++i) {
if (!typesAreEqual(typeA.instantiations().at(i), typeB.instantiations().at(i)))
return false;
}
@@ -115,48 +88,23 @@ static QString getImplicitConversionTypeName(const AbstractMetaType &containerTy
for (const auto &otherType : containerType.instantiations())
types << (otherType == instantiation ? impConv : getTypeName(otherType));
- return containerType.typeEntry()->qualifiedCppName() + QLatin1Char('<')
- + types.join(QLatin1String(", ")) + QLatin1String(" >");
-}
-
-// overloaddata.cpp
-static QString msgCyclicDependency(const QString &funcName, const QString &graphName,
- const AbstractMetaFunctionCList &cyclic,
- const AbstractMetaFunctionCList &involvedConversions)
-{
- QString result;
- QTextStream str(&result);
- str << "Cyclic dependency found on overloaddata for \"" << funcName
- << "\" method! The graph boy saved the graph at \"" << QDir::toNativeSeparators(graphName)
- << "\". Cyclic functions:";
- for (const auto &c : cyclic)
- str << ' ' << c->signature();
- if (const int count = involvedConversions.size()) {
- str << " Implicit conversions (" << count << "): ";
- for (int i = 0; i < count; ++i) {
- if (i)
- str << ", \"";
- str << involvedConversions.at(i)->signature() << '"';
- if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass())
- str << '(' << c->name() << ')';
- }
- }
- return result;
+ return containerType.typeEntry()->qualifiedCppName() + u'<'
+ + types.join(u", "_s) + u" >"_s;
}
-static inline int overloadNumber(const OverloadData *o)
+static inline int overloadNumber(const OverloadDataNodePtr &o)
{
return o->referenceFunction()->overloadNumber();
}
-bool OverloadData::sortByOverloadNumberModification()
+static bool sortByOverloadNumberModification(OverloadDataList &list)
{
- if (std::all_of(m_nextOverloadData.cbegin(), m_nextOverloadData.cend(),
- [](const OverloadData *o) { return overloadNumber(o) == TypeSystem::OverloadNumberDefault; })) {
+ if (std::all_of(list.cbegin(), list.cend(),
+ [](const OverloadDataNodePtr &o) { return overloadNumber(o) == TypeSystem::OverloadNumberDefault; })) {
return false;
}
- std::stable_sort(m_nextOverloadData.begin(), m_nextOverloadData.end(),
- [] (const OverloadData *o1, const OverloadData *o2) {
+ std::stable_sort(list.begin(), list.end(),
+ [] (const OverloadDataNodePtr &o1, const OverloadDataNodePtr &o2) {
return overloadNumber(o1) < overloadNumber(o2);
});
return true;
@@ -174,9 +122,10 @@ using OverloadGraph = Graph<QString>;
*
* Side effects: Modifies m_nextOverloadData
*/
-void OverloadData::sortNextOverloads()
+void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
{
QHash<QString, OverloadDataList> typeToOverloads;
+ using Edge = std::pair<QString, QString>;
bool checkPyObject = false;
bool checkPySequence = false;
@@ -186,16 +135,16 @@ void OverloadData::sortNextOverloads()
// Primitive types that are not int, long, short,
// char and their respective unsigned counterparts.
- static const QStringList nonIntegerPrimitives{floatT(), doubleT(), boolT()};
+ static const QStringList nonIntegerPrimitives{floatT, doubleT, boolT};
// Signed integer primitive types.
- static const QStringList signedIntegerPrimitives{intT(), shortT(), longT(), longLongT()};
+ static const QStringList signedIntegerPrimitives{intT, shortT, longT, longLongT};
// sort the children overloads
- for (OverloadData *ov : qAsConst(m_nextOverloadData))
- ov->sortNextOverloads();
+ for (const auto &ov : std::as_const(m_children))
+ ov->sortNextOverloads(api);
- if (m_nextOverloadData.size() <= 1 || sortByOverloadNumberModification())
+ if (m_children.size() <= 1 || sortByOverloadNumberModification(m_children))
return;
// Populates the OverloadSortData object containing map and reverseMap, to map type names to ids,
@@ -203,8 +152,8 @@ void OverloadData::sortNextOverloads()
// with graph sorting using integers.
OverloadGraph graph;
- for (OverloadData *ov : qAsConst(m_nextOverloadData)) {
- const QString typeName = getTypeName(ov);
+ for (const auto &ov : std::as_const(m_children)) {
+ const QString typeName = getTypeName(ov->modifiedArgType());
auto it = typeToOverloads.find(typeName);
if (it == typeToOverloads.end()) {
typeToOverloads.insert(typeName, {ov});
@@ -213,15 +162,15 @@ void OverloadData::sortNextOverloads()
it.value().append(ov);
}
- if (!checkPyObject && typeName == cPyObjectT())
+ if (!checkPyObject && typeName == cPyObjectT)
checkPyObject = true;
- else if (!checkPySequence && typeName == cPySequenceT())
+ else if (!checkPySequence && typeName == cPySequenceT)
checkPySequence = true;
- else if (!checkPyBuffer && typeName == cPyBufferT())
+ else if (!checkPyBuffer && typeName == cPyBufferT)
checkPyBuffer = true;
- else if (!checkQVariant && typeName == qVariantT())
+ else if (!checkQVariant && typeName == qVariantT)
checkQVariant = true;
- else if (!checkQString && typeName == qStringT())
+ else if (!checkQString && typeName == qStringT)
checkQString = true;
for (const auto &instantiation : ov->argType().instantiations()) {
@@ -234,10 +183,10 @@ void OverloadData::sortNextOverloads()
// as Point must come before the PointF instantiation, or else list<Point> will never
// be called. In the case of primitive types, list<double> must come before list<int>.
if (instantiation.isPrimitive() && (signedIntegerPrimitives.contains(instantiation.name()))) {
- for (const QString &primitive : qAsConst(nonIntegerPrimitives))
+ for (const QString &primitive : std::as_const(nonIntegerPrimitives))
graph.addNode(getImplicitConversionTypeName(ov->argType(), instantiation, nullptr, primitive));
} else {
- const auto &funcs = m_api.implicitConversions(instantiation);
+ const auto &funcs = api.implicitConversions(instantiation);
for (const auto &function : funcs)
graph.addNode(getImplicitConversionTypeName(ov->argType(), instantiation, function));
}
@@ -247,9 +196,9 @@ void OverloadData::sortNextOverloads()
// Create the graph of type dependencies based on implicit conversions.
// All C++ primitive types, add any forgotten type AT THE END OF THIS LIST!
- static const QStringList primitiveTypes{intT(), unsignedIntT(), longT(), unsignedLongT(),
- shortT(), unsignedShortT(), boolT(), unsignedCharT(), charT(), floatT(),
- doubleT(), constCharPtrT()};
+ static const QStringList primitiveTypes{intT, unsignedIntT, longT, unsignedLongT,
+ shortT, unsignedShortT, boolT, unsignedCharT, charT, floatT,
+ doubleT, constCharPtrT};
QStringList foundPrimitiveTypeIds;
for (const auto &p : primitiveTypes) {
@@ -258,18 +207,18 @@ void OverloadData::sortNextOverloads()
}
if (checkPySequence && checkPyObject)
- graph.addEdge(cPySequenceT(), cPyObjectT());
+ graph.addEdge(cPySequenceT, cPyObjectT);
QStringList classesWithIntegerImplicitConversion;
AbstractMetaFunctionCList involvedConversions;
- for (OverloadData *ov : qAsConst(m_nextOverloadData)) {
+ for (const auto &ov : std::as_const(m_children)) {
const AbstractMetaType &targetType = ov->argType();
- const QString targetTypeEntryName = getTypeName(ov);
+ const QString targetTypeEntryName = getTypeName(ov->modifiedArgType());
// Process implicit conversions
- const auto &functions = m_api.implicitConversions(targetType);
+ const auto &functions = api.implicitConversions(targetType);
for (const auto &function : functions) {
QString convertibleType;
if (function->isConversionOperator())
@@ -277,7 +226,7 @@ void OverloadData::sortNextOverloads()
else
convertibleType = getTypeName(function->arguments().constFirst().type());
- if (convertibleType == intT() || convertibleType == unsignedIntT())
+ if (convertibleType == intT || convertibleType == unsignedIntT)
classesWithIntegerImplicitConversion << targetTypeEntryName;
if (!graph.hasNode(convertibleType))
@@ -292,10 +241,12 @@ void OverloadData::sortNextOverloads()
// Process inheritance relationships
if (targetType.isValue() || targetType.isObject()) {
- auto metaClass = AbstractMetaClass::findClass(m_api.classes(),
- targetType.typeEntry());
- const AbstractMetaClassList &ancestors = metaClass->allTypeSystemAncestors();
- for (const AbstractMetaClass *ancestor : ancestors) {
+ const auto te = targetType.typeEntry();
+ auto metaClass = AbstractMetaClass::findClass(api.classes(), te);
+ if (!metaClass)
+ throw Exception(msgArgumentClassNotFound(m_overloads.constFirst(), te));
+ const auto &ancestors = metaClass->allTypeSystemAncestors();
+ for (const auto &ancestor : ancestors) {
QString ancestorTypeName = ancestor->typeEntry()->name();
if (!graph.hasNode(ancestorTypeName))
continue;
@@ -312,7 +263,7 @@ void OverloadData::sortNextOverloads()
graph.addEdge(convertible, targetTypeEntryName);
if (instantiation.isPrimitive() && (signedIntegerPrimitives.contains(instantiation.name()))) {
- for (const QString &primitive : qAsConst(nonIntegerPrimitives)) {
+ for (const QString &primitive : std::as_const(nonIntegerPrimitives)) {
QString convertibleTypeName =
getImplicitConversionTypeName(ov->argType(), instantiation, nullptr, primitive);
// Avoid cyclic dependency.
@@ -321,7 +272,7 @@ void OverloadData::sortNextOverloads()
}
} else {
- const auto &funcs = m_api.implicitConversions(instantiation);
+ const auto &funcs = api.implicitConversions(instantiation);
for (const auto &function : funcs) {
QString convertibleTypeName =
getImplicitConversionTypeName(ov->argType(), instantiation, function);
@@ -337,28 +288,28 @@ void OverloadData::sortNextOverloads()
if ((checkPySequence || checkPyObject || checkPyBuffer)
- && !targetTypeEntryName.contains(cPyObjectT())
- && !targetTypeEntryName.contains(cPyBufferT())
- && !targetTypeEntryName.contains(cPySequenceT())) {
+ && !targetTypeEntryName.contains(cPyObjectT)
+ && !targetTypeEntryName.contains(cPyBufferT)
+ && !targetTypeEntryName.contains(cPySequenceT)) {
if (checkPySequence) {
// PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeEntryName, cPySequenceT());
+ graph.addEdge(targetTypeEntryName, cPySequenceT);
} else if (checkPyBuffer) {
// PySequence will be checked after all more specific types, but before PyObject.
- graph.addEdge(targetTypeEntryName, cPyBufferT());
+ graph.addEdge(targetTypeEntryName, cPyBufferT);
} else {
// Add dependency on PyObject, so its check is the last one (too generic).
- graph.addEdge(targetTypeEntryName, cPyObjectT());
+ graph.addEdge(targetTypeEntryName, cPyObjectT);
}
- } else if (checkQVariant && targetTypeEntryName != qVariantT()) {
- if (!graph.containsEdge(qVariantT(), targetTypeEntryName)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeEntryName, qVariantT());
+ } else if (checkQVariant && targetTypeEntryName != qVariantT) {
+ if (!graph.containsEdge(qVariantT, targetTypeEntryName)) // Avoid cyclic dependency.
+ graph.addEdge(targetTypeEntryName, qVariantT);
} else if (checkQString && ov->argType().isPointer()
- && targetTypeEntryName != qStringT()
- && targetTypeEntryName != qByteArrayT()
- && (!checkPyObject || targetTypeEntryName != cPyObjectT())) {
- if (!graph.containsEdge(qStringT(), targetTypeEntryName)) // Avoid cyclic dependency.
- graph.addEdge(targetTypeEntryName, qStringT());
+ && targetTypeEntryName != qStringT
+ && targetTypeEntryName != qByteArrayT
+ && (!checkPyObject || targetTypeEntryName != cPyObjectT)) {
+ if (!graph.containsEdge(qStringT, targetTypeEntryName)) // Avoid cyclic dependency.
+ graph.addEdge(targetTypeEntryName, qStringT);
}
if (targetType.isEnum()) {
@@ -369,25 +320,36 @@ void OverloadData::sortNextOverloads()
}
// QByteArray args need to be checked after QString args
- if (graph.hasNode(qStringT()) && graph.hasNode(qByteArrayT()))
- graph.addEdge(qStringT(), qByteArrayT());
+ if (graph.hasNode(qStringT) && graph.hasNode(qByteArrayT))
+ graph.addEdge(qStringT, qByteArrayT);
- for (OverloadData *ov : qAsConst(m_nextOverloadData)) {
+ static const Edge rangeOrder[] =
+ {{doubleT, floatT},
+ {longLongT, longT}, {longLongT, intT}, {intT, shortT},
+ {unsignedLongLongT, unsignedLongT}, {unsignedLongLongT, unsignedT},
+ {unsignedLongLongT, unsignedIntT}, {unsignedT, unsignedShortT}
+ };
+ for (const auto &r : rangeOrder) {
+ if (graph.hasNode(r.first) && graph.hasNode(r.second))
+ graph.addEdge(r.first, r.second);
+ }
+
+ for (const auto &ov : std::as_const(m_children)) {
const AbstractMetaType &targetType = ov->argType();
if (!targetType.isEnum())
continue;
QString targetTypeEntryName = getTypeName(targetType);
// Enum values must precede types implicitly convertible from "int" or "unsigned int".
- for (const QString &implicitFromInt : qAsConst(classesWithIntegerImplicitConversion))
+ for (const QString &implicitFromInt : std::as_const(classesWithIntegerImplicitConversion))
graph.addEdge(targetTypeEntryName, implicitFromInt);
}
// Special case for double(int i) (not tracked by m_generator->implicitConversions
- for (const QString &signedIntegerName : qAsConst(signedIntegerPrimitives)) {
+ for (const QString &signedIntegerName : std::as_const(signedIntegerPrimitives)) {
if (graph.hasNode(signedIntegerName)) {
- for (const QString &nonIntegerName : qAsConst(nonIntegerPrimitives)) {
+ for (const QString &nonIntegerName : std::as_const(nonIntegerPrimitives)) {
if (graph.hasNode(nonIntegerName))
graph.addEdge(nonIntegerName, signedIntegerName);
}
@@ -398,11 +360,11 @@ void OverloadData::sortNextOverloads()
const auto unmappedResult = graph.topologicalSort();
if (!unmappedResult.isValid()) {
QString funcName = referenceFunction()->name();
- if (referenceFunction()->ownerClass())
- funcName.prepend(referenceFunction()->ownerClass()->name() + QLatin1Char('.'));
+ if (auto owner = referenceFunction()->ownerClass())
+ funcName.prepend(owner->name() + u'.');
// Dump overload graph
- QString graphName = QDir::tempPath() + QLatin1Char('/') + funcName + QLatin1String(".dot");
+ QString graphName = QDir::tempPath() + u'/' + funcName + u".dot"_s;
graph.dumpDot(graphName, [] (const QString &n) { return n; });
AbstractMetaFunctionCList cyclic;
for (const auto &typeName : unmappedResult.cyclic) {
@@ -413,21 +375,45 @@ void OverloadData::sortNextOverloads()
qCWarning(lcShiboken, "%s", qPrintable(msgCyclicDependency(funcName, graphName, cyclic, involvedConversions)));
}
- m_nextOverloadData.clear();
+ m_children.clear();
for (const auto &typeName : unmappedResult.result) {
const auto oit = typeToOverloads.constFind(typeName);
if (oit != typeToOverloads.cend()) {
std::copy(oit.value().crbegin(), oit.value().crend(),
- std::back_inserter(m_nextOverloadData));
+ std::back_inserter(m_children));
+ }
+ }
+}
+
+// Determine the minimum (first default argument)/maximum arguments (size)
+// of a function (taking into account the removed arguments).
+static std::pair<int, int> getMinMaxArgs(const AbstractMetaFunctionCPtr &func)
+{
+ int defaultValueIndex = -1;
+ const auto &arguments = func->arguments();
+ int argIndex = 0;
+ for (const auto &arg : arguments) {
+ if (!arg.isModifiedRemoved()) {
+ if (defaultValueIndex < 0 && arg.hasDefaultValueExpression())
+ defaultValueIndex = argIndex;
+ ++argIndex;
}
}
+ const int maxArgs = argIndex;
+ const int minArgs = defaultValueIndex >= 0 ? defaultValueIndex : maxArgs;
+ return {minArgs, maxArgs};
+}
+
+const OverloadDataRootNode *OverloadDataNode::parent() const
+{
+ return m_parent;
}
/**
* Root constructor for OverloadData
*
* This constructor receives the list of overloads for a given function and iterates generating
- * the graph of OverloadData instances. Each OverloadData instance references an argument/type
+ * the graph of OverloadData instances. Each OverloadDataNode instance references an argument/type
* combination.
*
* Example:
@@ -441,86 +427,58 @@ void OverloadData::sortNextOverloads()
*
*/
OverloadData::OverloadData(const AbstractMetaFunctionCList &overloads,
- const ApiExtractorResult &api)
- : m_minArgs(256), m_maxArgs(0), m_argPos(-1), m_argType(nullptr),
- m_headOverloadData(this), m_previousOverloadData(nullptr),
- m_api(api)
+ const ApiExtractorResult &api) :
+ OverloadDataRootNode(overloads)
{
for (const auto &func : overloads) {
- m_overloads.append(func);
- int argSize = func->arguments().size() - numberOfRemovedArguments(func);
- if (m_minArgs > argSize)
- m_minArgs = argSize;
- else if (m_maxArgs < argSize)
- m_maxArgs = argSize;
- OverloadData *currentOverloadData = this;
+ const auto minMaxArgs = getMinMaxArgs(func);
+ if (minMaxArgs.first < m_minArgs)
+ m_minArgs = minMaxArgs.first;
+ if (minMaxArgs.second > m_maxArgs)
+ m_maxArgs = minMaxArgs.second;
+ OverloadDataRootNode *currentOverloadData = this;
const AbstractMetaArgumentList &arguments = func->arguments();
for (const AbstractMetaArgument &arg : arguments) {
- if (func->argumentRemoved(arg.argumentIndex() + 1))
- continue;
- currentOverloadData = currentOverloadData->addOverloadData(func, arg);
+ if (!arg.isModifiedRemoved())
+ currentOverloadData = currentOverloadData->addOverloadDataNode(func, arg);
}
}
// Sort the overload possibilities so that the overload decisor code goes for the most
// important cases first, based on the topological order of the implicit conversions
- sortNextOverloads();
-
- // Fix minArgs
- if (minArgs() > maxArgs())
- m_headOverloadData->m_minArgs = maxArgs();
+ sortNextOverloads(api);
}
-OverloadData::OverloadData(OverloadData *headOverloadData, const AbstractMetaFunctionCPtr &func,
- const AbstractMetaType &argType, int argPos,
- const ApiExtractorResult &api) :
- m_minArgs(256), m_maxArgs(0), m_argPos(argPos), m_argType(argType),
- m_headOverloadData(headOverloadData), m_previousOverloadData(nullptr), m_api(api)
+OverloadDataNode::OverloadDataNode(const AbstractMetaFunctionCPtr &func,
+ OverloadDataRootNode *parent,
+ const AbstractMetaArgument &argument,
+ int argPos,
+ const QString argTypeReplaced) :
+ m_argument(argument),
+ m_argTypeReplaced(argTypeReplaced),
+ m_parent(parent),
+ m_argPos(argPos)
{
if (func)
this->addOverload(func);
}
-void OverloadData::addOverload(const AbstractMetaFunctionCPtr &func)
+void OverloadDataNode::addOverload(const AbstractMetaFunctionCPtr &func)
{
- int origNumArgs = func->arguments().size();
- int removed = numberOfRemovedArguments(func);
- int numArgs = origNumArgs - removed;
-
- if (numArgs > m_headOverloadData->m_maxArgs)
- m_headOverloadData->m_maxArgs = numArgs;
-
- if (numArgs < m_headOverloadData->m_minArgs)
- m_headOverloadData->m_minArgs = numArgs;
-
- for (int i = 0; m_headOverloadData->m_minArgs > 0 && i < origNumArgs; i++) {
- if (func->argumentRemoved(i + 1))
- continue;
- if (func->arguments().at(i).hasDefaultValueExpression()) {
- int fixedArgIndex = i - removed;
- if (fixedArgIndex < m_headOverloadData->m_minArgs)
- m_headOverloadData->m_minArgs = fixedArgIndex;
- }
- }
-
m_overloads.append(func);
}
-OverloadData *OverloadData::addOverloadData(const AbstractMetaFunctionCPtr &func,
- const AbstractMetaArgument &arg)
+OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFunctionCPtr &func,
+ const AbstractMetaArgument &arg)
{
- const AbstractMetaType &argType = arg.type();
- OverloadData *overloadData = nullptr;
+ OverloadDataNodePtr overloadData;
if (!func->isOperatorOverload()) {
- for (OverloadData *tmp : qAsConst(m_nextOverloadData)) {
+ for (const auto &tmp : std::as_const(m_children)) {
// TODO: 'const char *', 'char *' and 'char' will have the same TypeEntry?
// If an argument have a type replacement, then we should create a new overloaddata
// for it, unless the next argument also have a identical type replacement.
- QString replacedArg = func->typeReplaced(tmp->m_argPos + 1);
- bool argsReplaced = !replacedArg.isEmpty() || !tmp->m_argTypeReplaced.isEmpty();
- if ((!argsReplaced && typesAreEqual(tmp->m_argType, argType))
- || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) {
+ if (typesAreEqual(tmp->modifiedArgType(), arg.modifiedType())) {
tmp->addOverload(func);
overloadData = tmp;
}
@@ -528,34 +486,26 @@ OverloadData *OverloadData::addOverloadData(const AbstractMetaFunctionCPtr &func
}
if (!overloadData) {
- overloadData = new OverloadData(m_headOverloadData, func, argType, m_argPos + 1, m_api);
- overloadData->m_previousOverloadData = this;
- QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1);
-
- if (!typeReplaced.isEmpty())
- overloadData->m_argTypeReplaced = typeReplaced;
- m_nextOverloadData.append(overloadData);
+ const int argpos = argPos() + 1;
+ overloadData.reset(new OverloadDataNode(func, this, arg, argpos));
+ m_children.append(overloadData);
}
- return overloadData;
+ return overloadData.get();
}
-QStringList OverloadData::returnTypes() const
+bool OverloadData::hasNonVoidReturnType() const
{
- QSet<QString> retTypes;
for (const auto &func : m_overloads) {
- if (!func->typeReplaced(0).isEmpty())
- retTypes << func->typeReplaced(0);
- else if (!func->argumentRemoved(0))
- retTypes << func->type().cppSignature();
+ if (func->isTypeModified()) {
+ if (func->modifiedTypeName() != u"void")
+ return true;
+ } else {
+ if (!func->argumentRemoved(0) && !func->type().isVoid())
+ return true;
+ }
}
- return retTypes.values();
-}
-
-bool OverloadData::hasNonVoidReturnType() const
-{
- QStringList retTypes = returnTypes();
- return !retTypes.contains(QLatin1String("void")) || retTypes.size() > 1;
+ return false;
}
bool OverloadData::hasVarargs() const
@@ -568,15 +518,6 @@ bool OverloadData::hasVarargs() const
return false;
}
-bool OverloadData::hasAllowThread() const
-{
- for (const auto &func : m_overloads) {
- if (func->allowThread())
- return true;
- }
- return false;
-}
-
bool OverloadData::hasStaticFunction(const AbstractMetaFunctionCList &overloads)
{
for (const auto &func : overloads) {
@@ -641,20 +582,27 @@ bool OverloadData::hasStaticAndInstanceFunctions() const
return OverloadData::hasStaticFunction() && OverloadData::hasInstanceFunction();
}
-AbstractMetaFunctionCPtr OverloadData::referenceFunction() const
+OverloadDataRootNode::OverloadDataRootNode(const AbstractMetaFunctionCList &o) :
+ m_overloads(o)
+{
+}
+
+OverloadDataRootNode::~OverloadDataRootNode() = default;
+
+AbstractMetaFunctionCPtr OverloadDataRootNode::referenceFunction() const
{
return m_overloads.constFirst();
}
-const AbstractMetaArgument *OverloadData::argument(const AbstractMetaFunctionCPtr &func) const
+const AbstractMetaArgument *OverloadDataNode::overloadArgument(const AbstractMetaFunctionCPtr &func) const
{
- if (isHeadOverloadData() || !m_overloads.contains(func))
+ if (isRoot() || !m_overloads.contains(func))
return nullptr;
int argPos = 0;
int removed = 0;
for (int i = 0; argPos <= m_argPos; i++) {
- if (func->argumentRemoved(i + 1))
+ if (func->arguments().at(i).isModifiedRemoved())
removed++;
else
argPos++;
@@ -663,89 +611,54 @@ const AbstractMetaArgument *OverloadData::argument(const AbstractMetaFunctionCPt
return &func->arguments().at(m_argPos + removed);
}
-OverloadDataList OverloadData::overloadDataOnPosition(OverloadData *overloadData, int argPos) const
-{
- OverloadDataList overloadDataList;
- if (overloadData->argPos() == argPos) {
- overloadDataList.append(overloadData);
- } else if (overloadData->argPos() < argPos) {
- const OverloadDataList &data = overloadData->nextOverloadData();
- for (OverloadData *pd : data)
- overloadDataList += overloadDataOnPosition(pd, argPos);
- }
- return overloadDataList;
-}
-
-OverloadDataList OverloadData::overloadDataOnPosition(int argPos) const
+bool OverloadDataRootNode::nextArgumentHasDefaultValue() const
{
- OverloadDataList overloadDataList;
- overloadDataList += overloadDataOnPosition(m_headOverloadData, argPos);
- return overloadDataList;
-}
-
-bool OverloadData::nextArgumentHasDefaultValue() const
-{
- for (OverloadData *overloadData : m_nextOverloadData) {
- if (!overloadData->getFunctionWithDefaultValue().isNull())
+ for (const auto &overloadData : m_children) {
+ if (overloadData->getFunctionWithDefaultValue())
return true;
}
return false;
}
-static OverloadData *_findNextArgWithDefault(OverloadData *overloadData)
+static const OverloadDataRootNode *_findNextArgWithDefault(const OverloadDataRootNode *overloadData)
{
- if (!overloadData->getFunctionWithDefaultValue().isNull())
+ if (overloadData->getFunctionWithDefaultValue())
return overloadData;
- OverloadData *result = nullptr;
- const OverloadDataList &data = overloadData->nextOverloadData();
- for (OverloadData *odata : data) {
- OverloadData *tmp = _findNextArgWithDefault(odata);
+ const OverloadDataRootNode *result = nullptr;
+ const OverloadDataList &data = overloadData->children();
+ for (const auto &odata : data) {
+ const auto *tmp = _findNextArgWithDefault(odata.get());
if (!result || (tmp && result->argPos() > tmp->argPos()))
result = tmp;
}
return result;
}
-OverloadData *OverloadData::findNextArgWithDefault()
+const OverloadDataRootNode *OverloadDataRootNode::findNextArgWithDefault() const
{
return _findNextArgWithDefault(this);
}
-bool OverloadData::isFinalOccurrence(const AbstractMetaFunctionCPtr &func) const
+bool OverloadDataRootNode::isFinalOccurrence(const AbstractMetaFunctionCPtr &func) const
{
- for (const OverloadData *pd : m_nextOverloadData) {
+ for (const auto &pd : m_children) {
if (pd->overloads().contains(func))
return false;
}
return true;
}
-AbstractMetaFunctionCList OverloadData::overloadsWithoutRepetition() const
+AbstractMetaFunctionCPtr OverloadDataRootNode::getFunctionWithDefaultValue() const
{
- AbstractMetaFunctionCList overloads = m_overloads;
+ const qsizetype argpos = argPos();
for (const auto &func : m_overloads) {
- if (func->minimalSignature().endsWith(QLatin1String("const")))
- continue;
- for (const auto &f : qAsConst(overloads)) {
- if ((func->minimalSignature() + QLatin1String("const")) == f->minimalSignature()) {
- overloads.removeOne(f);
- break;
- }
- }
- }
- return overloads;
-}
-
-AbstractMetaFunctionCPtr OverloadData::getFunctionWithDefaultValue() const
-{
- for (const auto &func : m_overloads) {
- int removedArgs = 0;
- for (int i = 0; i <= m_argPos + removedArgs; i++) {
- if (func->argumentRemoved(i + 1))
+ qsizetype removedArgs = 0;
+ for (qsizetype i = 0; i <= argpos + removedArgs; i++) {
+ if (func->arguments().at(i).isModifiedRemoved())
removedArgs++;
}
- if (func->arguments().at(m_argPos + removedArgs).hasDefaultValueExpression())
+ if (func->arguments().at(argpos + removedArgs).hasDefaultValueExpression())
return func;
}
return {};
@@ -755,11 +668,11 @@ QList<int> OverloadData::invalidArgumentLengths() const
{
QSet<int> validArgLengths;
- for (const auto &func : qAsConst(m_headOverloadData->m_overloads)) {
+ for (const auto &func : m_overloads) {
const AbstractMetaArgumentList args = func->arguments();
int offset = 0;
- for (int i = 0; i < args.size(); ++i) {
- if (func->argumentRemoved(i+1)) {
+ for (qsizetype i = 0; i < args.size(); ++i) {
+ if (func->arguments().at(i).isModifiedRemoved()) {
offset++;
} else {
if (args.at(i).hasDefaultValueExpression())
@@ -770,7 +683,7 @@ QList<int> OverloadData::invalidArgumentLengths() const
}
QList<int> invalidArgLengths;
- for (int i = minArgs() + 1; i < maxArgs(); i++) {
+ for (int i = m_minArgs + 1; i < m_maxArgs; i++) {
if (!validArgLengths.contains(i))
invalidArgLengths.append(i);
}
@@ -778,196 +691,204 @@ QList<int> OverloadData::invalidArgumentLengths() const
return invalidArgLengths;
}
-int OverloadData::numberOfRemovedArguments(const AbstractMetaFunctionCPtr &func, int finalArgPos)
+int OverloadData::numberOfRemovedArguments(const AbstractMetaFunctionCPtr &func)
{
- int removed = 0;
- if (finalArgPos < 0) {
- for (int i = 0; i < func->arguments().size(); i++) {
- if (func->argumentRemoved(i + 1))
- removed++;
- }
- } else {
- for (int i = 0; i < finalArgPos + removed; i++) {
- if (func->argumentRemoved(i + 1))
- removed++;
- }
- }
- return removed;
+ return std::count_if(func->arguments().cbegin(), func->arguments().cend(),
+ [](const AbstractMetaArgument &a) { return a.isModifiedRemoved(); });
}
-bool OverloadData::isSingleArgument(const AbstractMetaFunctionCList &overloads)
+int OverloadData::numberOfRemovedArguments(const AbstractMetaFunctionCPtr &func, int finalArgPos)
{
- bool singleArgument = true;
- for (const auto &func : overloads) {
- if (func->arguments().size() - numberOfRemovedArguments(func) != 1) {
- singleArgument = false;
- break;
- }
+ Q_ASSERT(finalArgPos >= 0);
+ int removed = 0;
+ const auto size = func->arguments().size();
+ for (qsizetype i = 0; i < qMin(size, qsizetype(finalArgPos + removed)); ++i) {
+ if (func->arguments().at(i).isModifiedRemoved())
+ ++removed;
}
- return singleArgument;
+ return removed;
}
void OverloadData::dumpGraph(const QString &filename) const
{
QFile file(filename);
if (file.open(QFile::WriteOnly)) {
- TextStream s(&file);
- s << m_headOverloadData->dumpGraph();
+ QTextStream s(&file);
+ dumpRootGraph(s, m_minArgs, m_maxArgs);
}
}
+QString OverloadData::dumpGraph() const
+{
+ QString result;
+ QTextStream s(&result);
+ dumpRootGraph(s, m_minArgs, m_maxArgs);
+ return result;
+}
+
+bool OverloadData::showGraph() const
+{
+ return showDotGraph(referenceFunction()->name(), dumpGraph());
+}
+
static inline QString toHtml(QString s)
{
- s.replace(QLatin1Char('<'), QLatin1String("&lt;"));
- s.replace(QLatin1Char('>'), QLatin1String("&gt;"));
- s.replace(QLatin1Char('&'), QLatin1String("&amp;"));
+ s.replace(u'<', u"&lt;"_s);
+ s.replace(u'>', u"&gt;"_s);
+ s.replace(u'&', u"&amp;"_s);
return s;
}
-QString OverloadData::dumpGraph() const
+void OverloadDataRootNode::dumpRootGraph(QTextStream &s, int minArgs, int maxArgs) const
{
- QString result;
- QTextStream s(&result);
- if (m_argPos == -1) {
- const auto rfunc = referenceFunction();
- s << "digraph OverloadedFunction {\n";
- s << " graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];\n";
-
- // Shows all function signatures
- s << "legend [fontsize=9 fontname=freemono shape=rect label=\"";
- for (const auto &func : m_overloads) {
- s << "f" << functionNumber(func) << " : "
- << toHtml(func->type().cppSignature())
- << ' ' << toHtml(func->minimalSignature()) << "\\l";
- }
- s << "\"];\n";
-
- // Function box title
- s << " \"" << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 ";
- s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
- s << "<tr><td bgcolor=\"black\" align=\"center\" cellpadding=\"6\" colspan=\"2\"><font color=\"white\">";
- if (rfunc->ownerClass())
- s << rfunc->ownerClass()->name() << "::";
- s << toHtml(rfunc->name()) << "</font>";
- if (rfunc->isVirtual()) {
- s << "<br/><font color=\"white\" point-size=\"10\">&lt;&lt;";
- if (rfunc->isAbstract())
- s << "pure ";
- s << "virtual&gt;&gt;</font>";
- }
- s << "</td></tr>";
+ const auto rfunc = referenceFunction();
+ s << "digraph OverloadedFunction {\n";
+ s << " graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];\n";
- // Function return type
- s << "<tr><td bgcolor=\"gray\" align=\"right\">original type</td><td bgcolor=\"gray\" align=\"left\">"
- << toHtml(rfunc->type().cppSignature())
- << "</td></tr>";
+ // Shows all function signatures
+ s << "legend [fontsize=9 fontname=freemono shape=rect label=\"";
+ for (const auto &func : m_overloads) {
+ s << "f" << functionNumber(func) << " : "
+ << toHtml(func->type().cppSignature())
+ << ' ' << toHtml(func->minimalSignature()) << "\\l";
+ }
+ s << "\"];\n";
+
+ // Function box title
+ s << " \"" << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 ";
+ s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
+ s << "<tr><td bgcolor=\"black\" align=\"center\" cellpadding=\"6\" colspan=\"2\"><font color=\"white\">";
+ if (rfunc->ownerClass())
+ s << rfunc->ownerClass()->name() << "::";
+ s << toHtml(rfunc->name()) << "</font>";
+ if (rfunc->isVirtual()) {
+ s << "<br/><font color=\"white\" point-size=\"10\">&lt;&lt;";
+ if (rfunc->isAbstract())
+ s << "pure ";
+ s << "virtual&gt;&gt;</font>";
+ }
+ s << "</td></tr>";
+
+ // Function return type
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">original type</td><td bgcolor=\"gray\" align=\"left\">"
+ << toHtml(rfunc->type().cppSignature())
+ << "</td></tr>";
+
+ // Shows type changes for all function signatures
+ for (const auto &func : m_overloads) {
+ if (!func->isTypeModified())
+ continue;
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
+ s << "-type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(func->modifiedTypeName()) << "</td></tr>";
+ }
- // Shows type changes for all function signatures
- for (const auto &func : m_overloads) {
- if (func->typeReplaced(0).isEmpty())
- continue;
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-type</td><td bgcolor=\"gray\" align=\"left\">";
- s << toHtml(func->typeReplaced(0)) << "</td></tr>";
- }
+ // Minimum and maximum number of arguments
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">minArgs</td><td bgcolor=\"gray\" align=\"left\">";
+ s << minArgs << "</td></tr>";
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">maxArgs</td><td bgcolor=\"gray\" align=\"left\">";
+ s << maxArgs << "</td></tr>";
- // Minimum and maximum number of arguments
- s << "<tr><td bgcolor=\"gray\" align=\"right\">minArgs</td><td bgcolor=\"gray\" align=\"left\">";
- s << minArgs() << "</td></tr>";
- s << "<tr><td bgcolor=\"gray\" align=\"right\">maxArgs</td><td bgcolor=\"gray\" align=\"left\">";
- s << maxArgs() << "</td></tr>";
-
- if (rfunc->ownerClass()) {
- if (rfunc->implementingClass() != rfunc->ownerClass())
- s << "<tr><td align=\"right\">implementor</td><td align=\"left\">" << rfunc->implementingClass()->name() << "</td></tr>";
- if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass())
- s << "<tr><td align=\"right\">declarator</td><td align=\"left\">" << rfunc->declaringClass()->name() << "</td></tr>";
- }
+ if (rfunc->ownerClass()) {
+ if (rfunc->implementingClass() != rfunc->ownerClass())
+ s << "<tr><td align=\"right\">implementor</td><td align=\"left\">" << rfunc->implementingClass()->name() << "</td></tr>";
+ if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass())
+ s << "<tr><td align=\"right\">declarator</td><td align=\"left\">" << rfunc->declaringClass()->name() << "</td></tr>";
+ }
- // Overloads for the signature to present point
- s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
- for (const auto &func : m_overloads)
- s << 'f' << functionNumber(func) << ' ';
- s << "</td></tr>";
+ // Overloads for the signature to present point
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
+ for (const auto &func : m_overloads)
+ s << 'f' << functionNumber(func) << ' ';
+ s << "</td></tr>";
- s << "</table>> ];\n";
+ s << "</table>> ];\n";
- for (const OverloadData *pd : m_nextOverloadData)
- s << " \"" << rfunc->name() << "\" -> " << pd->dumpGraph();
+ for (const auto &pd : m_children) {
+ s << " \"" << rfunc->name() << "\" -> ";
+ pd->dumpNodeGraph(s);
+ }
- s << "}\n";
- } else {
- QString argId = QLatin1String("arg_") + QString::number(quintptr(this));
- s << argId << ";\n";
+ s << "}\n";
+}
- s << " \"" << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 ";
- s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
+void OverloadDataNode::dumpNodeGraph(QTextStream &s) const
+{
+ QString argId = u"arg_"_s + QString::number(quintptr(this));
+ s << argId << ";\n";
- // Argument box title
- s << "<tr><td bgcolor=\"black\" align=\"left\" cellpadding=\"2\" colspan=\"2\">";
- s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>";
+ s << " \"" << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 ";
+ s << "label=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
- // Argument type information
- QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType().cppSignature();
- s << "<tr><td bgcolor=\"gray\" align=\"right\">type</td><td bgcolor=\"gray\" align=\"left\">";
- s << toHtml(type) << "</td></tr>";
- if (hasArgumentTypeReplace()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">";
- s << toHtml(argType().cppSignature()) << "</td></tr>";
- }
+ // Argument box title
+ s << "<tr><td bgcolor=\"black\" align=\"left\" cellpadding=\"2\" colspan=\"2\">";
+ s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>";
- // Overloads for the signature to present point
- s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
- for (const auto &func : m_overloads)
- s << 'f' << functionNumber(func) << ' ';
- s << "</td></tr>";
+ // Argument type information
+ const QString type = modifiedArgType().cppSignature();
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(type) << "</td></tr>";
+ if (isTypeModified()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(argType().cppSignature()) << "</td></tr>";
+ }
- // Show default values (original and modified) for various functions
- for (const auto &func : m_overloads) {
- const AbstractMetaArgument *arg = argument(func);
- if (!arg)
- continue;
- QString argDefault = arg->defaultValueExpression();
- if (!argDefault.isEmpty() ||
- argDefault != arg->originalDefaultValueExpression()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-default</td><td bgcolor=\"gray\" align=\"left\">";
- s << argDefault << "</td></tr>";
- }
- if (argDefault != arg->originalDefaultValueExpression()) {
- s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
- s << "-orig-default</td><td bgcolor=\"gray\" align=\"left\">";
- s << arg->originalDefaultValueExpression() << "</td></tr>";
- }
- }
+ const OverloadDataRootNode *root = this;
+ while (!root->isRoot())
+ root = root->parent();
- s << "</table>>];\n";
+ // Overloads for the signature to present point
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
+ for (const auto &func : m_overloads)
+ s << 'f' << root->functionNumber(func) << ' ';
+ s << "</td></tr>";
- for (const OverloadData *pd : m_nextOverloadData)
- s << " " << argId << " -> " << pd->dumpGraph();
+ // Show default values (original and modified) for various functions
+ for (const auto &func : m_overloads) {
+ const AbstractMetaArgument *arg = overloadArgument(func);
+ if (!arg)
+ continue;
+ const int n = root->functionNumber(func);
+ QString argDefault = arg->defaultValueExpression();
+ if (!argDefault.isEmpty() ||
+ argDefault != arg->originalDefaultValueExpression()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << n;
+ s << "-default</td><td bgcolor=\"gray\" align=\"left\">";
+ s << argDefault << "</td></tr>";
+ }
+ if (argDefault != arg->originalDefaultValueExpression()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << n;
+ s << "-orig-default</td><td bgcolor=\"gray\" align=\"left\">";
+ s << arg->originalDefaultValueExpression() << "</td></tr>";
+ }
}
- return result;
-}
-int OverloadData::functionNumber(const AbstractMetaFunctionCPtr &func) const
-{
- return m_headOverloadData->m_overloads.indexOf(func);
-}
+ s << "</table>>];\n";
-OverloadData::~OverloadData()
-{
- while (!m_nextOverloadData.isEmpty())
- delete m_nextOverloadData.takeLast();
+ for (const auto &pd : m_children) {
+ s << " " << argId << " -> ";
+ pd->dumpNodeGraph(s);
+ }
}
-bool OverloadData::hasArgumentTypeReplace() const
+int OverloadDataRootNode::functionNumber(const AbstractMetaFunctionCPtr &func) const
{
- return !m_argTypeReplaced.isEmpty();
+ return m_overloads.indexOf(func);
}
-QString OverloadData::argumentTypeReplaced() const
+bool OverloadData::pythonFunctionWrapperUsesListOfArguments() const
{
- return m_argTypeReplaced;
+ auto referenceFunction = m_overloads.constFirst();
+ if (referenceFunction->isCallOperator())
+ return true;
+ if (referenceFunction->isOperatorOverload())
+ return false;
+ const int maxArgs = this->maxArgs();
+ const int minArgs = this->minArgs();
+ return (minArgs != maxArgs)
+ || (maxArgs > 1)
+ || referenceFunction->isConstructor()
+ || hasArgumentWithDefaultValue();
}
bool OverloadData::hasArgumentWithDefaultValue() const
@@ -985,9 +906,7 @@ bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunctionCPtr &f
{
const AbstractMetaArgumentList &arguments = func->arguments();
for (const AbstractMetaArgument &arg : arguments) {
- if (func->argumentRemoved(arg.argumentIndex() + 1))
- continue;
- if (arg.hasDefaultValueExpression())
+ if (!arg.isModifiedRemoved() && arg.hasDefaultValueExpression())
return true;
}
return false;
@@ -999,7 +918,7 @@ AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const Abstr
const AbstractMetaArgumentList &arguments = func->arguments();
for (const AbstractMetaArgument &arg : arguments) {
if (!arg.hasDefaultValueExpression()
- || func->argumentRemoved(arg.argumentIndex() + 1))
+ || arg.isModifiedRemoved())
continue;
args << arg;
}
@@ -1007,9 +926,9 @@ AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const Abstr
}
#ifndef QT_NO_DEBUG_STREAM
-void OverloadData::formatDebug(QDebug &d) const
+
+void OverloadDataRootNode::formatReferenceFunction(QDebug &d) const
{
- const qsizetype count = m_overloads.size();
auto refFunc = referenceFunction();
d << '"';
if (auto owner = refFunc->ownerClass())
@@ -1017,36 +936,76 @@ void OverloadData::formatDebug(QDebug &d) const
d << refFunc->minimalSignature() << '"';
if (m_overloads.constFirst()->isReverseOperator())
d << " [reverseop]";
- d << ", argType=" << m_argType << ", minArgs=" << m_minArgs << ", maxArgs=" << m_maxArgs
- << ", argPos=" << m_argPos;
- if (!m_argTypeReplaced.isEmpty())
- d << ", argTypeReplaced=\"" << m_argTypeReplaced << '"';
+}
+void OverloadDataRootNode::formatOverloads(QDebug &d) const
+{
+ const qsizetype count = m_overloads.size();
+ d << ", overloads[" << count << ']';
if (count < 2)
return;
- d << "\", overloads[" << count << "]=(";
- const int oldVerbosity = d.verbosity();
- d.setVerbosity(3);
- for (int i = 0; i < count; ++i) {
- if (i)
- d << '\n';
- d << m_overloads.at(i).data();
- }
- d.setVerbosity(oldVerbosity);
- d << ')';
+ d << "=(";
+ for (qsizetype i = 0; i < count; ++i) {
+ if (i)
+ d << '\n';
+ d << m_overloads.at(i)->signature();
+ }
+ d << ')';
}
-QDebug operator<<(QDebug d, const OverloadData *od)
+void OverloadDataRootNode::formatNextOverloadData(QDebug &d) const
+{
+ const qsizetype count = m_children.size();
+ d << ", next[" << count << ']';
+ if (d.verbosity() >= 3) {
+ d << "=(";
+ for (qsizetype i = 0; i < count; ++i) {
+ if (i)
+ d << '\n';
+ m_children.at(i)->formatDebug(d);
+ }
+ d << ')';
+ }
+}
+
+void OverloadDataRootNode::formatDebug(QDebug &d) const
+{
+ formatReferenceFunction(d);
+ formatOverloads(d);
+ formatNextOverloadData(d);
+}
+
+void OverloadDataNode::formatDebug(QDebug &d) const
+{
+ d << "OverloadDataNode(";
+ formatReferenceFunction(d);
+ d << ", argPos=" << m_argPos;
+ if (m_argument.argumentIndex() != m_argPos)
+ d << ", argIndex=" << m_argument.argumentIndex();
+ d << ", argType=\"" << m_argument.type().cppSignature() << '"';
+ if (isTypeModified())
+ d << ", modifiedArgType=\"" << modifiedArgType().cppSignature() << '"';
+ formatOverloads(d);
+ formatNextOverloadData(d);
+ d << ')';
+}
+
+void OverloadData::formatDebug(QDebug &d) const
+{
+ d << "OverloadData(";
+ formatReferenceFunction(d);
+ d << ", minArgs=" << m_minArgs << ", maxArgs=" << m_maxArgs;
+ formatOverloads(d);
+ formatNextOverloadData(d);
+ d << ')';
+}
+
+QDebug operator<<(QDebug d, const OverloadData &od)
{
QDebugStateSaver saver(d);
d.noquote();
d.nospace();
- d << "OverloadData(";
- if (od)
- od->formatDebug(d);
- else
- d << '0';
- d << ')';
+ od.formatDebug(d);
return d;
}
#endif // !QT_NO_DEBUG_STREAM