diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetatype.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetatype.cpp | 494 |
1 files changed, 397 insertions, 97 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp index 990d1ec07..3ec07509d 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp @@ -1,50 +1,114 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "abstractmetatype.h" +#include "abstractmetabuilder.h" +#include "abstractmetalang.h" +#include "messages.h" #include "typedatabase.h" -#include "typesystem.h" -#include "parser/codemodel.h" +#include "containertypeentry.h" +#include "enumtypeentry.h" +#include "flagstypeentry.h" + +#include "qtcompat.h" +#include "typeinfo.h" #ifndef QT_NO_DEBUG_STREAM # include <QtCore/QDebug> #endif +#include <QtCore/QHash> #include <QtCore/QSharedData> -#include <QtCore/QSharedPointer> #include <QtCore/QStack> -using AbstractMetaTypeCPtr = QSharedPointer<const AbstractMetaType>; +#include <memory> + +using namespace Qt::StringLiterals; + +using AbstractMetaTypeCPtr = std::shared_ptr<const AbstractMetaType>; + +const QSet<QString> &AbstractMetaType::cppFloatTypes() +{ + static const QSet<QString> result{u"double"_s, u"float"_s}; + return result; +} + +const QSet<QString> &AbstractMetaType::cppSignedCharTypes() +{ + static const QSet<QString> result{u"char"_s, u"signed char"_s}; + return result; +} + +const QSet<QString> &AbstractMetaType::cppUnsignedCharTypes() +{ + static const QSet<QString> result{u"unsigned char"_s}; + return result; +} + +const QSet<QString> &AbstractMetaType::cppCharTypes() +{ + static const QSet<QString> result = cppSignedCharTypes() | cppUnsignedCharTypes(); + return result; +} + +const QSet<QString> &AbstractMetaType::cppSignedIntTypes() +{ + static QSet<QString> result; + if (result.isEmpty()) { + result = {u"char"_s, u"signed char"_s, u"short"_s, u"short int"_s, + u"signed short"_s, u"signed short int"_s, + u"int"_s, u"signed int"_s, + u"long"_s, u"long int"_s, + u"signed long"_s, u"signed long int"_s, + u"long long"_s, u"long long int"_s, + u"signed long long int"_s, + u"ptrdiff_t"_s}; + result |= cppSignedCharTypes(); + } + return result; +} + +const QSet<QString> &AbstractMetaType::cppUnsignedIntTypes() +{ + static QSet<QString> result; + if (result.isEmpty()) { + result = {u"unsigned short"_s, u"unsigned short int"_s, + u"unsigned"_s, u"unsigned int"_s, + u"unsigned long"_s, u"unsigned long int"_s, + u"unsigned long long"_s, + u"unsigned long long int"_s, + u"size_t"_s}; + result |= cppUnsignedCharTypes(); + } + return result; +} + +const QSet<QString> &AbstractMetaType::cppIntegralTypes() +{ + static QSet<QString> result; + if (result.isEmpty()) { + result |= cppSignedIntTypes(); + result |= cppUnsignedIntTypes(); + result.insert(u"bool"_s); + } + return result; +} + +const QSet<QString> &AbstractMetaType::cppPrimitiveTypes() +{ + static QSet<QString> result; + if (result.isEmpty()) { + result |= cppIntegralTypes(); + result |= cppFloatTypes(); + result.insert(u"wchar_t"_s); + } + return result; +} class AbstractMetaTypeData : public QSharedData { public: - AbstractMetaTypeData(const TypeEntry *t); + AbstractMetaTypeData(const TypeEntryCPtr &t); int actualIndirections() const; bool passByConstRef() const; @@ -53,9 +117,14 @@ public: bool hasTemplateChildren() const; QString formatSignature(bool minimal) const; QString formatPythonSignature() const; + bool isEquivalent(const AbstractMetaTypeData &rhs) const; bool equals(const AbstractMetaTypeData &rhs) const; + QStringList instantiationCppSignatures() const; - const TypeEntry *m_typeEntry; + template <class Predicate> + bool generateOpaqueContainer(Predicate p) const; + + TypeEntryCPtr m_typeEntry; AbstractMetaTypeList m_instantiations; mutable QString m_cachedCppSignature; mutable QString m_cachedPythonSignature; @@ -77,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), @@ -86,21 +155,32 @@ 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() : d(new AbstractMetaTypeData(nullptr)) +AbstractMetaType::AbstractMetaType(const TypeEntryCPtr &t) : + d(new AbstractMetaTypeData(t)) { + Q_ASSERT(t); +} + +AbstractMetaType::AbstractMetaType() +{ + *this = AbstractMetaType::createVoid(); } AbstractMetaType &AbstractMetaType::operator=(const AbstractMetaType &) = default; 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; @@ -151,16 +231,21 @@ 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) { if (d->m_pattern == AbstractMetaType::NativePointerAsArrayPattern) { - *errorMessage = QLatin1String("<array> modification already applied."); + *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; @@ -184,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; @@ -208,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 @@ -243,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; @@ -271,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; @@ -349,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(); @@ -441,6 +543,7 @@ void AbstractMetaType::decideUsagePattern() pattern = ObjectPattern; } setTypeUsagePattern(pattern); + Q_ASSERT(pattern != ContainerPattern || !d->m_instantiations.isEmpty()); } bool AbstractMetaTypeData::hasTemplateChildren() const @@ -467,10 +570,33 @@ bool AbstractMetaType::hasTemplateChildren() const static inline QString formatArraySize(int e) { QString result; - result += QLatin1Char('['); + result += u'['; if (e >= 0) result += QString::number(e); - result += QLatin1Char(']'); + result += u']'; + 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; } @@ -478,13 +604,13 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const { QString result; if (m_constant) - result += QLatin1String("const "); + result += u"const "_s; if (m_volatile) - result += QLatin1String("volatile "); + result += u"volatile "_s; if (m_pattern == AbstractMetaType::ArrayPattern) { // Build nested array dimensions a[2][3] in correct order result += m_arrayElementType->minimalSignature(); - const int arrayPos = result.indexOf(QLatin1Char('[')); + const int arrayPos = result.indexOf(u'['); if (arrayPos != -1) result.insert(arrayPos, formatArraySize(m_arrayElementCount)); else @@ -493,29 +619,30 @@ QString AbstractMetaTypeData::formatSignature(bool minimal) const result += m_typeEntry->qualifiedCppName(); } if (!m_instantiations.isEmpty()) { - result += QLatin1Char('<'); + result += u'<'; if (minimal) - result += QLatin1Char(' '); - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + result += u' '; + const auto size = stripDefaultTemplateArgs(m_typeEntry, m_instantiations); + for (qsizetype i = 0; i < size; ++i) { if (i > 0) - result += QLatin1Char(','); + result += u','; result += m_instantiations.at(i).minimalSignature(); } - result += QLatin1String(" >"); + result += u'>'; } if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) - result += QLatin1Char(' '); + result += u' '; for (Indirection i : m_indirections) result += TypeInfo::indirectionKeyword(i); switch (m_referenceType) { case NoReference: break; case LValueReference: - result += QLatin1Char('&'); + result += u'&'; break; case RValueReference: - result += QLatin1String("&&"); + result += u"&&"_s; break; } return result; @@ -541,7 +668,7 @@ QString AbstractMetaTypeData::formatPythonSignature() const */ QString result; if (m_pattern == AbstractMetaType::NativePointerAsArrayPattern) - result += QLatin1String("array "); + result += u"array "_s; // We no longer use the "const" qualifier for heuristics. Instead, // NativePointerAsArrayPattern indicates when we have <array> in XML. // if (m_typeEntry->isPrimitive() && isConstant()) @@ -549,12 +676,12 @@ QString AbstractMetaTypeData::formatPythonSignature() const if (!m_typeEntry->isPrimitive() && !m_typeEntry->isSmartPointer()) { const QString package = m_typeEntry->targetLangPackage(); if (!package.isEmpty()) - result += package + QLatin1Char('.'); + result += package + u'.'; } if (m_pattern == AbstractMetaType::ArrayPattern) { // Build nested array dimensions a[2][3] in correct order result += m_arrayElementType->formatPythonSignature(); - const int arrayPos = result.indexOf(QLatin1Char('[')); + const int arrayPos = result.indexOf(u'['); if (arrayPos != -1) result.insert(arrayPos, formatArraySize(m_arrayElementCount)); else @@ -563,22 +690,24 @@ QString AbstractMetaTypeData::formatPythonSignature() const result += m_typeEntry->targetLangName(); } if (!m_instantiations.isEmpty()) { - result += QLatin1Char('['); - for (int i = 0, size = m_instantiations.size(); i < size; ++i) { + result += u'['; + for (qsizetype i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) - result += QLatin1String(", "); + result += u", "_s; result += m_instantiations.at(i).formatPythonSignature(); } - result += QLatin1Char(']'); + result += u']'; } 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 (m_typeEntry->isFlags()) - result = m_typeEntry->qualifiedTargetLangName(); - result.replace(QLatin1String("::"), QLatin1String(".")); + // 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()) { + const auto fte = std::static_pointer_cast<const FlagsTypeEntry>(m_typeEntry); + result = fte->originator()->qualifiedTargetLangName(); + } + result.replace(u"::"_s, u"."_s); return result; } @@ -589,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 @@ -620,12 +749,12 @@ 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::equals(const AbstractMetaTypeData &rhs) const +bool AbstractMetaTypeData::isEquivalent(const AbstractMetaTypeData &rhs) const { if (m_typeEntry != rhs.m_typeEntry || m_indirections != rhs.m_indirections @@ -633,11 +762,6 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const return false; } - if (m_constant != rhs.m_constant || m_volatile != rhs.m_volatile - || m_referenceType != rhs.m_referenceType) { - return false; - } - if (!equalsCPtr(m_arrayElementType, rhs.m_arrayElementType)) return false; @@ -649,19 +773,30 @@ bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const return true; } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool AbstractMetaTypeData::equals(const AbstractMetaTypeData &rhs) const +{ + return m_constant == rhs.m_constant && m_volatile == rhs.m_volatile + && m_referenceType == rhs.m_referenceType && isEquivalent(rhs); +} + +bool comparesEqual(const AbstractMetaType &lhs, const AbstractMetaType &rhs) noexcept +{ + return lhs.d->equals(*rhs.d); +} + +bool AbstractMetaType::isEquivalent(const AbstractMetaType &rhs) const { - return d->equals(*rhs.d); + return d->isEquivalent(*rhs.d); } 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)); } @@ -669,7 +804,7 @@ AbstractMetaType AbstractMetaType::createVoid() { static QScopedPointer<AbstractMetaType> metaType; if (metaType.isNull()) { - static const TypeEntry *voidTypeEntry = TypeDatabase::instance()->findType(QLatin1String("void")); + static TypeEntryCPtr voidTypeEntry = TypeDatabase::instance()->findType(u"void"_s); Q_ASSERT(voidTypeEntry); metaType.reset(new AbstractMetaType(voidTypeEntry)); metaType->decideUsagePattern(); @@ -677,12 +812,55 @@ AbstractMetaType AbstractMetaType::createVoid() return *metaType.data(); } +void AbstractMetaType::dereference(QString *type) +{ + type->prepend(u"(*"_s); + 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; + + type->prepend(dereferencePrefix(n)); + type->prepend(u'('); + type->append(u')'); +} + +bool AbstractMetaType::stripDereference(QString *type) +{ + if (type->startsWith(u"(*") && type->endsWith(u')')) { + type->chop(1); + type->remove(0, 2); + *type = type->trimmed(); + return true; + } + if (type->startsWith(u'*')) { + type->remove(0, 1); + *type = type->trimmed(); + return true; + } + return false; +} + // Query functions for generators bool AbstractMetaType::isObjectType() const { return d->m_typeEntry->isObject(); } +bool AbstractMetaType::isUniquePointer() const +{ + return isSmartPointer() && d->m_typeEntry->isUniquePointer(); +} + bool AbstractMetaType::isPointer() const { return !d->m_indirections.isEmpty() @@ -699,19 +877,19 @@ bool AbstractMetaType::isCString() const { return isNativePointer() && d->m_indirections.size() == 1 - && name() == QLatin1String("char"); + && name() == u"char"; } bool AbstractMetaType::isVoidPointer() const { return isNativePointer() && d->m_indirections.size() == 1 - && name() == QLatin1String("void"); + && name() == u"void"; } 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 @@ -730,15 +908,15 @@ bool AbstractMetaType::isPointerToWrapperType() const return (isObjectType() && d->m_indirections.size() == 1) || isValuePointer(); } -bool AbstractMetaType::shouldDereferencePointer() const +bool AbstractMetaType::isWrapperPassedByReference() const { return d->m_referenceType == LValueReference && isWrapperType() - && !isPointer(); + && !isPointer(); } bool AbstractMetaType::isCppIntegralPrimitive() const { - return d->m_typeEntry->isCppIntegralPrimitive(); + return ::isCppIntegralPrimitive(d->m_typeEntry); } bool AbstractMetaType::isExtendedCppPrimitive() const @@ -747,14 +925,136 @@ 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 = std::static_pointer_cast<const ComplexTypeEntry>(d->m_typeEntry); + result = cte->isValueTypeWithCopyConstructorOnly(); + } + return result; +} + +bool AbstractMetaType::valueTypeWithCopyConstructorOnlyPassed() const +{ + return (passByValue() || passByConstRef()) + && isValueTypeWithCopyConstructorOnly(); +} + +using AbstractMetaTypeCache = QHash<QString, AbstractMetaType>; + +Q_GLOBAL_STATIC(AbstractMetaTypeCache, metaTypeFromStringCache) + +std::optional<AbstractMetaType> +AbstractMetaType::fromString(const QString &typeSignatureIn, QString *errorMessage) +{ + 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); + + it = cache.find(typeSignature); + if (it == cache.end()) { + auto metaType = + AbstractMetaBuilder::translateType(typeSignature, nullptr, {}, errorMessage); + if (Q_UNLIKELY(!metaType.has_value())) { + if (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 TypeEntryCPtr &typeEntry) +{ + QString typeName = typeEntry->qualifiedCppName(); + if (typeName.startsWith(u"::")) + typeName.remove(0, 2); + auto &cache = *metaTypeFromStringCache(); + auto it = cache.find(typeName); + if (it != cache.end()) + return it.value(); + AbstractMetaType metaType = AbstractMetaType(typeEntry).plainType(); + cache.insert(typeName, metaType); + return metaType; +} + +AbstractMetaType AbstractMetaType::fromAbstractMetaClass(const AbstractMetaClassCPtr &metaClass) +{ + return fromTypeEntry(metaClass->typeEntry()); +} + +template <class Predicate> // Predicate(containerTypeEntry, signature) +bool AbstractMetaTypeData::generateOpaqueContainer(Predicate pred) const +{ + // Allow for passing containers by pointer as well. + if (!m_typeEntry->isContainer()) + return false; + if (m_indirections.size() > 1) + return false; + auto containerTypeEntry = std::static_pointer_cast<const ContainerTypeEntry>(m_typeEntry); + auto kind = containerTypeEntry->containerKind(); + if (kind != ContainerTypeEntry::ListContainer && kind != ContainerTypeEntry::SpanContainer) + return false; + + 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: + break; + default: + return false; + } + + return pred(containerTypeEntry, instantiationCppSignatures()); +} + +// Simple predicate for checking whether an opaque container should be generated +static bool opaqueContainerPredicate(const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) +{ + return t->generateOpaqueContainer(instantiations); +} + +bool AbstractMetaType::generateOpaqueContainer() const +{ + return d->generateOpaqueContainer(opaqueContainerPredicate); +} + +// Helper for determining whether a function should return an opaque container, +// that is, the function return type is modified accordingly +// (cf AbstractMetaFunction::generateOpaqueContainerReturn()) +bool AbstractMetaType::generateOpaqueContainerForGetter(const QString &modifiedType) const +{ + auto predicate = [&modifiedType](const ContainerTypeEntryCPtr &t, + const QStringList &instantiations) { + return t->opaqueContainerName(instantiations) == modifiedType; + }; + return d->generateOpaqueContainer(predicate); } #ifndef QT_NO_DEBUG_STREAM void AbstractMetaType::formatDebug(QDebug &debug) const { debug << '"' << name() << '"'; - if (debug.verbosity() > 2) { + if (debug.verbosity() > 2 && !isVoid()) { auto te = typeEntry(); debug << ", typeEntry="; if (debug.verbosity() > 3) @@ -769,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]"; @@ -780,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); |