aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetalang.cpp')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp398
1 files changed, 281 insertions, 117 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 5be7050bf..c65d7e0bd 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -27,10 +27,13 @@
****************************************************************************/
#include "abstractmetalang.h"
+#include "messages.h"
#include "reporthandler.h"
#include "typedatabase.h"
#include "typesystem.h"
+#include <parser/codemodel.h>
+
#ifndef QT_NO_DEBUG_STREAM
# include <QtCore/QMetaEnum>
# include <QtCore/QMetaObject>
@@ -55,6 +58,16 @@ QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa)
}
#endif // !QT_NO_DEBUG_STREAM
+template <class MetaClass>
+MetaClass *findByName(QVector<MetaClass *> haystack, QStringView needle)
+{
+ for (MetaClass *c : haystack) {
+ if (c->name() == needle)
+ return c;
+ }
+ return nullptr;
+}
+
/*******************************************************************************
* AbstractMetaVariable
*/
@@ -112,8 +125,8 @@ void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes &
AbstractMetaType::AbstractMetaType() :
m_constant(false),
+ m_volatile(false),
m_cppInstantiation(true),
- m_indirections(0),
m_reserved(0)
{
}
@@ -155,8 +168,9 @@ AbstractMetaType *AbstractMetaType::copy() const
cpy->setTypeUsagePattern(typeUsagePattern());
cpy->setConstant(isConstant());
+ cpy->setVolatile(isVolatile());
cpy->setReferenceType(referenceType());
- cpy->setIndirections(indirections());
+ cpy->setIndirectionsV(indirectionsV());
cpy->setInstantiations(instantiations());
cpy->setArrayElementCount(arrayElementCount());
cpy->setOriginalTypeDescription(originalTypeDescription());
@@ -278,6 +292,26 @@ bool AbstractMetaType::hasTemplateChildren() const
return false;
}
+bool AbstractMetaType::equals(const AbstractMetaType &rhs) const
+{
+ if (m_typeEntry != rhs.m_typeEntry || m_constant != rhs.m_constant
+ || m_referenceType != rhs.m_referenceType
+ || m_indirections != rhs.m_indirections
+ || m_instantiations.size() != rhs.m_instantiations.size()
+ || m_arrayElementCount != rhs.m_arrayElementCount) {
+ return false;
+ }
+ if ((m_arrayElementType != nullptr) != (rhs.m_arrayElementType != nullptr)
+ || (m_arrayElementType != nullptr && !m_arrayElementType->equals(*rhs.m_arrayElementType))) {
+ return false;
+ }
+ for (int i = 0, size = m_instantiations.size(); i < size; ++i) {
+ if (!m_instantiations.at(i)->equals(*rhs.m_instantiations.at(i)))
+ return false;
+ }
+ return true;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const AbstractMetaType *at)
{
@@ -291,16 +325,32 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at)
d << ", typeEntry=" << at->typeEntry() << ", signature=\""
<< at->cppSignature() << "\", pattern="
<< at->typeUsagePattern();
- if (at->indirections())
- d << ", indirections=" << at->indirections();
+ const auto indirections = at->indirectionsV();
+ if (!indirections.isEmpty()) {
+ d << ", indirections=";
+ for (auto i : indirections)
+ d << ' ' << TypeInfo::indirectionKeyword(i);
+ }
if (at->referenceType())
d << ", reftype=" << at->referenceType();
if (at->isConstant())
d << ", [const]";
+ if (at->isVolatile())
+ d << ", [volatile]";
if (at->isArray()) {
d << ", array of \"" << at->arrayElementType()->cppSignature()
<< "\", arrayElementCount=" << at->arrayElementCount();
}
+ const auto &instantiations = at->instantiations();
+ if (const int instantiationsSize = instantiations.size()) {
+ d << ", instantiations[" << instantiationsSize << "]=<";
+ for (int i = 0; i < instantiationsSize; ++i) {
+ if (i)
+ d << ", ";
+ d << instantiations.at(i);
+ }
+ }
+ d << '>';
}
} else {
d << '0';
@@ -357,7 +407,8 @@ AbstractMetaFunction::AbstractMetaFunction()
m_userAdded(false),
m_explicit(false),
m_pointerOperator(false),
- m_isCallOperator(false)
+ m_isCallOperator(false),
+ m_generateExceptionHandling(false)
{
}
@@ -475,6 +526,8 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const
if (type())
cpy->setType(type()->copy());
cpy->setConstant(isConstant());
+ cpy->setExceptionSpecification(m_exceptionSpecification);
+ cpy->setGenerateExceptionHandling(m_generateExceptionHandling);
for (AbstractMetaArgument *arg : m_arguments)
cpy->addArgument(arg->copy());
@@ -504,18 +557,17 @@ QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStrin
if (arguments.size() == resolvedArguments.size()) {
QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')');
return QStringList(TypeDatabase::normalizedSignature(signature));
- } else {
- QStringList returned;
-
- AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
- QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::"));
- for (int i = 0; i < minimalTypeSignature.size(); ++i) {
- returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
- << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::")));
- }
+ }
+ QStringList returned;
- return returned;
+ AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
+ QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::"));
+ for (int i = 0; i < minimalTypeSignature.size(); ++i) {
+ returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
+ << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::")));
}
+
+ return returned;
}
QString AbstractMetaFunction::signature() const
@@ -674,38 +726,54 @@ bool AbstractMetaFunction::argumentRemoved(int key) const
return false;
}
-bool AbstractMetaFunction::isVirtualSlot() const
+bool AbstractMetaFunction::isDeprecated() const
{
const FunctionModificationList &modifications = this->modifications(declaringClass());
for (const FunctionModification &modification : modifications) {
- if (modification.isVirtualSlot())
+ if (modification.isDeprecated())
return true;
}
-
return false;
}
-bool AbstractMetaFunction::isDeprecated() const
+// Auto-detect whether a function should be wrapped into
+// Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS, that is, temporarily release
+// the GIL (global interpreter lock). Doing so is required for any thread-wait
+// functions, anything that might call a virtual function (potentially
+// reimplemented in Python), and recommended for lengthy I/O or similar.
+// It has performance costs, though.
+bool AbstractMetaFunction::autoDetectAllowThread() const
{
- const FunctionModificationList &modifications = this->modifications(declaringClass());
- for (const FunctionModification &modification : modifications) {
- if (modification.isDeprecated())
- return true;
- }
- return false;
+ // Disallow for simple getter functions.
+ const bool maybeGetter = m_constant != 0 && m_type != nullptr
+ && m_arguments.isEmpty();
+ return !maybeGetter;
}
bool AbstractMetaFunction::allowThread() const
{
- const FunctionModificationList &modifications = this->modifications(declaringClass());
- for (const FunctionModification &modification : modifications) {
- if (modification.allowThread())
- return true;
+ using AllowThread = TypeSystem::AllowThread;
+
+ if (m_cachedAllowThread < 0) {
+ AllowThread allowThread = AllowThread::Auto;
+ // Find a modification that specifies allowThread
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ if (modification.allowThread() != AllowThread::Unspecified) {
+ allowThread = modification.allowThread();
+ break;
+ }
+ }
+
+ m_cachedAllowThread = allowThread == AllowThread::Allow
+ || (allowThread == AllowThread::Auto && autoDetectAllowThread()) ? 1 : 0;
+
+ if (m_cachedAllowThread == 0)
+ qCDebug(lcShiboken).noquote() << msgDisallowThread(this);
}
- return false;
+ return m_cachedAllowThread > 0;
}
-
TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
{
const FunctionModificationList &modifications = this->modifications(cls);
@@ -751,6 +819,18 @@ QString AbstractMetaFunction::typeReplaced(int key) const
return QString();
}
+bool AbstractMetaFunction::isModifiedToArray(int argumentIndex) const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == argumentIndex && argumentModification.array != 0)
+ return true;
+ }
+ }
+ return false;
+}
+
QString AbstractMetaFunction::minimalSignature() const
{
if (!m_cachedMinimalSignature.isEmpty())
@@ -809,8 +889,9 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC
while (implementor) {
mods += implementor->typeEntry()->functionModifications(minimalSignature());
if ((implementor == implementor->baseClass()) ||
- (implementor == implementingClass() && (mods.size() > 0)))
+ (implementor == implementingClass() && !mods.isEmpty())) {
break;
+ }
const AbstractMetaClassList &interfaces = implementor->interfaces();
for (const AbstractMetaClass *interface : interfaces)
mods += this->modifications(interface);
@@ -873,14 +954,24 @@ bool AbstractMetaFunction::hasSignatureModifications() const
return false;
}
-bool AbstractMetaFunction::isConversionOperator(QString funcName)
+bool AbstractMetaFunction::isConversionOperator(const QString& funcName)
{
static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$"));
Q_ASSERT(opRegEx.isValid());
return opRegEx.match(funcName).hasMatch();
}
-bool AbstractMetaFunction::isOperatorOverload(QString funcName)
+ExceptionSpecification AbstractMetaFunction::exceptionSpecification() const
+{
+ return m_exceptionSpecification;
+}
+
+void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e)
+{
+ m_exceptionSpecification = e;
+}
+
+bool AbstractMetaFunction::isOperatorOverload(const QString& funcName)
{
if (isConversionOperator(funcName))
return true;
@@ -1038,6 +1129,13 @@ bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
return a->signature() < b->signature();
}
+AbstractMetaFunction *
+AbstractMetaFunction::find(const AbstractMetaFunctionList &haystack,
+ const QString &needle)
+{
+ return findByName(haystack, needle);
+}
+
#ifndef QT_NO_DEBUG_STREAM
static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af)
{
@@ -1046,7 +1144,20 @@ static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction
void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const
{
- d << m_functionType << ' ' << m_type << ' ' << m_name << '(';
+ d << m_functionType << ' ' << m_type << ' ' << m_name;
+ switch (m_exceptionSpecification) {
+ case ExceptionSpecification::Unknown:
+ break;
+ case ExceptionSpecification::NoExcept:
+ d << " noexcept";
+ break;
+ case ExceptionSpecification::Throws:
+ d << " throw(...)";
+ break;
+ }
+ if (m_generateExceptionHandling)
+ d << "[generate-exception-handling]";
+ d << '(';
for (int i = 0, count = m_arguments.size(); i < count; ++i) {
if (i)
d << ", ";
@@ -1106,7 +1217,6 @@ AbstractMetaClass::AbstractMetaClass()
: m_hasVirtuals(false),
m_isPolymorphic(false),
m_hasNonpublic(false),
- m_hasVirtualSlots(false),
m_hasNonPrivateConstructor(false),
m_hasPrivateConstructor(false),
m_functionsFixed(false),
@@ -1330,11 +1440,8 @@ void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
for (AbstractMetaFunction *f : qAsConst(m_functions)) {
f->setOwnerClass(this);
-
- m_hasVirtualSlots = m_hasVirtualSlots || f->isVirtualSlot();
- m_hasVirtuals = m_hasVirtuals || f->isVirtualSlot() || hasVirtualDestructor();
- m_isPolymorphic = m_isPolymorphic || m_hasVirtuals;
- m_hasNonpublic = m_hasNonpublic || !f->isPublic();
+ if (!f->isPublic())
+ m_hasNonpublic = true;
}
}
@@ -1368,8 +1475,7 @@ void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
else
Q_ASSERT(false); //memory leak
- m_hasVirtualSlots |= function->isVirtualSlot();
- m_hasVirtuals |= function->isVirtual() || function->isVirtualSlot() || hasVirtualDestructor();
+ m_hasVirtuals |= function->isVirtual() || hasVirtualDestructor();
m_isPolymorphic |= m_hasVirtuals;
m_hasNonpublic |= !function->isPublic();
}
@@ -1432,11 +1538,7 @@ bool AbstractMetaClass::hasFunction(const QString &str) const
const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& functionName) const
{
- for (const AbstractMetaFunction *f : m_functions) {
- if (f->name() == functionName)
- return f;
- }
- return 0;
+ return AbstractMetaFunction::find(m_functions, functionName);
}
bool AbstractMetaClass::hasProtectedFunctions() const
@@ -1511,6 +1613,13 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList&
metaClassBaseTemplateInstantiations()->insert(this, instantiations);
}
+// Does any of the base classes require deletion in the main thread?
+bool AbstractMetaClass::deleteInMainThread() const
+{
+ return typeEntry()->deleteInMainThread()
+ || (m_baseClass && m_baseClass->deleteInMainThread());
+}
+
static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func)
{
for (const AbstractMetaFunction *f : l) {
@@ -1537,6 +1646,11 @@ AbstractMetaField *AbstractMetaField::copy() const
return returned;
}
+AbstractMetaField *AbstractMetaField::find(const AbstractMetaFieldList &haystack,
+ const QString &needle)
+{
+ return findByName(haystack, needle);
+}
/*******************************************************************************
* Indicates that this field has a modification that removes it
*/
@@ -1723,27 +1837,22 @@ QDebug operator<<(QDebug d, const AbstractMetaEnum *ae)
bool AbstractMetaClass::hasConstructors() const
{
- return queryFunctions(Constructors).size();
+ return AbstractMetaClass::queryFirstFunction(m_functions, Constructors) != nullptr;
}
-bool AbstractMetaClass::hasCopyConstructor() const
+const AbstractMetaFunction *AbstractMetaClass::copyConstructor() const
{
- const AbstractMetaFunctionList &ctors = queryFunctions(Constructors);
- for (const AbstractMetaFunction* ctor : ctors) {
- if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction)
- return true;
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->functionType() == AbstractMetaFunction::CopyConstructorFunction)
+ return f;
}
- return false;
+ return nullptr;
}
bool AbstractMetaClass::hasPrivateCopyConstructor() const
{
- const AbstractMetaFunctionList &ctors = queryFunctions(Constructors);
- for (const AbstractMetaFunction *ctor : ctors) {
- if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate())
- return true;
- }
- return false;
+ const AbstractMetaFunction *copyCt = copyConstructor();
+ return copyCt && copyCt->isPrivate();
}
void AbstractMetaClass::addDefaultConstructor()
@@ -1801,85 +1910,122 @@ bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
return functions_contains(m_functions, f);
}
+bool AbstractMetaClass::generateExceptionHandling() const
+{
+ return queryFirstFunction(m_functions, AbstractMetaClass::Visible
+ | AbstractMetaClass::GenerateExceptionHandling) != nullptr;
+}
/* Goes through the list of functions and returns a list of all
functions matching all of the criteria in \a query.
*/
-AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const
+bool AbstractMetaClass::queryFunction(const AbstractMetaFunction *f, FunctionQueryOptions query)
{
- AbstractMetaFunctionList functions;
-
- for (AbstractMetaFunction *f : m_functions) {
- if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode))
- continue;
+ if ((query & NotRemovedFromTargetLang)
+ && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) {
+ return false;
+ }
- if ((query & NotRemovedFromTargetLang) && f->isVirtual() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode))
- continue;
+ if ((query & NotRemovedFromTargetLang) && f->isVirtual()
+ && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) {
+ return false;
+ }
- if ((query & Visible) && f->isPrivate())
- continue;
+ if ((query & Visible) && f->isPrivate())
+ return false;
- if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang())
- continue;
+ if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang())
+ return false;
- if ((query & Invisible) && !f->isPrivate())
- continue;
+ if ((query & Invisible) && !f->isPrivate())
+ return false;
- if ((query & Empty) && !f->isEmptyFunction())
- continue;
+ if ((query & Empty) && !f->isEmptyFunction())
+ return false;
- if ((query & WasPublic) && !f->wasPublic())
- continue;
+ if ((query & WasPublic) && !f->wasPublic())
+ return false;
- if ((query & ClassImplements) && f->ownerClass() != f->implementingClass())
- continue;
+ if ((query & ClassImplements) && f->ownerClass() != f->implementingClass())
+ return false;
- if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang())
- continue;
+ if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang())
+ return false;
- if ((query & VirtualInCppFunctions) && !f->isVirtual())
- continue;
+ if ((query & VirtualInCppFunctions) && !f->isVirtual())
+ return false;
- if ((query & Signals) && (!f->isSignal()))
- continue;
+ if ((query & Signals) && (!f->isSignal()))
+ return false;
- if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass()))
- continue;
+ if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass()))
+ return false;
- if (!(query & Constructors) && f->isConstructor())
- continue;
+ if (!(query & Constructors) && f->isConstructor())
+ return false;
- // Destructors are never included in the functions of a class currently
- /*
+ // Destructors are never included in the functions of a class currently
+ /*
if ((query & Destructors) && (!f->isDestructor()
|| f->ownerClass() != f->implementingClass())
|| f->isDestructor() && (query & Destructors) == 0) {
- continue;
+ return false;
}*/
- if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal()))
- continue;
+ if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal()))
+ return false;
- if ((query & NonStaticFunctions) && (f->isStatic()))
- continue;
+ if ((query & NonStaticFunctions) && (f->isStatic()))
+ return false;
- if ((query & NormalFunctions) && (f->isSignal()))
- continue;
+ if ((query & NormalFunctions) && (f->isSignal()))
+ return false;
- if ((query & OperatorOverloads) && !f->isOperatorOverload())
- continue;
+ if ((query & OperatorOverloads) && !f->isOperatorOverload())
+ return false;
+
+ if ((query & GenerateExceptionHandling) && !f->generateExceptionHandling())
+ return false;
+
+ return true;
+}
- functions << f;
+AbstractMetaFunctionList AbstractMetaClass::queryFunctionList(const AbstractMetaFunctionList &list,
+ FunctionQueryOptions query)
+{
+ AbstractMetaFunctionList result;
+ for (AbstractMetaFunction *f : list) {
+ if (queryFunction(f, query))
+ result.append(f);
+ }
+ return result;
+}
+
+const AbstractMetaFunction *AbstractMetaClass::queryFirstFunction(const AbstractMetaFunctionList &list,
+ FunctionQueryOptions query)
+{
+ AbstractMetaFunctionList result;
+ for (AbstractMetaFunction *f : list) {
+ if (queryFunction(f, query))
+ return f;
}
+ return nullptr;
+}
- return functions;
+AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const
+{
+ return AbstractMetaClass::queryFunctionList(m_functions, query);
}
bool AbstractMetaClass::hasSignals() const
{
- return cppSignalFunctions().size() > 0;
+ return queryFirstFunction(m_functions, Signals | Visible | NotRemovedFromTargetLang) != nullptr;
}
+AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const
+{
+ return queryFunctions(Signals | Visible | NotRemovedFromTargetLang);
+}
/**
* Adds the specified interface to this class by adding all the
@@ -1932,13 +2078,15 @@ void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
}
}
+AbstractMetaField *AbstractMetaClass::findField(const QString &name) const
+{
+ return AbstractMetaField::find(m_fields, name);
+}
AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
{
- for (AbstractMetaEnum *e : qAsConst(m_enums)) {
- if (e->name() == enumName)
- return e;
- }
+ if (AbstractMetaEnum *e = findByName(m_enums, enumName))
+ return e;
if (typeEntry()->designatedInterface())
return extractInterface()->findEnum(enumName);
@@ -2002,8 +2150,8 @@ void AbstractMetaClass::fixFunctions()
{
if (m_functionsFixed)
return;
- else
- m_functionsFixed = true;
+
+ m_functionsFixed = true;
AbstractMetaClass *superClass = baseClass();
AbstractMetaFunctionList funcs = functions();
@@ -2046,8 +2194,7 @@ void AbstractMetaClass::fixFunctions()
// we generally don't care about private functions, but we have to get the ones that are
// virtual in case they override abstract functions.
bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
- for (int fi = 0; fi < funcs.size(); ++fi) {
- AbstractMetaFunction *f = funcs.at(fi);
+ for (AbstractMetaFunction *f : funcs) {
if (f->isRemovedFromAllLanguages(f->implementingClass()))
continue;
@@ -2114,7 +2261,8 @@ void AbstractMetaClass::fixFunctions()
if (mod.isNonFinal()) {
hasNonFinalModifier = true;
break;
- } else if (mod.isPrivate()) {
+ }
+ if (mod.isPrivate()) {
isBaseImplPrivate = true;
break;
}
@@ -2222,6 +2370,8 @@ QString AbstractMetaType::formatSignature(bool minimal) const
QString result;
if (isConstant())
result += QLatin1String("const ");
+ if (isVolatile())
+ result += QLatin1String("volatile ");
if (isArray()) {
// Build nested array dimensions a[2][3] in correct order
result += m_arrayElementType->minimalSignature();
@@ -2245,10 +2395,10 @@ QString AbstractMetaType::formatSignature(bool minimal) const
result += QLatin1String(" >");
}
- if (!minimal && (m_indirections != 0 || m_referenceType != NoReference))
+ if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference))
result += QLatin1Char(' ');
- if (m_indirections)
- result += QString(m_indirections, QLatin1Char('*'));
+ for (Indirection i : m_indirections)
+ result += TypeInfo::indirectionKeyword(i);
switch (referenceType()) {
case NoReference:
break;
@@ -2376,6 +2526,8 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
d << " [final]";
if (ac->m_baseClass)
d << ", inherits \"" << ac->m_baseClass->name() << '"';
+ if (ac->m_templateBaseClass)
+ d << ", inherits template \"" << ac->m_templateBaseClass->name() << '"';
const AbstractMetaEnumList &enums = ac->enums();
if (!enums.isEmpty())
d << ", enums[" << enums.size() << "]=" << enums;
@@ -2406,6 +2558,18 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
}
d << ')';
}
+ const auto &templateArguments = ac->templateArguments();
+ if (const int count = templateArguments.size()) {
+ d << ", templateArguments=[" << count << "](";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ d << ", ";
+ d << templateArguments.at(i);
+ }
+ d << ')';
+ }
+
+
} else {
d << '0';
}