aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetatype.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetatype.cpp494
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);