aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp706
1 files changed, 379 insertions, 327 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index 84c116708..f6724e61d 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include "abstractmetabuilder_p.h"
+#include "messages.h"
#include "reporthandler.h"
#include "typedatabase.h"
@@ -159,38 +160,18 @@ AbstractMetaEnumList AbstractMetaBuilder::globalEnums() const
return d->m_globalEnums;
}
-static QString msgNoFunctionForModification(const QString &signature,
- const QString &originalSignature,
- const QString &className,
- const QStringList &possibleSignatures,
- const AbstractMetaFunctionList &allFunctions)
-{
- QString result;
- QTextStream str(&result);
- str << "signature '" << signature << '\'';
- if (!originalSignature.isEmpty() && originalSignature != signature)
- str << " (specified as '" << originalSignature << "')";
- str << " for function modification in '"
- << className << "' not found.";
- if (possibleSignatures.isEmpty()) {
- str << " No candidates were found. Member functions: ";
- for (int f = 0, size = allFunctions.size(); f < size; ++f) {
- if (f)
- str << ", ";
- str << allFunctions.at(f)->minimalSignature();
- }
- } else {
- str << " Possible candidates: " << possibleSignatures.join(QLatin1String(", "));
- }
- return result;
+AbstractMetaEnum *AbstractMetaBuilder::findEnum(const TypeEntry *typeEntry) const
+{
+ if (typeEntry && typeEntry->isFlags())
+ typeEntry = static_cast<const FlagsTypeEntry*>(typeEntry)->originator();
+ return d->m_enums.value(typeEntry);
}
void AbstractMetaBuilderPrivate::checkFunctionModifications()
{
- TypeDatabase *types = TypeDatabase::instance();
- const SingleTypeEntryHash entryHash = types->entries();
+ const auto &entries = TypeDatabase::instance()->entries();
- for (SingleTypeEntryHash::const_iterator it = entryHash.cbegin(), end = entryHash.cend(); it != end; ++it) {
+ for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
const TypeEntry *entry = it.value();
if (!entry)
continue;
@@ -241,7 +222,7 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem argument)
+AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument)
{
AbstractMetaClass* returned = 0;
AbstractMetaType *type = translateType(argument->type());
@@ -256,7 +237,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem
/**
* Checks the argument of a hash function and flags the type if it is a complex type
*/
-void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function_item)
+void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 1) {
@@ -269,12 +250,12 @@ void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function
* Check if a class has a debug stream operator that can be used as toString
*/
-void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem function_item)
+void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 2) {
if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) {
- ArgumentModelItem arg = arguments.at(1);
+ const ArgumentModelItem &arg = arguments.at(1);
if (AbstractMetaClass *cls = argumentToClass(arg)) {
if (arg->type().indirections() < 2)
cls->setToStringCapability(true);
@@ -283,7 +264,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem fu
}
}
-void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item)
+void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item)
{
if (item->accessPolicy() != CodeModel::Public)
return;
@@ -348,7 +329,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item
setupFunctionDefaults(metaFunction, baseoperandClass);
baseoperandClass->addFunction(metaFunction);
Q_ASSERT(!metaFunction->wasPrivate());
- } else if (metaFunction) {
+ } else {
delete metaFunction;
}
@@ -356,7 +337,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item
}
}
-void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item)
+void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item)
{
ArgumentList arguments = item->arguments();
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
@@ -404,7 +385,7 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item)
funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
m_currentClass = oldCurrentClass;
- } else if (streamFunction) {
+ } else {
delete streamFunction;
}
@@ -422,7 +403,7 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom,
TypeEntry* entry = types->findType(qualifiedName);
if (entry) {
if (isQObject(dom, qualifiedName) && entry->isComplex())
- ((ComplexTypeEntry*) entry)->setQObject(true);
+ static_cast<ComplexTypeEntry *>(entry)->setQObject(true);
}
}
@@ -475,19 +456,18 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
const ClassList &typeValues = dom->classes();
ReportHandler::setProgressReference(typeValues);
for (const ClassModelItem &item : typeValues) {
- ReportHandler::progress(QLatin1String("Generating class model..."));
- AbstractMetaClass *cls = traverseClass(dom, item);
- if (!cls)
- continue;
-
- addAbstractMetaClass(cls);
+ ReportHandler::progress(QStringLiteral("Generating class model (%1)...")
+ .arg(typeValues.size()));
+ if (AbstractMetaClass *cls = traverseClass(dom, item))
+ addAbstractMetaClass(cls);
}
// We need to know all global enums
const EnumList &enums = dom->enums();
ReportHandler::setProgressReference(enums);
for (const EnumModelItem &item : enums) {
- ReportHandler::progress(QLatin1String("Generating enum model..."));
+ ReportHandler::progress(QStringLiteral("Generating enum model (%1)...")
+ .arg(enums.size()));
AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>());
if (metaEnum) {
if (metaEnum->typeEntry()->generateCode())
@@ -495,10 +475,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
- const QSet<NamespaceModelItem> &namespaceTypeValues = dom->uniqueNamespaces();
+ const auto &namespaceTypeValues = dom->namespaces();
ReportHandler::setProgressReference(namespaceTypeValues);
for (const NamespaceModelItem &item : namespaceTypeValues) {
- ReportHandler::progress(QLatin1String("Generating namespace model..."));
+ ReportHandler::progress(QStringLiteral("Generating namespace model (%1)...")
+ .arg(namespaceTypeValues.size()));
AbstractMetaClass *metaClass = traverseNamespace(dom, item);
if (metaClass)
m_metaClasses << metaClass;
@@ -509,11 +490,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
const TypeDefList typeDefs = dom->typeDefs();
ReportHandler::setProgressReference(typeDefs);
for (const TypeDefModelItem &typeDef : typeDefs) {
- ReportHandler::progress(QLatin1String("Resolving typedefs..."));
- AbstractMetaClass* cls = traverseTypeDef(dom, typeDef);
- addAbstractMetaClass(cls);
+ ReportHandler::progress(QStringLiteral("Resolving typedefs (%1)...")
+ .arg(typeDefs.size()));
+ if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef))
+ addAbstractMetaClass(cls);
}
+ traverseTypesystemTypedefs();
+
for (const ClassModelItem &item : typeValues)
traverseClassMembers(item);
@@ -580,13 +564,12 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
if (cls->isAbstract() && !cls->isInterface())
cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper"));
}
- const TypeEntryHash allEntries = types->allEntries();
- ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem..."));
- for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
- for (TypeEntry *entry : it.value()) {
- if (entry->isPrimitive())
- continue;
-
+ const auto &allEntries = types->entries();
+ ReportHandler::progress(QStringLiteral("Detecting inconsistencies in typesystem (%1)...")
+ .arg(allEntries.size()));
+ for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
+ TypeEntry *entry = it.value();
+ if (!entry->isPrimitive()) {
if ((entry->isValue() || entry->isObject())
&& !entry->isString()
&& !entry->isChar()
@@ -616,20 +599,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
} else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) {
- const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier();
+ const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier();
AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
- bool enumFound = false;
- if (cls) {
- enumFound = cls->findEnum(entry->targetLangName());
- } else { // Global enum
- for (AbstractMetaEnum *metaEnum : qAsConst(m_enums)) {
- if (metaEnum->typeEntry() == entry) {
- enumFound = true;
- break;
- }
- }
- }
+ const bool enumFound = cls
+ ? cls->findEnum(entry->targetLangName()) != nullptr
+ : m_enums.contains(entry);
+
if (!enumFound) {
entry->setCodeGeneration(TypeEntry::GenerateNothing);
qCWarning(lcShiboken).noquote().nospace()
@@ -727,6 +703,15 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
std::puts("");
}
+static bool metaEnumLessThan(const AbstractMetaEnum *e1, const AbstractMetaEnum *e2)
+{ return e1->fullName() < e2->fullName(); }
+
+static bool metaClassLessThan(const AbstractMetaClass *c1, const AbstractMetaClass *c2)
+{ return c1->fullName() < c2->fullName(); }
+
+static bool metaFunctionLessThan(const AbstractMetaFunction *f1, const AbstractMetaFunction *f2)
+{ return f1->name() < f2->name(); }
+
bool AbstractMetaBuilder::build(const QByteArrayList &arguments,
LanguageLevel level,
unsigned clangFlags)
@@ -737,6 +722,14 @@ bool AbstractMetaBuilder::build(const QByteArrayList &arguments,
if (ReportHandler::isDebug(ReportHandler::MediumDebug))
qCDebug(lcShiboken) << dom.data();
d->traverseDom(dom);
+
+ // Ensure that indexes are in alphabetical order, roughly
+ std::sort(d->m_globalEnums.begin(), d->m_globalEnums.end(), metaEnumLessThan);
+ std::sort(d->m_metaClasses.begin(), d->m_metaClasses.end(), metaClassLessThan);
+ std::sort(d->m_templates.begin(), d->m_templates.end(), metaClassLessThan);
+ std::sort(d->m_smartPointers.begin(), d->m_smartPointers.end(), metaClassLessThan);
+ std::sort(d->m_globalFunctions.begin(), d->m_globalFunctions.end(), metaFunctionLessThan);
+
return true;
}
@@ -749,9 +742,6 @@ void AbstractMetaBuilder::setLogDirectory(const QString& logDir)
void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls)
{
- if (!cls)
- return;
-
cls->setOriginalAttributes(cls->attributes());
if (cls->typeEntry()->isContainer()) {
m_templates << cls;
@@ -827,8 +817,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
}
// Traverse namespaces recursively
- const QSet<NamespaceModelItem> &innerNamespaces = namespaceItem->uniqueNamespaces();
- for (const NamespaceModelItem &ni : innerNamespaces) {
+ for (const NamespaceModelItem &ni : namespaceItem->namespaces()) {
AbstractMetaClass* mjc = traverseNamespace(dom, ni);
if (mjc) {
metaClass->addInnerClass(mjc);
@@ -848,7 +837,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
return metaClass;
}
-AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem,
+AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
AbstractMetaClass *enclosing,
const QSet<QString> &enumsDeclarations)
{
@@ -857,7 +846,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
TypeEntry* typeEntry = 0;
if (enumItem->accessPolicy() == CodeModel::Private) {
QStringList names = enumItem->qualifiedName();
- QString enumName = names.constLast();
+ const QString &enumName = names.constLast();
QString nspace;
if (names.size() > 1)
nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon());
@@ -892,15 +881,23 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
return 0;
}
- if ((!typeEntry || !typeEntry->isEnum())) {
- if (!m_currentClass ||
- (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("enum '%1' does not have a type entry or is not an enum")
- .arg(qualifiedName);
+ const bool rejectionWarning = !m_currentClass
+ || (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang);
+
+ if (!typeEntry) {
+ if (rejectionWarning)
+ qCWarning(lcShiboken, "%s", qPrintable(msgNoEnumTypeEntry(enumItem, className)));
+ m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ return nullptr;
+ }
+
+ if (!typeEntry->isEnum()) {
+ if (rejectionWarning) {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgNoEnumTypeConflict(enumItem, className, typeEntry)));
}
m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
- return 0;
+ return nullptr;
}
AbstractMetaEnum *metaEnum = new AbstractMetaEnum;
@@ -946,15 +943,9 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = "
<< metaEnumValue->value() << " = " << metaEnumValue->value();
}
-
- // Add into global register...
- if (enclosing)
- m_enumValues[enclosing->name() + colonColon() + metaEnumValue->name()] = metaEnumValue;
- else
- m_enumValues[metaEnumValue->name()] = metaEnumValue;
}
- m_enums << metaEnum;
+ m_enums.insert(typeEntry, metaEnum);
if (!metaEnum->typeEntry()->include().isValid())
setInclude(metaEnum->typeEntry(), enumItem->fileName());
@@ -962,6 +953,15 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
metaEnum->setOriginalAttributes(metaEnum->attributes());
// Register all enum values on Type database
+ QString prefix;
+ if (enclosing) {
+ prefix += enclosing->typeEntry()->qualifiedCppName();
+ prefix += colonColon();
+ }
+ if (enumItem->enumKind() == EnumClass) {
+ prefix += enumItem->name();
+ prefix += colonColon();
+ }
const EnumeratorList &enumerators = enumItem->enumerators();
for (const EnumeratorModelItem &e : enumerators) {
QString name;
@@ -969,11 +969,12 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte
name += enclosing->name();
name += colonColon();
}
- name += e->name();
EnumValueTypeEntry *enumValue =
- new EnumValueTypeEntry(name, e->stringValue(),
+ new EnumValueTypeEntry(prefix + e->name(), e->stringValue(),
enumTypeEntry, enumTypeEntry->version());
TypeDatabase::instance()->addType(enumValue);
+ if (e->value().isNullValue())
+ enumTypeEntry->setNullValue(enumValue);
}
return metaEnum;
@@ -1014,7 +1015,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
AbstractMetaClass *metaClass = new AbstractMetaClass;
metaClass->setTypeDef(true);
metaClass->setTypeEntry(type);
- metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon()));
+ metaClass->setBaseClassNames(QStringList(typeDef->type().toString()));
*metaClass += AbstractMetaAttributes::Public;
// Set the default include file name
@@ -1026,6 +1027,22 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
return metaClass;
}
+// Add the typedef'ed classes
+void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
+{
+ const auto &entries = TypeDatabase::instance()->typedefEntries();
+ for (auto it = entries.begin(), end = entries.end(); it != end; ++it) {
+ TypedefEntry *te = it.value();
+ AbstractMetaClass *metaClass = new AbstractMetaClass;
+ metaClass->setTypeDef(true);
+ metaClass->setTypeEntry(te->target());
+ metaClass->setBaseClassNames(QStringList(te->sourceType()));
+ *metaClass += AbstractMetaAttributes::Public;
+ fillAddedFunctions(metaClass);
+ addAbstractMetaClass(metaClass);
+ }
+}
+
AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom,
const ClassModelItem &classItem)
{
@@ -1197,25 +1214,24 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem ite
traverseScopeMembers(item, metaClass);
// Inner namespaces
- const QSet<NamespaceModelItem> &innerNamespaces = item->uniqueNamespaces();
- for (const NamespaceModelItem &ni : innerNamespaces)
+ for (const NamespaceModelItem &ni : item->namespaces())
traverseNamespaceMembers(ni);
m_currentClass = oldCurrentClass;
}
-static inline QString fieldSignatureWithType(VariableModelItem field)
+static inline QString fieldSignatureWithType(const VariableModelItem &field)
{
return field->name() + QStringLiteral(" -> ") + field->type().toString();
}
static inline QString qualifiedFieldSignatureWithType(const QString &className,
- VariableModelItem field)
+ const VariableModelItem &field)
{
return className + colonColon() + fieldSignatureWithType(field);
}
-AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem field,
+AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field,
const AbstractMetaClass *cls)
{
QString fieldName = field->name();
@@ -1272,7 +1288,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem f
return metaField;
}
-void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item,
+void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item,
AbstractMetaClass *metaClass)
{
const VariableList &variables = scope_item->variables();
@@ -1327,14 +1343,8 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other)
{
- if (!type && !other)
- return true;
- if (!type || !other)
- return false;
- return type->typeEntry() == other->typeEntry()
- && type->isConstant() == other->isConstant()
- && type->referenceType() == other->referenceType()
- && type->indirections() == other->indirections();
+ return (type != nullptr) == (other != nullptr)
+ && (type == nullptr || *type == *other);
}
static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other)
@@ -1426,7 +1436,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
}
} else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) {
// Property resetter must be in the form "void name()"
- if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) {
+ if ((!metaFunction->type()) && metaFunction->arguments().isEmpty()) {
*metaFunction += AbstractMetaAttributes::PropertyResetter;
metaFunction->setPropertySpec(reset);
}
@@ -1635,7 +1645,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
return true;
}
-void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem,
+void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
AbstractMetaClass *metaClass,
const QStringList &enumsDeclarations)
{
@@ -1724,13 +1734,9 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
if (!replacedExpression.isEmpty()) {
- QString expr = replacedExpression;
if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) {
- metaArg->setDefaultValueExpression(expr);
- metaArg->setOriginalDefaultValueExpression(expr);
-
- if (metaArg->type()->isEnum() || metaArg->type()->isFlags())
- m_enumDefaultArguments << QPair<AbstractMetaArgument*, AbstractMetaFunction*>(metaArg, metaFunction);
+ metaArg->setDefaultValueExpression(replacedExpression);
+ metaArg->setOriginalDefaultValueExpression(replacedExpression);
}
}
}
@@ -1784,7 +1790,7 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, co
}
}
-static QString functionSignature(FunctionModelItem functionItem)
+static QString functionSignature(const FunctionModelItem &functionItem)
{
QStringList args;
const ArgumentList &arguments = functionItem->arguments();
@@ -1802,50 +1808,6 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem
result += functionSignature(functionItem);
return result;
}
-
-static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n)
-{
- QString result;
- QTextStream str(&result);
- str << "unmatched type '" << arg->type().toString() << "' in parameter #"
- << (n + 1);
- if (!arg->name().isEmpty())
- str << " \"" << arg->name() << '"';
- return result;
-}
-
-static inline QString msgUnmatchedReturnType(const FunctionModelItem &functionItem)
-{
- return QLatin1String("unmatched return type '")
- + functionItem->type().toString() + QLatin1Char('\'');
-}
-
-static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n)
-{
- QString result;
- QTextStream str(&result);
- str << "'void' encountered at parameter #" << (n + 1);
- if (!arg->name().isEmpty())
- str << " \"" << arg->name() << '"';
- return result;
-}
-
-static QString msgSkippingFunction(const FunctionModelItem &functionItem,
- const QString &signature, const QString &why)
-{
- QString result;
- QTextStream str(&result);
- str << "skipping ";
- if (functionItem->isAbstract())
- str << "abstract ";
- str << "function '" << signature << "', " << why;
- if (functionItem->isAbstract()) {
- str << "\nThis will lead to compilation errors due to not "
- "being able to instantiate the wrapper.";
- }
- return result;
-}
-
static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeModel::FunctionType ft)
{
AbstractMetaFunction::FunctionType result = AbstractMetaFunction::NormalFunction;
@@ -1874,12 +1836,6 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM
return result;
}
-static inline QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason)
-{
- return function + QLatin1String(": Cannot use parameter ") + QString::number(i + 1)
- + QLatin1String(" as an array: ") + reason;
-}
-
bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func,
const FunctionModelItem &functionItem,
int i)
@@ -1911,12 +1867,40 @@ bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func
return true;
}
-AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem)
+static bool generateExceptionHandling(const AbstractMetaFunction *func,
+ ExceptionSpecification spec,
+ TypeSystem::ExceptionHandling handling)
+{
+ switch (func->functionType()) {
+ case AbstractMetaFunction::CopyConstructorFunction:
+ case AbstractMetaFunction::MoveConstructorFunction:
+ case AbstractMetaFunction::AssignmentOperatorFunction:
+ case AbstractMetaFunction::MoveAssignmentOperatorFunction:
+ case AbstractMetaFunction::DestructorFunction:
+ return false;
+ default:
+ break;
+ }
+ switch (handling) {
+ case TypeSystem::ExceptionHandling::On:
+ return true;
+ case TypeSystem::ExceptionHandling::AutoDefaultToOn:
+ return spec != ExceptionSpecification::NoExcept;
+ case TypeSystem::ExceptionHandling::AutoDefaultToOff:
+ return spec == ExceptionSpecification::Throws;
+ default:
+ break;
+ }
+ return false;
+}
+
+AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem)
{
if (functionItem->isDeleted() || !functionItem->templateParameters().isEmpty())
return nullptr;
QString functionName = functionItem->name();
QString className;
+ TypeSystem::ExceptionHandling exceptionHandling = TypeSystem::ExceptionHandling::Unspecified;
if (m_currentClass) {
// Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT
// and overridden metaObject(), QGADGET helpers
@@ -1925,6 +1909,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
return nullptr;
}
className = m_currentClass->typeEntry()->qualifiedCppName();
+ exceptionHandling = m_currentClass->typeEntry()->exceptionHandling();
if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject"))
return nullptr;
}
@@ -1936,13 +1921,16 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
QString rejectReason;
if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- return 0;
- }
- else if (TypeDatabase::instance()->isFunctionRejected(className,
- functionSignature(functionItem), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- return 0;
+ return nullptr;
}
+ const QString &signature = functionSignature(functionItem);
+ const bool rejected =
+ TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason);
+ qCDebug(lcShiboken).nospace().noquote() << __FUNCTION__
+ << ": Checking rejection for signature \"" << signature << "\" for " << className
+ << ": " << rejected;
+ if (rejected)
+ return nullptr;
if (functionItem->isFriend())
return 0;
@@ -1951,6 +1939,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
// Additional check for assignment/move assignment down below
metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType()));
metaFunction->setConstant(functionItem->isConstant());
+ metaFunction->setExceptionSpecification(functionItem->exceptionSpecification());
if (ReportHandler::isDebug(ReportHandler::MediumDebug))
qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()";
@@ -1987,6 +1976,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
else
*metaFunction += AbstractMetaAttributes::Protected;
+ QString errorMessage;
switch (metaFunction->functionType()) {
case AbstractMetaFunction::DestructorFunction:
break;
@@ -2005,9 +1995,9 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
AbstractMetaType *type = nullptr;
if (!returnType.isVoid()) {
- type = translateType(returnType);
+ type = translateType(returnType, true, &errorMessage);
if (!type) {
- const QString reason = msgUnmatchedReturnType(functionItem);
+ const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
@@ -2033,7 +2023,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
AbstractMetaArgumentList metaArguments;
for (int i = 0; i < arguments.size(); ++i) {
- ArgumentModelItem arg = arguments.at(i);
+ const ArgumentModelItem &arg = arguments.at(i);
if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
@@ -2041,7 +2031,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
return nullptr;
}
- AbstractMetaType *metaType = translateType(arg->type());
+ AbstractMetaType *metaType = translateType(arg->type(), true, &errorMessage);
if (!metaType) {
// If an invalid argument has a default value, simply remove it
if (arg->defaultValue()) {
@@ -2058,18 +2048,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
break;
}
Q_ASSERT(metaType == 0);
- const QString reason = msgUnmatchedParameterType(arg, i);
- qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
- + QLatin1String(": ") + reason;
- m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
- delete metaFunction;
- return nullptr;
- }
-
- if (metaType == Q_NULLPTR) {
- const QString reason = msgVoidParameterType(arg, i);
+ const QString reason = msgUnmatchedParameterType(arg, i, errorMessage);
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
@@ -2089,9 +2068,22 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
metaFunction->setArguments(metaArguments);
+ const FunctionModificationList functionMods = metaFunction->modifications(m_currentClass);
+
+ for (const FunctionModification &mod : functionMods) {
+ if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified) {
+ exceptionHandling = mod.exceptionHandling();
+ break;
+ }
+ }
+
+ metaFunction->setGenerateExceptionHandling(generateExceptionHandling(metaFunction,
+ functionItem->exceptionSpecification(),
+ exceptionHandling));
+
// Find the correct default values
for (int i = 0, size = metaArguments.size(); i < size; ++i) {
- ArgumentModelItem arg = arguments.at(i);
+ const ArgumentModelItem &arg = arguments.at(i);
AbstractMetaArgument* metaArg = metaArguments.at(i);
//use relace-default-expression for set default value
@@ -2099,9 +2091,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
if (m_currentClass) {
replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
} else {
- FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature());
- if (!mods.isEmpty()) {
- QVector<ArgumentModification> argMods = mods.constFirst().argument_mods;
+ if (!functionMods.isEmpty()) {
+ QVector<ArgumentModification> argMods = functionMods.constFirst().argument_mods;
if (!argMods.isEmpty())
replacedExpression = argMods.constFirst().replacedDefaultExpression;
}
@@ -2119,10 +2110,6 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
expr = replacedExpression;
}
metaArg->setDefaultValueExpression(expr);
-
- if (metaArg->type()->isEnum() || metaArg->type()->isFlags())
- m_enumDefaultArguments << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(metaArg, metaFunction);
-
hasDefaultValue = !expr.isEmpty();
}
@@ -2140,9 +2127,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
}
if (!metaArguments.isEmpty()) {
- const FunctionModificationList &mods = metaFunction->modifications(m_currentClass);
- fixArgumentNames(metaFunction, mods);
- for (const FunctionModification &mod : mods) {
+ fixArgumentNames(metaFunction, functionMods);
+ for (const FunctionModification &mod : functionMods) {
for (const ArgumentModification &argMod : mod.argument_mods) {
if (argMod.array)
setArrayArgumentType(metaFunction, functionItem, argMod.index - 1);
@@ -2202,8 +2188,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction:
if (!type) {
QStringList candidates;
- SingleTypeEntryHash entries = typeDb->entries();
- for (SingleTypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
+ const auto &entries = typeDb->entries();
+ for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
// Let's try to find the type in different scopes.
if (it.key().endsWith(colonColon() + typeName))
candidates.append(it.key());
@@ -2211,15 +2197,17 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction:
QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName);
- if (candidates.isEmpty())
- qFatal(qPrintable(QString(msg + QLatin1String("Declare it in the type system using the proper <*-type> tag."))), NULL);
+ if (candidates.isEmpty()) {
+ qFatal("%sDeclare it in the type system using the proper <*-type> tag.",
+ qPrintable(msg));
+ }
msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n");
candidates.sort();
for (const QString& candidate : qAsConst(candidates)) {
msg += QLatin1String(" ") + candidate + QLatin1Char('\n');
}
- qFatal(qPrintable(msg), NULL);
+ qFatal("%s", qPrintable(msg));
}
AbstractMetaType *metaType = new AbstractMetaType;
@@ -2243,7 +2231,7 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC
{
const TypeEntry* type = 0;
QStringList context = metaClass->qualifiedCppName().split(colonColon());
- while(!type && (context.size() > 0) ) {
+ while (!type && !context.isEmpty()) {
type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName);
context.removeLast();
}
@@ -2251,43 +2239,48 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC
}
AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
- bool resolveType)
+ bool resolveType,
+ QString *errorMessage)
+{
+ return translateTypeStatic(_typei, m_currentClass, this, resolveType, errorMessage);
+}
+
+AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
+ AbstractMetaClass *currentClass,
+ AbstractMetaBuilderPrivate *d,
+ bool resolveType,
+ QString *errorMessageIn)
{
// 1. Test the type info without resolving typedefs in case this is present in the
// type system
- TypeInfo typei;
if (resolveType) {
- if (AbstractMetaType *resolved = translateType(_typei, false))
+ if (AbstractMetaType *resolved = translateTypeStatic(_typei, currentClass, d, false, errorMessageIn))
return resolved;
}
- if (!resolveType) {
- typei = _typei;
- } else {
+ TypeInfo typeInfo = _typei;
+ if (resolveType) {
// Go through all parts of the current scope (including global namespace)
// to resolve typedefs. The parser does not properly resolve typedefs in
// the global scope when they are referenced from inside a namespace.
// This is a work around to fix this bug since fixing it in resolveType
// seemed non-trivial
- int i = m_scopes.size() - 1;
+ int i = d ? d->m_scopes.size() - 1 : -1;
while (i >= 0) {
- typei = TypeInfo::resolveType(_typei, m_scopes.at(i--));
- if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
+ typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--));
+ if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
break;
}
}
- if (typei.isFunctionPointer())
+ if (typeInfo.isFunctionPointer()) {
+ if (errorMessageIn)
+ *errorMessageIn = msgUnableToTranslateType(_typei, QLatin1String("Unsupported function pointer."));
return nullptr;
+ }
QString errorMessage;
- TypeInfo typeInfo = TypeParser::parse(typei.toString(), &errorMessage);
- if (typeInfo.qualifiedName().isEmpty()) {
- qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString()
- << "\": " << errorMessage;
- return 0;
- }
// 2. Handle arrays.
// 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with
@@ -2312,16 +2305,22 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
if (!typeInfo.arrayElements().isEmpty() && !isConstCharStarCase) {
TypeInfo newInfo;
//newInfo.setArguments(typeInfo.arguments());
- newInfo.setIndirections(typeInfo.indirections());
+ newInfo.setIndirectionsV(typeInfo.indirectionsV());
newInfo.setConstant(typeInfo.isConstant());
+ newInfo.setVolatile(typeInfo.isVolatile());
newInfo.setFunctionPointer(typeInfo.isFunctionPointer());
newInfo.setQualifiedName(typeInfo.qualifiedName());
newInfo.setReferenceType(typeInfo.referenceType());
newInfo.setVolatile(typeInfo.isVolatile());
- AbstractMetaType *elementType = translateType(newInfo);
- if (!elementType)
+ AbstractMetaType *elementType = translateTypeStatic(newInfo, currentClass, d, true, &errorMessage);
+ if (!elementType) {
+ if (errorMessageIn) {
+ errorMessage.prepend(QLatin1String("Unable to translate array element: "));
+ *errorMessageIn = msgUnableToTranslateType(_typei, errorMessage);
+ }
return nullptr;
+ }
for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
AbstractMetaType *arrayType = new AbstractMetaType;
@@ -2329,7 +2328,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
const QString &arrayElement = typeInfo.arrayElements().at(i);
if (!arrayElement.isEmpty()) {
bool _ok;
- const qint64 elems = findOutValueFromString(arrayElement, _ok);
+ const qint64 elems = d
+ ? d->findOutValueFromString(arrayElement, _ok)
+ : arrayElement.toLongLong(&_ok, 0);
if (_ok)
arrayType->setArrayElementCount(int(elems));
}
@@ -2344,8 +2345,11 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
QStringList qualifierList = typeInfo.qualifiedName();
if (qualifierList.isEmpty()) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("horribly broken type '%1'").arg(_typei.toString());
+ errorMessage = msgUnableToTranslateType(_typei, QLatin1String("horribly broken type"));
+ if (errorMessageIn)
+ *errorMessageIn = errorMessage;
+ else
+ qCWarning(lcShiboken,"%s", qPrintable(errorMessage));
return nullptr;
}
@@ -2353,19 +2357,21 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
QString name = qualifierList.takeLast();
// 4. Special case QFlags (include instantiation in name)
- if (qualifiedName == QLatin1String("QFlags"))
+ if (qualifiedName == QLatin1String("QFlags")) {
qualifiedName = typeInfo.toString();
+ typeInfo.clearInstantiations();
+ }
const TypeEntry *type = 0;
// 5. Try to find the type
// 5.1 - Try first using the current scope
- if (m_currentClass) {
- type = findTypeEntryUsingContext(m_currentClass, qualifiedName);
+ if (currentClass) {
+ type = findTypeEntryUsingContext(currentClass, qualifiedName);
// 5.1.1 - Try using the class parents' scopes
- if (!type && !m_currentClass->baseClassNames().isEmpty()) {
- const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass);
+ if (!type && d && !currentClass->baseClassNames().isEmpty()) {
+ const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
for (const AbstractMetaClass *cls : baseClasses) {
type = findTypeEntryUsingContext(cls, qualifiedName);
if (type)
@@ -2388,36 +2394,40 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
// 8. No? Check if the current class is a template and this type is one
// of the parameters.
- if (!type && m_currentClass) {
- const QVector<TypeEntry *> &template_args = m_currentClass->templateArguments();
+ if (!type && currentClass) {
+ const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
for (TypeEntry *te : template_args) {
if (te->name() == qualifiedName)
type = te;
}
}
- if (!type)
+ if (!type) {
+ if (errorMessageIn) {
+ *errorMessageIn =
+ msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName));
+ }
return nullptr;
-
- // Used to for diagnostics later...
- m_usedTypes << type;
+ }
// These are only implicit and should not appear in code...
Q_ASSERT(!type->isInterface());
AbstractMetaType *metaType = new AbstractMetaType;
metaType->setTypeEntry(type);
- metaType->setIndirections(typeInfo.indirections());
+ metaType->setIndirectionsV(typeInfo.indirectionsV());
metaType->setReferenceType(typeInfo.referenceType());
metaType->setConstant(typeInfo.isConstant());
+ metaType->setVolatile(typeInfo.isVolatile());
metaType->setOriginalTypeDescription(_typei.toString());
- const auto &templateArguments = typeInfo.arguments();
+ const auto &templateArguments = typeInfo.instantiations();
for (int t = 0, size = templateArguments.size(); t < size; ++t) {
- TypeInfo ti = templateArguments.at(t);
- ti.setQualifiedName(ti.instantiationName());
- AbstractMetaType *targType = translateType(ti);
+ const TypeInfo &ti = templateArguments.at(t);
+ AbstractMetaType *targType = translateTypeStatic(ti, currentClass, d, true, &errorMessage);
if (!targType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage);
delete metaType;
return nullptr;
}
@@ -2434,6 +2444,33 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return metaType;
}
+AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei,
+ AbstractMetaClass *currentClass,
+ bool resolveType,
+ QString *errorMessage)
+{
+ return AbstractMetaBuilderPrivate::translateTypeStatic(_typei, currentClass,
+ nullptr, resolveType,
+ errorMessage);
+}
+
+AbstractMetaType *AbstractMetaBuilder::translateType(const QString &t,
+ AbstractMetaClass *currentClass,
+ bool resolveType,
+ QString *errorMessageIn)
+{
+ QString errorMessage;
+ TypeInfo typeInfo = TypeParser::parse(t, &errorMessage);
+ if (typeInfo.qualifiedName().isEmpty()) {
+ errorMessage = msgUnableToTranslateType(t, errorMessage);
+ if (errorMessageIn)
+ *errorMessageIn = errorMessage;
+ else
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
+ return nullptr;
+ }
+ return translateType(typeInfo, currentClass, resolveType, errorMessageIn);
+}
qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok)
{
@@ -2472,7 +2509,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
return 0;
}
-QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item,
+QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &item,
AbstractMetaType *type,
AbstractMetaFunction *fnc,
AbstractMetaClass *implementingClass,
@@ -2676,59 +2713,55 @@ bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const Abstrac
return false;
}
-AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector<AbstractMetaType *> &templateTypes,
- const AbstractMetaType *metaType,
- bool *ok)
+AbstractMetaType *
+ AbstractMetaBuilderPrivate::inheritTemplateType(const AbstractMetaTypeList &templateTypes,
+ const AbstractMetaType *metaType)
{
- if (ok)
- *ok = true;
- if (!metaType || (!metaType->typeEntry()->isTemplateArgument() && !metaType->hasInstantiations()))
- return metaType ? metaType->copy() : 0;
+ Q_ASSERT(metaType);
+
+ QScopedPointer<AbstractMetaType> returned(metaType->copy());
- AbstractMetaType *returned = metaType->copy();
- returned->setOriginalTemplateType(metaType->copy());
+ if (!metaType->typeEntry()->isTemplateArgument() && !metaType->hasInstantiations())
+ return returned.take();
+
+ returned->setOriginalTemplateType(metaType);
if (returned->typeEntry()->isTemplateArgument()) {
const TemplateArgumentEntry* tae = static_cast<const TemplateArgumentEntry*>(returned->typeEntry());
// If the template is intantiated with void we special case this as rejecting the functions that use this
// parameter from the instantiation.
- if (templateTypes.size() <= tae->ordinal() || templateTypes.at(tae->ordinal())->typeEntry()->name() == QLatin1String("void")) {
- if (ok)
- *ok = false;
- return 0;
- }
+ const AbstractMetaType *templateType = templateTypes.value(tae->ordinal());
+ if (!templateType || templateType->typeEntry()->isVoid())
+ return nullptr;
AbstractMetaType* t = returned->copy();
- t->setTypeEntry(templateTypes.at(tae->ordinal())->typeEntry());
- t->setIndirections(templateTypes.at(tae->ordinal())->indirections() + t->indirections() ? 1 : 0);
+ t->setTypeEntry(templateType->typeEntry());
+ t->setIndirections(templateType->indirections() + t->indirections() ? 1 : 0);
t->decideUsagePattern();
- delete returned;
- returned = inheritTemplateType(templateTypes, t, ok);
- if (ok && !(*ok))
- return 0;
+ return inheritTemplateType(templateTypes, t);
}
if (returned->hasInstantiations()) {
AbstractMetaTypeList instantiations = returned->instantiations();
for (int i = 0; i < instantiations.count(); ++i) {
- AbstractMetaType *type = instantiations[i];
- instantiations[i] = inheritTemplateType(templateTypes, type, ok);
- if (ok && !(*ok))
- return 0;
+ instantiations[i] =
+ inheritTemplateType(templateTypes, instantiations.at(i));
+ if (!instantiations.at(i))
+ return nullptr;
}
returned->setInstantiations(instantiations, true);
}
- return returned;
+ return returned.take();
}
bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
const AbstractMetaClass *templateClass,
const TypeInfo &info)
{
- QVector<TypeInfo> targs = info.arguments();
+ QVector<TypeInfo> targs = info.instantiations();
QVector<AbstractMetaType *> templateTypes;
if (subclass->isTypeDef()) {
@@ -2743,20 +2776,35 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
for (const TypeInfo &i : qAsConst(targs)) {
QString typeName = i.qualifiedName().join(colonColon());
- QStringList possibleNames;
- possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
- possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
- if (subclass->enclosingClass())
- possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName;
- possibleNames << typeName;
-
- TypeDatabase* typeDb = TypeDatabase::instance();
- TypeEntry* t = 0;
- QString templateParamName;
- for (const QString &possibleName : qAsConst(possibleNames)) {
- t = typeDb->findType(possibleName);
- if (t)
- break;
+ TypeDatabase *typeDb = TypeDatabase::instance();
+ TypeEntry *t = nullptr;
+ // Check for a non-type template integer parameter, that is, for a base
+ // "template <int R, int C> Matrix<R, C>" and subclass
+ // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of
+ // EnumValueTypeEntry for the integer values encountered on the fly.
+ const bool isNumber = std::all_of(typeName.cbegin(), typeName.cend(),
+ [](QChar c) { return c.isDigit(); });
+ if (isNumber) {
+ t = typeDb->findType(typeName);
+ if (!t) {
+ t = new EnumValueTypeEntry(typeName, typeName, nullptr,
+ QVersionNumber(0, 0));
+ t->setCodeGeneration(0);
+ typeDb->addType(t);
+ }
+ } else {
+ QStringList possibleNames;
+ possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
+ possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
+ if (subclass->enclosingClass())
+ possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName;
+ possibleNames << typeName;
+
+ for (const QString &possibleName : qAsConst(possibleNames)) {
+ t = typeDb->findType(possibleName);
+ if (t)
+ break;
+ }
}
if (t) {
@@ -2764,48 +2812,48 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
temporaryType->setTypeEntry(t);
temporaryType->setConstant(i.isConstant());
temporaryType->setReferenceType(i.referenceType());
- temporaryType->setIndirections(i.indirections());
+ temporaryType->setIndirectionsV(i.indirectionsV());
temporaryType->decideUsagePattern();
templateTypes << temporaryType;
} else {
qCWarning(lcShiboken).noquote().nospace()
- << "Ignoring template parameter " << templateParamName << " from "
- << info.instantiationName() << ", because I don't know what it is.";
+ << "Ignoring template parameter " << typeName << " from "
+ << info.toString() << ". The corresponding type was not found in the typesystem.";
}
}
- AbstractMetaFunctionList funcs = subclass->functions();
+ const AbstractMetaFunctionList &subclassFuncs = subclass->functions();
const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions();
for (const AbstractMetaFunction *function : templateClassFunctions) {
- if (function->isModifiedRemoved(TypeSystem::All))
+ // If the function is modified or the instantiation has an equally named
+ // function we have shadowing, so we need to skip it.
+ if (function->isModifiedRemoved(TypeSystem::All)
+ || AbstractMetaFunction::find(subclassFuncs, function->name()) != nullptr) {
continue;
+ }
- AbstractMetaFunction *f = function->copy();
+ QScopedPointer<AbstractMetaFunction> f(function->copy());
f->setArguments(AbstractMetaArgumentList());
- bool ok = true;
- AbstractMetaType *ftype = function->type();
- f->replaceType(inheritTemplateType(templateTypes, ftype, &ok));
- if (!ok) {
- delete f;
- continue;
+ if (function->type()) { // Non-void
+ AbstractMetaType *returnType = inheritTemplateType(templateTypes, function->type());
+ if (!returnType)
+ continue;
+ f->replaceType(returnType);
}
const AbstractMetaArgumentList &arguments = function->arguments();
for (AbstractMetaArgument *argument : arguments) {
- AbstractMetaType* atype = argument->type();
-
- AbstractMetaArgument *arg = argument->copy();
- arg->replaceType(inheritTemplateType(templateTypes, atype, &ok));
- if (!ok)
+ AbstractMetaType *argType = inheritTemplateType(templateTypes, argument->type());
+ if (!argType)
break;
+ AbstractMetaArgument *arg = argument->copy();
+ arg->replaceType(argType);
f->addArgument(arg);
}
- if (!ok) {
- delete f;
+ if (f->arguments().size() < function->arguments().size())
continue;
- }
// There is no base class in the target language to inherit from here, so
// the template instantiation is the class that implements the function.
@@ -2816,27 +2864,11 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
// on the inherited functions.
f->setDeclaringClass(subclass);
-
- if (f->isConstructor() && subclass->isTypeDef()) {
+ if (f->isConstructor()) {
+ if (!subclass->isTypeDef())
+ continue;
f->setName(subclass->name());
f->setOriginalName(subclass->name());
- } else if (f->isConstructor()) {
- delete f;
- continue;
- }
-
- // if the instantiation has a function named the same as an existing
- // function we have shadowing so we need to skip it.
- bool found = false;
- for (int i = 0; i < funcs.size(); ++i) {
- if (funcs.at(i)->name() == f->name()) {
- found = true;
- continue;
- }
- }
- if (found) {
- delete f;
- continue;
}
ComplexTypeEntry* te = subclass->typeEntry();
@@ -2863,7 +2895,27 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
te->addFunctionModification(mod);
}
- subclass->addFunction(f);
+ subclass->addFunction(f.take());
+ }
+
+ const AbstractMetaFieldList &subClassFields = subclass->fields();
+ const AbstractMetaFieldList &templateClassFields = templateClass->fields();
+ for (const AbstractMetaField *field : templateClassFields) {
+ // If the field is modified or the instantiation has a field named
+ // the same as an existing field we have shadowing, so we need to skip it.
+ if (field->isModifiedRemoved(TypeSystem::All)
+ || field->attributes().testFlag(AbstractMetaAttributes::Static)
+ || AbstractMetaField::find(subClassFields, field->name()) != nullptr) {
+ continue;
+ }
+
+ QScopedPointer<AbstractMetaField> f(field->copy());
+ f->setEnclosingClass(subclass);
+ AbstractMetaType *fieldType = inheritTemplateType(templateTypes, field->type());
+ if (!fieldType)
+ continue;
+ f->replaceType(fieldType);
+ subclass->addField(f.take());
}
subclass->setTemplateBaseClass(templateClass);
@@ -2878,9 +2930,9 @@ void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass,
const QStringList &declarations)
{
for (int i = 0; i < declarations.size(); ++i) {
- QString p = declarations.at(i);
+ const QString &p = declarations.at(i);
- QStringList l = p.split(QLatin1String(" "));
+ QStringList l = p.split(QLatin1Char(' '));
QStringList qualifiedScopeName = currentScope()->qualifiedName();
@@ -2925,8 +2977,8 @@ void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass,
static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls)
{
- AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible);
- functions << cls->queryFunctions(AbstractMetaClass::Visible);
+
+ const auto &functions = cls->functions();
for (AbstractMetaFunction *f : qAsConst(functions)) {
const AbstractMetaFunction::FunctionType t = f->functionType();