aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-09-14 13:52:14 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-10-01 11:24:55 +0200
commit2edf0042bb23fa8528dfb964377dae5bd35ee932 (patch)
treecafc76b224135aef870fe60e3215c18eb3ded1b0
parent6c62738a9a051c4e06444c6d37c766f7ccc696c8 (diff)
shiboken6: Refactor modified types of functions
Remove AbstractMetaFunction::typeReplaced(), which returned the modified type of an argument or the return type as a string. Instead, for function arguments, for which modified types must always be valid AbstractMetaTypes, add a getter modifiedType() returning an AbstractMetaType to AbstractMetaArgument. This fixes a number of potential bugs when accessing typeReplaced(int) with the wrong position due to removed arguments. The modified argument types are parsed from the XML strings in early on in AbstractMetaClass::fixFunctions() with proper error reporting. For return types, for which modified types need to be valid only when generating a type check for virtual method return in the C++ wrapper, add a function modifiedTypeName() to AbstractMetaFunction. Adapt the client code accordingly. Split apart CppGenerator::writeTypeCheck() into one overload taking an AbstractMetaType and one taking a string. Task-number: PYSIDE-1660 Change-Id: Id95379892b40ae2632ca33ed27263bada0ec015d Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaargument.cpp14
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaargument.h3
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp1
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.cpp77
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafunction.h6
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp5
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp27
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h6
-rw-r--r--sources/shiboken6/ApiExtractor/modifications.cpp7
-rw-r--r--sources/shiboken6/ApiExtractor/modifications.h3
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp83
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h8
-rw-r--r--sources/shiboken6/generator/shiboken/overloaddata.cpp38
-rw-r--r--sources/shiboken6/generator/shiboken/overloaddata.h4
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp37
15 files changed, 199 insertions, 120 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
index 366fc00a1..539234249 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.cpp
@@ -39,6 +39,7 @@ public:
QString m_name;
AbstractMetaType m_type;
+ AbstractMetaType m_modifiedType;
bool m_hasName = false;
Documentation m_doc;
QString m_expression;
@@ -68,7 +69,18 @@ const AbstractMetaType &AbstractMetaArgument::type() const
void AbstractMetaArgument::setType(const AbstractMetaType &type)
{
if (d->m_type != type)
- d->m_type = type;
+ d->m_type = d->m_modifiedType = type;
+}
+
+const AbstractMetaType &AbstractMetaArgument::modifiedType() const
+{
+ return d->m_modifiedType;
+}
+
+void AbstractMetaArgument::setModifiedType(const AbstractMetaType &type)
+{
+ if (d->m_modifiedType != type)
+ d->m_modifiedType = type;
}
QString AbstractMetaArgument::name() const
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaargument.h b/sources/shiboken6/ApiExtractor/abstractmetaargument.h
index b5fe22db7..93dab6f79 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaargument.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaargument.h
@@ -54,6 +54,9 @@ public:
const AbstractMetaType &type() const;
void setType(const AbstractMetaType &type);
+ void setModifiedType(const AbstractMetaType &type);
+ const AbstractMetaType &modifiedType() const;
+ bool isTypeModified() const { return modifiedType() != type(); }
QString name() const;
void setName(const QString &name, bool realName = true);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 32c7e99fd..d27dc4abb 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -506,6 +506,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
metaFunc->setTypeEntry(funcEntry);
applyFunctionModifications(metaFunc);
+ metaFunc->applyTypeModifications();
setInclude(funcEntry, func->fileName());
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
index 2d9ee3dcb..05b598811 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.cpp
@@ -33,6 +33,7 @@
#include "abstractmetatype.h"
#include <codemodel.h>
#include "documentation.h"
+#include "exception.h"
#include "messages.h"
#include "modifications.h"
#include "propertyspec.h"
@@ -75,6 +76,9 @@ public:
const FunctionModificationList &modifications(const AbstractMetaFunction *q,
const AbstractMetaClass *implementor) const;
+ bool applyTypeModification(const AbstractMetaFunction *q,
+ const QString &type, int number, QString *errorMessage);
+
QString m_name;
QString m_originalName;
Documentation m_doc;
@@ -85,6 +89,7 @@ public:
FunctionTypeEntry* m_typeEntry = nullptr;
AbstractMetaFunction::FunctionType m_functionType = AbstractMetaFunction::NormalFunction;
AbstractMetaType m_type;
+ QString m_modifiedTypeName;
const AbstractMetaClass *m_class = nullptr;
const AbstractMetaClass *m_implementingClass = nullptr;
const AbstractMetaClass *m_declaringClass = nullptr;
@@ -421,6 +426,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const
cpy->setExceptionSpecification(d->m_exceptionSpecification);
cpy->setAllowThreadModification(d->m_allowThreadModification);
cpy->setExceptionHandlingModification(d->m_exceptionHandlingModification);
+ cpy->d->m_modifiedTypeName = d->m_modifiedTypeName;
cpy->d->m_addedFunction = d->m_addedFunction;
cpy->d->m_arguments = d->m_arguments;
@@ -770,18 +776,9 @@ TypeSystem::Ownership AbstractMetaFunction::argumentTargetOwnership(const Abstra
return TypeSystem::UnspecifiedOwnership;
}
-QString AbstractMetaFunction::typeReplaced(int key) const
+const QString &AbstractMetaFunction::modifiedTypeName() const
{
- for (const auto &modification : modifications(declaringClass())) {
- for (const ArgumentModification &argumentModification : modification.argument_mods()) {
- if (argumentModification.index() == key
- && !argumentModification.modifiedType().isEmpty()) {
- return argumentModification.modifiedType();
- }
- }
- }
-
- return QString();
+ return d->m_modifiedTypeName;
}
bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const
@@ -795,6 +792,48 @@ bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const
return false;
}
+// Note: The declaring class must be correctly set for this to work.
+bool AbstractMetaFunctionPrivate::applyTypeModification(const AbstractMetaFunction *q,
+ const QString &type,
+ int number, QString *errorMessage)
+{
+ if (number < 0 || number > m_arguments.size()) {
+ *errorMessage =
+ msgTypeModificationFailed(type, number, q,
+ msgArgumentOutOfRange(number, 0, m_arguments.size()));
+ return false;
+ }
+
+ // Modified return types may have unparseable types like Python tuples
+ if (number == 0) {
+ m_modifiedTypeName = type;
+ return true;
+ }
+
+ auto typeOpt = AbstractMetaType::fromString(type, errorMessage);
+ if (!typeOpt.has_value()) {
+ *errorMessage = msgTypeModificationFailed(type, number, q, *errorMessage);
+ return false;
+ }
+ m_arguments[number - 1].setModifiedType(typeOpt.value());
+ return true;
+}
+
+void AbstractMetaFunction::applyTypeModifications()
+{
+ QString errorMessage;
+ for (const auto &modification : modifications(declaringClass())) {
+ for (const ArgumentModification &am : modification.argument_mods()) {
+ const int n = am.index();
+ if (am.isTypeModified()
+ && !d->applyTypeModification(this, am.modifiedType(),
+ n, &errorMessage)) {
+ throw Exception(errorMessage);
+ }
+ }
+ }
+}
+
QString AbstractMetaFunction::pyiTypeReplaced(int argumentIndex) const
{
for (const auto &modification : modifications(declaringClass())) {
@@ -822,12 +861,9 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu
if (i > 0)
result += QLatin1Char(',');
- QString typeName;
- if (comment)
- typeName = q->typeReplaced(i + 1);
- if (typeName.isEmpty())
- typeName = m_arguments.at(i).type().minimalSignature();
- result += typeName;
+ result += comment
+ ? m_arguments.at(i).modifiedType().minimalSignature()
+ : m_arguments.at(i).type().minimalSignature();
}
result += QLatin1Char(')');
if (m_constant)
@@ -835,10 +871,9 @@ QString AbstractMetaFunctionPrivate::formatMinimalSignature(const AbstractMetaFu
result = TypeDatabase::normalizedSignature(result);
if (comment && !q->isVoid()) {
- QString typeName = q->typeReplaced(0);
- if (typeName.isEmpty())
- typeName = q->type().minimalSignature();
- result += QStringLiteral("->") + typeName;
+ result += u"->"_qs;
+ result += q->isTypeModified()
+ ? q->modifiedTypeName() : q->type().minimalSignature();
}
return result;
}
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafunction.h b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
index 415fc4ae2..9bad1cd44 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafunction.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetafunction.h
@@ -308,9 +308,13 @@ public:
// Returns the ownership rules for the given argument (target lang).
TypeSystem::Ownership argumentTargetOwnership(const AbstractMetaClass *cls, int idx) const;
- QString typeReplaced(int argument_index) const;
+ const QString &modifiedTypeName() const;
+ bool isTypeModified() const { return !modifiedTypeName().isEmpty(); }
+
bool isModifiedToArray(int argumentIndex) const;
+ void applyTypeModifications();
+
/// Return the (modified) type for the signature; modified-pyi-type, modified-type
QString pyiTypeReplaced(int argumentIndex) const;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
index 3e42f40ac..9e6b3d44e 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
@@ -1562,11 +1562,14 @@ void AbstractMetaClass::fixFunctions()
bool hasPrivateConstructors = false;
bool hasPublicConstructors = false;
+ // Apply modifications after the declaring class has been set
for (const auto &func : qAsConst(funcs)) {
+ auto ncFunc = qSharedPointerConstCast<AbstractMetaFunction>(func);
for (const auto &mod : func->modifications(this)) {
if (mod.isRenameModifier())
- qSharedPointerConstCast<AbstractMetaFunction>(func)->setName(mod.renamedToName());
+ ncFunc->setName(mod.renamedToName());
}
+ ncFunc->applyTypeModifications();
// Make sure class is abstract if one of the functions is
if (func->isAbstract()) {
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index ff4a9fa42..b7a1e9091 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -77,6 +77,33 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass,
return result;
}
+QString msgTypeModificationFailed(const QString &type, int n,
+ const AbstractMetaFunction *func,
+ const QString &why)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "Unable to modify the ";
+ if (n == 0)
+ str << "return type";
+ else
+ str << "type of argument " << n;
+
+ str << " of ";
+ if (auto *c = func->ownerClass())
+ str << c->name() << "::";
+ str << func->signature() << " to \"" << type << "\": " << why;
+ return result;
+}
+
+QString msgArgumentOutOfRange(int number, int minValue, int maxValue)
+{
+ QString result;
+ QTextStream(&result) << "Argument number " << number
+ << " out of range " << minValue << ".." << maxValue << '.';
+ return result;
+}
+
template <class Stream>
static void msgFormatEnumType(Stream &str,
const EnumModelItem &enumItem,
diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h
index fb4b28e26..0accbd449 100644
--- a/sources/shiboken6/ApiExtractor/messages.h
+++ b/sources/shiboken6/ApiExtractor/messages.h
@@ -66,6 +66,12 @@ QString msgNoFunctionForModification(const AbstractMetaClass *klass,
const QStringList &possibleSignatures,
const AbstractMetaFunctionCList &allFunctions);
+QString msgTypeModificationFailed(const QString &type, int n,
+ const AbstractMetaFunction *func,
+ const QString &why);
+
+QString msgArgumentOutOfRange(int number, int minValue, int maxValue);
+
QString msgClassOfEnumNotFound(const EnumTypeEntry *entry);
QString msgNoEnumTypeEntry(const EnumModelItem &enumItem,
diff --git a/sources/shiboken6/ApiExtractor/modifications.cpp b/sources/shiboken6/ApiExtractor/modifications.cpp
index 8c6f31187..92b445791 100644
--- a/sources/shiboken6/ApiExtractor/modifications.cpp
+++ b/sources/shiboken6/ApiExtractor/modifications.cpp
@@ -481,7 +481,7 @@ ArgumentModification::ArgumentModification(ArgumentModification &&) = default;
ArgumentModification &ArgumentModification::operator=(ArgumentModification &&) = default;
ArgumentModification::~ArgumentModification() = default;
-QString ArgumentModification::modifiedType() const
+const QString &ArgumentModification::modifiedType() const
{
return d->modified_type;
}
@@ -492,6 +492,11 @@ void ArgumentModification::setModifiedType(const QString &value)
d->modified_type = value;
}
+bool ArgumentModification::isTypeModified() const
+{
+ return !d->modified_type.isEmpty();
+}
+
QString ArgumentModification::pyiType() const
{
return d->pyiType;
diff --git a/sources/shiboken6/ApiExtractor/modifications.h b/sources/shiboken6/ApiExtractor/modifications.h
index 291f80545..917dd7459 100644
--- a/sources/shiboken6/ApiExtractor/modifications.h
+++ b/sources/shiboken6/ApiExtractor/modifications.h
@@ -190,8 +190,9 @@ public:
void addReferenceCount(const ReferenceCount &value);
// The text given for the new type of the argument
- QString modifiedType() const;
+ const QString &modifiedType() const;
void setModifiedType(const QString &value);
+ bool isTypeModified() const;
QString pyiType() const;
void setPyiType(const QString &value);
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 4fd5d4094..8aba8cd20 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -860,8 +860,8 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
if (func->type().isVoid())
return QLatin1String("\"\"");
- if (!func->typeReplaced(0).isEmpty())
- return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"');
+ if (func->isTypeModified())
+ return u'"' + func->modifiedTypeName() + u'"';
// SbkType would return null when the type is a container.
auto typeEntry = func->type().typeEntry();
@@ -1168,10 +1168,10 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
if (invalidateReturn)
s << "bool invalidateArg0 = " << PYTHON_RETURN_VAR << "->ob_refcnt == 1;\n";
- if (func->typeReplaced(0) != cPyObjectT()) {
+ if (func->modifiedTypeName() != cPyObjectT()) {
s << "// Check return type\n";
- if (func->typeReplaced(0).isEmpty()) {
+ if (!func->isTypeModified()) {
s << PYTHON_TO_CPPCONVERSION_STRUCT
<< ' ' << PYTHON_TO_CPP_VAR << " = "
<< cpythonIsConvertibleFunction(func->type())
@@ -1192,8 +1192,15 @@ void CppGenerator::writeVirtualMethodNative(TextStream &s,
s << "// Check return type\n"
<< "bool typeIsValid = ";
- writeTypeCheck(s, func->type(), QLatin1String(PYTHON_RETURN_VAR),
- isNumber(func->type().typeEntry()), func->typeReplaced(0));
+ if (func->isTypeModified()) {
+ writeTypeCheck(s, func->modifiedTypeName(),
+ QLatin1String(PYTHON_RETURN_VAR));
+ } else {
+ const bool numberType = isNumber(func->type().typeEntry());
+ writeTypeCheck(s, func->type(),
+ QLatin1String(PYTHON_RETURN_VAR), numberType);
+ }
+
s << ";\n";
s << "if (!typeIsValid";
if (func->type().isPointerToWrapperType())
@@ -1570,9 +1577,10 @@ return result;)";
toCppConv = QLatin1Char('*') + cpythonWrapperCPtr(sourceClass->typeEntry(), QLatin1String("pyIn"));
} else {
// Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1))
+ const auto &firstArg = conv->arguments().constFirst();
+ if (firstArg.isTypeModified() || conv->isModifiedToArray(1))
continue;
- const AbstractMetaType sourceType = conv->arguments().constFirst().type();
+ const AbstractMetaType &sourceType = firstArg.type();
typeCheck = cpythonCheckFunction(sourceType);
bool isUserPrimitiveWithoutTargetLangName = sourceType.isUserPrimitive()
&& !sourceType.typeEntry()->hasTargetLangApiType();
@@ -1750,9 +1758,10 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
sourceType = AbstractMetaType::fromAbstractMetaClass(conv->ownerClass());
} else {
// Constructor that does implicit conversion.
- if (!conv->typeReplaced(1).isEmpty() || conv->isModifiedToArray(1))
+ const auto &firstArg = conv->arguments().constFirst();
+ if (firstArg.isTypeModified() || conv->isModifiedToArray(1))
continue;
- sourceType = conv->arguments().constFirst().type();
+ sourceType = firstArg.type();
}
QString toCpp = pythonToCppFunctionName(sourceType, targetType);
QString isConv = convertibleToCppFunctionName(sourceType, targetType);
@@ -2383,18 +2392,21 @@ static QString pythonToCppConverterForArgumentName(const QString &argumentName)
return result;
}
-void CppGenerator::writeTypeCheck(TextStream &s, AbstractMetaType argType,
- const QString &argumentName, bool isNumber,
- const QString &customType, bool rejectNull) const
+void CppGenerator::writeTypeCheck(TextStream &s, const QString &customType,
+ const QString &argumentName) const
{
- if (!customType.isEmpty()) {
- QString errorMessage;
- const auto metaTypeOpt = AbstractMetaType::fromString(customType, &errorMessage);
- if (!metaTypeOpt.has_value())
- throw Exception(errorMessage);
- argType = metaTypeOpt.value();
- }
+ QString errorMessage;
+ const auto metaTypeOpt = AbstractMetaType::fromString(customType, &errorMessage);
+ if (!metaTypeOpt.has_value())
+ throw Exception(errorMessage);
+ writeTypeCheck(s, metaTypeOpt.value(), argumentName,
+ ShibokenGenerator::isNumber(metaTypeOpt.value()));
+}
+void CppGenerator::writeTypeCheck(TextStream &s, const AbstractMetaType &argType,
+ const QString &argumentName, bool isNumber,
+ bool rejectNull) const
+{
// TODO-CONVERTER: merge this with the code below.
QString typeCheck = cpythonIsConvertibleFunction(argType);
typeCheck.append(u'(' +argumentName + u')');
@@ -2419,13 +2431,16 @@ void CppGenerator::writeTypeCheck(TextStream &s, AbstractMetaType argType,
static void checkTypeViability(const AbstractMetaFunctionCPtr &func,
const AbstractMetaType &type, int argIdx)
{
+ const bool modified = argIdx == 0
+ ? func->isTypeModified()
+ : func->arguments().at(argIdx -1).isTypeModified();
if (type.isVoid()
|| !type.typeEntry()->isPrimitive()
|| type.indirections() == 0
|| (type.indirections() == 1 && type.typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern)
|| type.isCString()
|| func->argumentRemoved(argIdx)
- || !func->typeReplaced(argIdx).isEmpty()
+ || modified
|| !func->conversionRule(TypeSystem::All, argIdx).isEmpty()
|| func->hasInjectedCode())
return;
@@ -2473,14 +2488,13 @@ void CppGenerator::writeTypeCheck(TextStream &s,
// This condition trusts that the OverloadData object will arrange for
// PyLong type to come after the more precise numeric types (e.g. float and bool)
- AbstractMetaType argType = overloadData->argType();
+ AbstractMetaType argType = overloadData->modifiedArgType();
if (auto viewOn = argType.viewOn())
argType = *viewOn;
bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType);
- QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : QString());
bool rejectNull =
shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos());
- writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull);
+ writeTypeCheck(s, argType, argumentName, numberType, rejectNull);
}
void CppGenerator::writeArgumentConversion(TextStream &s,
@@ -2508,16 +2522,8 @@ AbstractMetaType
return {};
}
- QString typeReplaced = func->typeReplaced(index + 1);
- if (typeReplaced.isEmpty()) {
- auto argType = func->arguments().at(index).type();
- return argType.viewOn() ? *argType.viewOn() : argType;
- }
-
- auto argType = AbstractMetaType::fromString(typeReplaced);
- if (!argType.has_value())
- throw Exception(msgUnknownTypeInArgumentTypeReplacement(typeReplaced, func.data()));
- return argType.value();
+ auto argType = func->arguments().at(index).modifiedType();
+ return argType.viewOn() ? *argType.viewOn() : argType;
}
static inline QString arrayHandleType(const AbstractMetaTypeList &nestedArrayTypes)
@@ -2870,7 +2876,8 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(TextStream &s,
int startArg = od->argPos();
int sequenceArgCount = 0;
while (od && !od->argType().isVarargs()) {
- bool typeReplacedByPyObject = od->argumentTypeReplaced() == cPyObjectT();
+ const bool typeReplacedByPyObject = od->isTypeModified()
+ && od->modifiedArgType().name() == cPyObjectT();
if (!typeReplacedByPyObject) {
if (usePyArgs)
pyArgName = pythonArgsAt(od->argPos());
@@ -3401,8 +3408,8 @@ void CppGenerator::writeNamedArgumentResolution(TextStream &s, const AbstractMet
{
Indentation indent(s);
s << pyArgName << " = value;\nif (!";
- writeTypeCheck(s, arg.type(), pyArgName, isNumber(arg.type().typeEntry()),
- func->typeReplaced(arg.argumentIndex() + 1));
+ const auto &type = arg.modifiedType();
+ writeTypeCheck(s, type, pyArgName, isNumber(type.typeEntry()), {});
s << ")\n";
{
Indentation indent(s);
@@ -6565,7 +6572,7 @@ void CppGenerator::writeReturnValueHeuristics(TextStream &s, const AbstractMetaF
|| type.isVoid()
|| func->isStatic()
|| func->isConstructor()
- || !func->typeReplaced(0).isEmpty()) {
+ || func->isTypeModified()) {
return;
}
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index 8181e5711..3e3e5a21d 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -142,9 +142,11 @@ private:
/// Writes the check section for the validity of wrapped C++ objects.
static void writeInvalidPyObjectCheck(TextStream &s, const QString &pyObj);
- void writeTypeCheck(TextStream &s, AbstractMetaType argType, const QString &argumentName,
- bool isNumber = false, const QString &customType = QString(),
- bool rejectNull = false) const;
+ void writeTypeCheck(TextStream &s, const AbstractMetaType &argType,
+ const QString &argumentName,
+ bool isNumber = false, bool rejectNull = false) const;
+ void writeTypeCheck(TextStream &s, const QString &customType,
+ const QString &argumentName) const;
void writeTypeCheck(TextStream& s, const QSharedPointer<OverloadDataNode> &overloadData,
const QString &argumentName) const;
diff --git a/sources/shiboken6/generator/shiboken/overloaddata.cpp b/sources/shiboken6/generator/shiboken/overloaddata.cpp
index 46a2ee201..3f0e484e8 100644
--- a/sources/shiboken6/generator/shiboken/overloaddata.cpp
+++ b/sources/shiboken6/generator/shiboken/overloaddata.cpp
@@ -64,11 +64,6 @@ static QString getTypeName(const AbstractMetaType &type)
return typeName;
}
-static QString getTypeName(const OverloadDataNodePtr &ov)
-{
- return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType());
-}
-
static bool typesAreEqual(const AbstractMetaType &typeA, const AbstractMetaType &typeB)
{
if (typeA.typeEntry() == typeB.typeEntry()) {
@@ -199,7 +194,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
OverloadGraph graph;
for (const auto &ov : qAsConst(m_children)) {
- const QString typeName = getTypeName(ov);
+ const QString typeName = getTypeName(ov->modifiedArgType());
auto it = typeToOverloads.find(typeName);
if (it == typeToOverloads.end()) {
typeToOverloads.insert(typeName, {ov});
@@ -261,7 +256,7 @@ void OverloadDataRootNode::sortNextOverloads(const ApiExtractorResult &api)
for (const auto &ov : qAsConst(m_children)) {
const AbstractMetaType &targetType = ov->argType();
- const QString targetTypeEntryName = getTypeName(ov);
+ const QString targetTypeEntryName = getTypeName(ov->modifiedArgType());
// Process implicit conversions
const auto &functions = api.implicitConversions(targetType);
@@ -505,7 +500,6 @@ void OverloadDataNode::addOverload(const AbstractMetaFunctionCPtr &func)
OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFunctionCPtr &func,
const AbstractMetaArgument &arg)
{
- const AbstractMetaType &argType = arg.type();
OverloadDataNodePtr overloadData;
if (!func->isOperatorOverload()) {
for (const auto &tmp : qAsConst(m_children)) {
@@ -513,10 +507,7 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu
// 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->argPos() + 1);
- bool argsReplaced = !replacedArg.isEmpty() || tmp->hasArgumentTypeReplace();
- if ((!argsReplaced && typesAreEqual(tmp->argType(), argType))
- || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) {
+ if (typesAreEqual(tmp->modifiedArgType(), arg.modifiedType())) {
tmp->addOverload(func);
overloadData = tmp;
}
@@ -524,10 +515,8 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu
}
if (overloadData.isNull()) {
- QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1);
const int argpos = argPos() + 1;
- overloadData.reset(new OverloadDataNode(func, this, arg, argpos,
- typeReplaced));
+ overloadData.reset(new OverloadDataNode(func, this, arg, argpos));
m_children.append(overloadData);
}
@@ -537,12 +526,11 @@ OverloadDataNode *OverloadDataRootNode::addOverloadDataNode(const AbstractMetaFu
bool OverloadData::hasNonVoidReturnType() const
{
for (const auto &func : m_overloads) {
- const QString typeReplaced = func->typeReplaced(0);
- if (typeReplaced.isEmpty()) {
- if (!func->argumentRemoved(0) && !func->type().isVoid())
+ if (func->isTypeModified()) {
+ if (func->modifiedTypeName() != u"void")
return true;
} else {
- if (typeReplaced != u"void")
+ if (!func->argumentRemoved(0) && !func->type().isVoid())
return true;
}
}
@@ -833,11 +821,11 @@ void OverloadDataRootNode::dumpRootGraph(QTextStream &s, int minArgs, int maxArg
// Shows type changes for all function signatures
for (const auto &func : m_overloads) {
- if (func->typeReplaced(0).isEmpty())
+ 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->typeReplaced(0)) << "</td></tr>";
+ s << toHtml(func->modifiedTypeName()) << "</td></tr>";
}
// Minimum and maximum number of arguments
@@ -882,10 +870,10 @@ void OverloadDataNode::dumpNodeGraph(QTextStream &s) const
s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>";
// Argument type information
- QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType().cppSignature();
+ 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 (hasArgumentTypeReplace()) {
+ if (isTypeModified()) {
s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">";
s << toHtml(argType().cppSignature()) << "</td></tr>";
}
@@ -1042,8 +1030,8 @@ void OverloadDataNode::formatDebug(QDebug &d) const
if (m_argument.argumentIndex() != m_argPos)
d << ", argIndex=" << m_argument.argumentIndex();
d << ", argType=\"" << m_argument.type().cppSignature() << '"';
- if (!m_argTypeReplaced.isEmpty())
- d << ", argTypeReplaced=\"" << m_argTypeReplaced << '"';
+ if (isTypeModified())
+ d << ", modifiedArgType=\"" << modifiedArgType().cppSignature() << '"';
formatOverloads(d);
formatNextOverloadData(d);
d << ')';
diff --git a/sources/shiboken6/generator/shiboken/overloaddata.h b/sources/shiboken6/generator/shiboken/overloaddata.h
index e72b64778..cbf2470f6 100644
--- a/sources/shiboken6/generator/shiboken/overloaddata.h
+++ b/sources/shiboken6/generator/shiboken/overloaddata.h
@@ -116,9 +116,9 @@ public:
const AbstractMetaArgument &argument() const
{ return m_argument; }
const AbstractMetaType &argType() const { return m_argument.type(); }
+ const AbstractMetaType &modifiedArgType() const { return m_argument.modifiedType(); }
- bool hasArgumentTypeReplace() const { return !m_argTypeReplaced.isEmpty(); }
- const QString &argumentTypeReplaced() const { return m_argTypeReplaced; }
+ bool isTypeModified() const { return m_argument.isTypeModified(); }
const AbstractMetaArgument *overloadArgument(const AbstractMetaFunctionCPtr &func) const;
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index c05ee2e25..0bf43482d 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -643,7 +643,7 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunctionCPtr &f
continue;
const auto &type = arg.type();
- if (!func->typeReplaced(arg.argumentIndex() + 1).isEmpty()) {
+ if (arg.isTypeModified()) {
result += QLatin1Char(objType);
} else if (arg.type().isObject()
|| type.isValue()
@@ -1228,15 +1228,13 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunctionCPtr &func,
const AbstractMetaArgument &argument,
Options options) const
{
- QString modified_type;
- if (!(options & OriginalTypeDescription))
- modified_type = func->typeReplaced(argument.argumentIndex() + 1);
- QString arg;
+ auto type = options.testFlag(OriginalTypeDescription)
+ ? argument.type() : argument.modifiedType();
- if (modified_type.isEmpty())
- arg = translateType(argument.type(), func->implementingClass(), options);
- else
- arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.'));
+ QString arg = translateType(type, func->implementingClass(), options);
+
+ if (argument.isTypeModified())
+ arg.replace(QLatin1Char('$'), QLatin1Char('.')); // Haehh?
// "int a", "int a[]"
const int arrayPos = arg.indexOf(QLatin1Char('['));
@@ -1300,9 +1298,8 @@ GeneratorContext ShibokenGenerator::contextForClass(const AbstractMetaClass *c)
QString ShibokenGenerator::functionReturnType(const AbstractMetaFunctionCPtr &func, Options options) const
{
- QString modifiedReturnType = QString(func->typeReplaced(0));
- if (!modifiedReturnType.isEmpty() && !(options & OriginalTypeDescription))
- return modifiedReturnType;
+ if (func->isTypeModified() && !options.testFlag(OriginalTypeDescription))
+ return func->modifiedTypeName();
return translateType(func->type(), func->implementingClass(), options);
}
@@ -1536,13 +1533,7 @@ ShibokenGenerator::ArgumentVarReplacementList
argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(i);
if (!argRemoved && argValue.isEmpty()) {
int argPos = i - removed;
- AbstractMetaType type = arg.type();
- QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1);
- if (!typeReplaced.isEmpty()) {
- auto builtType = AbstractMetaType::fromString(typeReplaced);
- if (builtType.has_value())
- type = builtType.value();
- }
+ AbstractMetaType type = arg.modifiedType();
if (type.typeEntry()->isCustom()) {
argValue = usePyArgs
? pythonArgsAt(argPos) : QLatin1String(PYTHON_ARG);
@@ -1768,13 +1759,7 @@ void ShibokenGenerator::writeCodeSnips(TextStream &s,
for (const ArgumentVarReplacementPair &pair : argReplacements) {
const AbstractMetaArgument &arg = pair.first;
int idx = arg.argumentIndex() + 1;
- AbstractMetaType type = arg.type();
- QString typeReplaced = func->typeReplaced(arg.argumentIndex() + 1);
- if (!typeReplaced.isEmpty()) {
- auto builtType = AbstractMetaType::fromString(typeReplaced);
- if (builtType.has_value())
- type = builtType.value();
- }
+ AbstractMetaType type = arg.modifiedType();
if (type.isWrapperType()) {
QString replacement = pair.second;
if (type.shouldDereferenceArgument())