diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetatype.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetatype.cpp | 226 |
1 files changed, 132 insertions, 94 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp index a56557e76..3ec07509d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp @@ -9,9 +9,9 @@ #include "containertypeentry.h" #include "enumtypeentry.h" #include "flagstypeentry.h" -#include "parser/codemodel.h" #include "qtcompat.h" +#include "typeinfo.h" #ifndef QT_NO_DEBUG_STREAM # include <QtCore/QDebug> @@ -19,12 +19,13 @@ #include <QtCore/QHash> #include <QtCore/QSharedData> -#include <QtCore/QSharedPointer> #include <QtCore/QStack> +#include <memory> + using namespace Qt::StringLiterals; -using AbstractMetaTypeCPtr = QSharedPointer<const AbstractMetaType>; +using AbstractMetaTypeCPtr = std::shared_ptr<const AbstractMetaType>; const QSet<QString> &AbstractMetaType::cppFloatTypes() { @@ -107,7 +108,7 @@ const QSet<QString> &AbstractMetaType::cppPrimitiveTypes() class AbstractMetaTypeData : public QSharedData { public: - AbstractMetaTypeData(const TypeEntry *t); + AbstractMetaTypeData(const TypeEntryCPtr &t); int actualIndirections() const; bool passByConstRef() const; @@ -118,11 +119,12 @@ public: QString formatPythonSignature() const; bool isEquivalent(const AbstractMetaTypeData &rhs) const; bool equals(const AbstractMetaTypeData &rhs) const; + QStringList instantiationCppSignatures() const; template <class Predicate> bool generateOpaqueContainer(Predicate p) const; - const TypeEntry *m_typeEntry; + TypeEntryCPtr m_typeEntry; AbstractMetaTypeList m_instantiations; mutable QString m_cachedCppSignature; mutable QString m_cachedPythonSignature; @@ -144,7 +146,7 @@ public: AbstractMetaTypeList m_children; }; -AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) : +AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntryCPtr &t) : m_typeEntry(t), m_constant(false), m_volatile(false), @@ -153,7 +155,16 @@ AbstractMetaTypeData::AbstractMetaTypeData(const TypeEntry *t) : { } -AbstractMetaType::AbstractMetaType(const TypeEntry *t) : d(new AbstractMetaTypeData(t)) +QStringList AbstractMetaTypeData::instantiationCppSignatures() const +{ + QStringList result; + for (const auto &i : m_instantiations) + result.append(i.cppSignature()); + return result; +} + +AbstractMetaType::AbstractMetaType(const TypeEntryCPtr &t) : + d(new AbstractMetaTypeData(t)) { Q_ASSERT(t); } @@ -167,9 +178,9 @@ AbstractMetaType &AbstractMetaType::operator=(const AbstractMetaType &) = defaul AbstractMetaType::AbstractMetaType(const AbstractMetaType &rhs) = default; -AbstractMetaType::AbstractMetaType(AbstractMetaType &&) = default; +AbstractMetaType::AbstractMetaType(AbstractMetaType &&) noexcept = default; -AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) = default; +AbstractMetaType &AbstractMetaType::operator=(AbstractMetaType &&) noexcept = default; AbstractMetaType::~AbstractMetaType() = default; @@ -220,6 +231,11 @@ const AbstractMetaTypeList &AbstractMetaType::instantiations() const return d->m_instantiations; } +QStringList AbstractMetaType::instantiationCppSignatures() const +{ + return d->instantiationCppSignatures(); +} + // For applying the <array> function argument modification: change into a type // where "int *" becomes "int[]". bool AbstractMetaType::applyArrayModification(QString *errorMessage) @@ -229,7 +245,7 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage) *errorMessage = u"<array> modification already applied."_s; return false; } - if (!d->m_arrayElementType.isNull()) { + if (d->m_arrayElementType) { QTextStream(errorMessage) << "The type \"" << cppSignature() << "\" is an array of " << d->m_arrayElementType->name() << '.'; return false; @@ -253,12 +269,12 @@ bool AbstractMetaType::applyArrayModification(QString *errorMessage) return true; } -const TypeEntry *AbstractMetaType::typeEntry() const +TypeEntryCPtr AbstractMetaType::typeEntry() const { return d->m_typeEntry; } -void AbstractMetaType::setTypeEntry(const TypeEntry *type) +void AbstractMetaType::setTypeEntry(const TypeEntryCPtr &type) { if (d->m_typeEntry != type) d->m_typeEntry = type; @@ -277,13 +293,13 @@ QString AbstractMetaType::originalTypeDescription() const void AbstractMetaType::setOriginalTemplateType(const AbstractMetaType &type) { - if (d->m_originalTemplateType.isNull() || *d->m_originalTemplateType != type) + if (!d->m_originalTemplateType || *d->m_originalTemplateType != type) d->m_originalTemplateType.reset(new AbstractMetaType(type)); } const AbstractMetaType *AbstractMetaType::originalTemplateType() const { - return d->m_originalTemplateType.data(); + return d->m_originalTemplateType.get(); } AbstractMetaType AbstractMetaType::getSmartPointerInnerType() const @@ -312,7 +328,7 @@ AbstractMetaTypeList AbstractMetaType::nestedArrayTypes() const } break; case NativePointerAsArrayPattern: - result.append(*d->m_arrayElementType.data()); + result.append(*d->m_arrayElementType.get()); break; default: break; @@ -340,6 +356,12 @@ bool AbstractMetaType::passByValue() const return d->passByValue(); } +bool AbstractMetaType::useStdMove() const +{ + return (isUniquePointer() && d->passByValue()) + || d->m_referenceType == RValueReference; +} + ReferenceType AbstractMetaType::referenceType() const { return d->m_referenceType; @@ -418,17 +440,28 @@ int AbstractMetaType::arrayElementCount() const const AbstractMetaType *AbstractMetaType::arrayElementType() const { - return d->m_arrayElementType.data(); + return d->m_arrayElementType.get(); } void AbstractMetaType::setArrayElementType(const AbstractMetaType &t) { - if (d->m_arrayElementType.isNull() || *d->m_arrayElementType != t) { + if (!d->m_arrayElementType || *d->m_arrayElementType != t) { d->m_arrayElementType.reset(new AbstractMetaType(t)); d->m_signaturesDirty = true; } } +AbstractMetaType AbstractMetaType::plainType() const +{ + AbstractMetaType result = *this; + result.clearIndirections(); + result.setReferenceType(NoReference); + result.setConstant(false); + result.setVolatile(false); + result.decideUsagePattern(); + return result; +} + QString AbstractMetaType::cppSignature() const { const AbstractMetaTypeData *cd = d.constData(); @@ -510,6 +543,7 @@ void AbstractMetaType::decideUsagePattern() pattern = ObjectPattern; } setTypeUsagePattern(pattern); + Q_ASSERT(pattern != ContainerPattern || !d->m_instantiations.isEmpty()); } bool AbstractMetaTypeData::hasTemplateChildren() const @@ -543,6 +577,29 @@ static inline QString formatArraySize(int e) return result; } +// Return the number of template parameters; remove the default +// non template type parameter of std::span from the signature. +static qsizetype stripDefaultTemplateArgs(const TypeEntryCPtr &te, + const AbstractMetaTypeList &instantiations) +{ + static const char16_t dynamicExtent64[] = u"18446744073709551615"; // size_t(-1) + static const char16_t dynamicExtent32[] = u"4294967295"; + + qsizetype result = instantiations.size(); + if (result == 0 || !te->isContainer()) + return result; + auto cte = std::static_pointer_cast<const ContainerTypeEntry>(te); + if (cte->containerKind() != ContainerTypeEntry::SpanContainer) + return result; + const auto lastTe = instantiations.constLast().typeEntry(); + if (lastTe->type() == TypeEntry::ConstantValueType) { + const QString &name = lastTe->name(); + if (name == dynamicExtent64 || name == dynamicExtent32) + --result; + } + return result; +} + QString AbstractMetaTypeData::formatSignature(bool minimal) const { QString result; @@ -565,12 +622,13 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const result += u'<'; if (minimal) result += u' '; - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + const auto size = stripDefaultTemplateArgs(m_typeEntry, m_instantiations); + for (qsizetype i = 0; i < size; ++i) { if (i > 0) result += u','; result += m_instantiations.at(i).minimalSignature(); } - result += u" >"_s; + result += u'>'; } if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) @@ -633,7 +691,7 @@ QString AbstractMetaTypeData::formatPythonSignature() const } if (!m_instantiations.isEmpty()) { result += u'['; - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) result += u", "_s; result += m_instantiations.at(i).formatPythonSignature(); @@ -643,18 +701,12 @@ QString AbstractMetaTypeData::formatPythonSignature() const if (m_typeEntry->isPrimitive()) for (Indirection i : m_indirections) result += TypeInfo::indirectionKeyword(i); - // If it is a flags type, we replace it with the full name: - // "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" + // If it is a flags type, we replace it with the full name of the enum: + // "PySide6.QtCore.Qt.ItemFlag" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>" if (m_typeEntry->isFlags()) { - // PYSIDE-1735: We need to provide both the flags type and the original enum type - // as a choice at runtime. - auto flagsTypeEntry = static_cast<const FlagsTypeEntry *>(m_typeEntry); - auto enumTypeEntry = flagsTypeEntry->originator(); - result = m_typeEntry->targetLangPackage() + u".^^"_s - + flagsTypeEntry->targetLangName() + u"^^"_s - + enumTypeEntry->targetLangName() + u"^^"_s; + const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(m_typeEntry); + result = fte->originator()->qualifiedTargetLangName(); } - result.replace(u"::"_s, u"."_s); return result; } @@ -666,7 +718,7 @@ QString AbstractMetaType::formatPythonSignature() const bool AbstractMetaType::isCppPrimitive() const { - return d->m_pattern == PrimitivePattern && d->m_typeEntry->isCppPrimitive(); + return d->m_pattern == PrimitivePattern && ::isCppPrimitive(d->m_typeEntry); } bool AbstractMetaType::isConstant() const @@ -697,9 +749,9 @@ void AbstractMetaType::setVolatile(bool v) static bool equalsCPtr(const AbstractMetaTypeCPtr &t1, const AbstractMetaTypeCPtr &t2) { - if (t1.isNull() != t2.isNull()) + if (bool(t1) != bool(t2)) return false; - return t1.isNull() || *t1 == *t2; + return !t1 || *t1 == *t2; } bool AbstractMetaTypeData::isEquivalent(const AbstractMetaTypeData &rhs) const @@ -727,9 +779,9 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const && m_referenceType == rhs.m_referenceType && isEquivalent(rhs); } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool comparesEqual(const AbstractMetaType &lhs, const AbstractMetaType &rhs) noexcept { - return d->equals(*rhs.d); + return lhs.d->equals(*rhs.d); } bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const @@ -739,12 +791,12 @@ bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const const AbstractMetaType *AbstractMetaType::viewOn() const { - return d->m_viewOn.data(); + return d->m_viewOn.get(); } void AbstractMetaType::setViewOn(const AbstractMetaType &v) { - if (d->m_viewOn.isNull() || *d->m_viewOn != v) + if (!d->m_viewOn || *d->m_viewOn != v) d->m_viewOn.reset(new AbstractMetaType(v)); } @@ -752,7 +804,7 @@ AbstractMetaType AbstractMetaType::createVoid() { static QScopedPointer<AbstractMetaType> metaType; if (metaType.isNull()) { - static const TypeEntry *voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); + static TypeEntryCPtr voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); Q_ASSERT(voidTypeEntry); metaType.reset(new AbstractMetaType(voidTypeEntry)); metaType->decideUsagePattern(); @@ -766,13 +818,18 @@ void AbstractMetaType::dereference(QString *type) type->append(u')'); } +QString AbstractMetaType::dereferencePrefix(qsizetype n) +{ + const QChar c = n > 0 ? u'*' : u'&'; + return QString(qAbs(n), c); +} + void AbstractMetaType::applyDereference(QString *type, qsizetype n) { if (n == 0) return; - const char c = n > 0 ? '*' : '&'; - type->prepend(QString(qAbs(n), QLatin1Char(c))); + type->prepend(dereferencePrefix(n)); type->prepend(u'('); type->append(u')'); } @@ -832,7 +889,7 @@ bool AbstractMetaType::isVoidPointer() const bool AbstractMetaType::isUserPrimitive() const { - return d->m_indirections.isEmpty() && d->m_typeEntry->isUserPrimitive(); + return d->m_indirections.isEmpty() && ::isUserPrimitive(d->m_typeEntry); } bool AbstractMetaType::isObjectTypeUsedAsValueType() const @@ -857,28 +914,9 @@ bool AbstractMetaType::isWrapperPassedByReference() const && !isPointer(); } -qsizetype AbstractMetaType::shouldDereferenceArgument() const -{ - if (isWrapperPassedByReference() || valueTypeWithCopyConstructorOnlyPassed() - || isObjectTypeUsedAsValueType()) { - return 1; - } - - if (!d->m_typeEntry->isContainer()) - return 0; - - qsizetype result = -d->m_indirections.size(); - - // For opaque containers, the cppArg in the generated code is a pointer - if (generateOpaqueContainer()) - ++result; - - return result; -} - bool AbstractMetaType::isCppIntegralPrimitive() const { - return d->m_typeEntry->isCppIntegralPrimitive(); + return ::isCppIntegralPrimitive(d->m_typeEntry); } bool AbstractMetaType::isExtendedCppPrimitive() const @@ -887,14 +925,14 @@ bool AbstractMetaType::isExtendedCppPrimitive() const return true; if (!d->m_indirections.isEmpty()) return false; - return d->m_typeEntry->isExtendedCppPrimitive(); + return ::isExtendedCppPrimitive(d->m_typeEntry); } bool AbstractMetaType::isValueTypeWithCopyConstructorOnly() const { bool result = false; if (d->m_typeEntry->isComplex()) { - const auto *cte = static_cast<const ComplexTypeEntry *>(d->m_typeEntry); + const auto cte = std::static_pointer_cast<const ComplexTypeEntry>(d->m_typeEntry); result = cte->isValueTypeWithCopyConstructorOnly(); } return result; @@ -911,14 +949,18 @@ using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>; Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache) std::optional<AbstractMetaType> -AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) +AbstractMetaType::fromString(const QString &typeSignatureIn, QString *errorMessage) { - typeSignature = typeSignature.trimmed(); + auto &cache = *metaTypeFromStringCache(); + auto it = cache.find(typeSignatureIn); + if (it != cache.end()) + return it.value(); + + QString typeSignature = typeSignatureIn.trimmed(); if (typeSignature.startsWith(u"::")) typeSignature.remove(0, 2); - auto &cache = *metaTypeFromStringCache(); - auto it = cache.find(typeSignature); + it = cache.find(typeSignature); if (it == cache.end()) { auto metaType = AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage); @@ -927,12 +969,14 @@ AbstractMetaType::fromString(QString typeSignature, QString *errorMessage) errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); return {}; } + if (typeSignature != typeSignatureIn) + cache.insert(typeSignatureIn, metaType.value()); it = cache.insert(typeSignature, metaType.value()); } return it.value(); } -AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry) +AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntryCPtr &typeEntry) { QString typeName = typeEntry->qualifiedCppName(); if (typeName.startsWith(u"::")) @@ -941,16 +985,12 @@ AbstractMetaType AbstractMetaType::fromTypeEntry(const TypeEntry *typeEntry) auto it = cache.find(typeName); if (it != cache.end()) return it.value(); - AbstractMetaType metaType(typeEntry); - metaType.clearIndirections(); - metaType.setReferenceType(NoReference); - metaType.setConstant(false); - metaType.decideUsagePattern(); + AbstractMetaType metaType = AbstractMetaType(typeEntry).plainType(); cache.insert(typeName, metaType); return metaType; } -AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClass *metaClass) +AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass) { return fromTypeEntry(metaClass->typeEntry()); } @@ -963,37 +1003,34 @@ bool AbstractMetaTypeData::generateOpaqueContainer(Predicate pred) const return false; if (m_indirections.size() > 1) return false; - auto *containerTypeEntry = static_cast<const ContainerTypeEntry *>(m_typeEntry); + auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(m_typeEntry); auto kind = containerTypeEntry->containerKind(); - if (kind != ContainerTypeEntry::ListContainer) - return false; - const auto &instantation = m_instantiations.constFirst(); - if (instantation.referenceType() != NoReference) + if (kind != ContainerTypeEntry::ListContainer && kind != ContainerTypeEntry::SpanContainer) return false; - const QString signature = instantation.cppSignature(); - bool result = false; - auto *instTypEntry = instantation.typeEntry(); - switch (instTypEntry->type()) { + const auto &firstInstantiation = m_instantiations.constFirst(); + if (firstInstantiation.referenceType() != NoReference) + return false; + switch (firstInstantiation.typeEntry()->type()) { case TypeEntry::PrimitiveType: case TypeEntry::FlagsType: case TypeEntry::EnumType: case TypeEntry::BasicValueType: case TypeEntry::ObjectType: case TypeEntry::CustomType: - result = pred(containerTypeEntry, signature); break; default: - break; + return false; } - return result; + + return pred(containerTypeEntry, instantiationCppSignatures()); } // Simple predicate for checking whether an opaque container should be generated -static bool opaqueContainerPredicate(const ContainerTypeEntry *t, - const QString &signature) +static bool opaqueContainerPredicate(const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { - return t->generateOpaqueContainer(signature); + return t->generateOpaqueContainer(instantiations); } bool AbstractMetaType::generateOpaqueContainer() const @@ -1006,8 +1043,9 @@ bool AbstractMetaType::generateOpaqueContainer() const // (cf AbstractMetaFunction::generateOpaqueContainerReturn()) bool AbstractMetaType::generateOpaqueContainerForGetter(const QString &modifiedType) const { - auto predicate = [&modifiedType](const ContainerTypeEntry *t, const QString &signature) { - return t->opaqueContainerName(signature) == modifiedType; + auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { + return t->opaqueContainerName(instantiations) == modifiedType; }; return d->generateOpaqueContainer(predicate); } @@ -1031,7 +1069,7 @@ void AbstractMetaType::formatDebug(QDebug &debug) const for (auto i : indirections) debug << ' ' << TypeInfo::indirectionKeyword(i); } - if (referenceType()) + if (referenceType() != NoReference) debug << ", reftype=" << referenceType(); if (isConstant()) debug << ", [const]"; @@ -1042,9 +1080,9 @@ void AbstractMetaType::formatDebug(QDebug &debug) const << "\", arrayElementCount=" << arrayElementCount(); } const auto &instantiations = this->instantiations(); - if (const int instantiationsSize = instantiations.size()) { + if (const auto instantiationsSize = instantiations.size()) { debug << ", instantiations[" << instantiationsSize << "]=<"; - for (int i = 0; i < instantiationsSize; ++i) { + for (qsizetype i = 0; i < instantiationsSize; ++i) { if (i) debug << ", "; instantiations.at(i).formatDebug(debug); |