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.cpp832
1 files changed, 422 insertions, 410 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index ae3cdd86b..5ab6c1976 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -28,6 +28,7 @@
#include "abstractmetabuilder_p.h"
#include "messages.h"
+#include "propertyspec.h"
#include "reporthandler.h"
#include "typedatabase.h"
@@ -42,7 +43,6 @@
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
-#include <QTextCodec>
#include <QTextStream>
#include <QVariant>
#include <QTime>
@@ -135,27 +135,27 @@ AbstractMetaBuilder::~AbstractMetaBuilder()
delete d;
}
-AbstractMetaClassList AbstractMetaBuilder::classes() const
+const AbstractMetaClassList &AbstractMetaBuilder::classes() const
{
return d->m_metaClasses;
}
-AbstractMetaClassList AbstractMetaBuilder::templates() const
+const AbstractMetaClassList &AbstractMetaBuilder::templates() const
{
return d->m_templates;
}
-AbstractMetaClassList AbstractMetaBuilder::smartPointers() const
+const AbstractMetaClassList &AbstractMetaBuilder::smartPointers() const
{
return d->m_smartPointers;
}
-AbstractMetaFunctionList AbstractMetaBuilder::globalFunctions() const
+const AbstractMetaFunctionList &AbstractMetaBuilder::globalFunctions() const
{
return d->m_globalFunctions;
}
-AbstractMetaEnumList AbstractMetaBuilder::globalEnums() const
+const AbstractMetaEnumList &AbstractMetaBuilder::globalEnums() const
{
return d->m_globalEnums;
}
@@ -175,12 +175,12 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
const TypeEntry *entry = it.value();
if (!entry)
continue;
- if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
+ if (!entry->isComplex() || !entry->generateCode())
continue;
auto centry = static_cast<const ComplexTypeEntry *>(entry);
- if (!(centry->codeGeneration() & TypeEntry::GenerateTargetLang))
+ if (!centry->generateCode())
continue;
FunctionModificationList modifications = centry->functionModifications();
@@ -213,9 +213,8 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
if (!found) {
qCWarning(lcShiboken).noquote().nospace()
- << msgNoFunctionForModification(signature,
+ << msgNoFunctionForModification(clazz, signature,
modification.originalSignature(),
- clazz->qualifiedCppName(),
possibleSignatures, functions);
}
}
@@ -270,7 +269,7 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI
const ArgumentModelItem &arg = arguments.at(1);
if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) {
if (arg->type().indirections() < 2)
- cls->setToStringCapability(true, arg->type().indirections());
+ cls->setToStringCapability(true, int(arg->type().indirections()));
}
}
}
@@ -291,7 +290,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
if (arguments.size() == 1) {
unaryOperator = true;
} else if (!baseoperandClass
- || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) {
+ || !baseoperandClass->typeEntry()->generateCode()) {
baseoperandClass = argumentToClass(arguments.at(1), currentClass);
firstArgumentIsSelf = false;
} else {
@@ -410,6 +409,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
unsigned clangFlags)
{
clang::Builder builder;
+ builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes());
if (level == LanguageLevel::Default)
level = clang::emulatedCompilerLanguageLevel();
arguments.prepend(QByteArrayLiteral("-std=")
@@ -512,8 +512,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
ReportHandler::startProgress("Fixing class inheritance...");
for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
- if (!cls->isInterface() && !cls->isNamespace()) {
+ if (!cls->isNamespace()) {
setupInheritance(cls);
+ if (cls->templateBaseClass())
+ inheritTemplateFunctions(cls);
if (!cls->hasVirtualDestructor() && cls->baseClass()
&& cls->baseClass()->hasVirtualDestructor())
cls->setHasVirtualDestructor(true);
@@ -530,7 +532,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
.arg(cls->name());
} else {
const bool couldAddDefaultCtors = cls->isConstructible()
- && !cls->isInterface() && !cls->isNamespace()
+ && !cls->isNamespace()
&& (cls->attributes() & AbstractMetaAttributes::HasRejectedConstructor) == 0;
if (couldAddDefaultCtors) {
if (!cls->hasConstructors())
@@ -539,9 +541,6 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls));
}
}
-
- if (cls->isAbstract() && !cls->isInterface())
- cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper"));
}
const auto &allEntries = types->entries();
@@ -552,16 +551,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
if (!entry->isPrimitive()) {
if ((entry->isValue() || entry->isObject())
&& !types->shouldDropTypeEntry(entry->qualifiedCppName())
- && !entry->isString()
- && !entry->isChar()
&& !entry->isContainer()
&& !entry->isCustom()
- && !entry->isVariant()
- && (entry->generateCode() & TypeEntry::GenerateTargetLang)
+ && entry->generateCode()
&& !AbstractMetaClass::findClass(m_metaClasses, entry)) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
- .arg(entry->qualifiedCppName());
+ qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry)));
} else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
auto fte = static_cast<const FunctionTypeEntry *>(entry);
const QStringList &signatures = fte->signatures();
@@ -574,24 +568,24 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
if (!ok) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
- .arg(signature);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgGlobalFunctionNotDefined(fte, signature)));
}
}
- } else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) {
- const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier();
- AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
+ } else if (entry->isEnum() && entry->generateCode()) {
+ auto enumEntry = static_cast<const EnumTypeEntry *>(entry);
+ const QString name = enumEntry->targetLangQualifier();
+ AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses,
+ enumEntry->parent());
const bool enumFound = cls
- ? cls->findEnum(entry->targetLangName()) != nullptr
+ ? cls->findEnum(entry->targetLangEntryName()) != nullptr
: m_enums.contains(entry);
if (!enumFound) {
entry->setCodeGeneration(TypeEntry::GenerateNothing);
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("enum '%1' is specified in typesystem, but not declared")
- .arg(entry->qualifiedCppName());
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgEnumNotDefined(enumEntry)));
}
}
@@ -680,6 +674,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
m_itemToClass.clear();
+ m_typeSystemTypeDefs.clear();
ReportHandler::endProgress();
}
@@ -732,12 +727,6 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls,
m_smartPointers << cls;
} else {
m_metaClasses << cls;
- if (cls->typeEntry()->designatedInterface()) {
- AbstractMetaClass *interface = cls->extractInterface();
- m_metaClasses << interface;
- if (ReportHandler::isDebug(ReportHandler::SparseDebug))
- qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name());
- }
}
}
@@ -756,11 +745,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName());
if (!type) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName)));
return nullptr;
}
+ if (namespaceItem->type() == NamespaceType::Inline) {
+ type->setInlineNamespace(true);
+ TypeDatabase::instance()->addInlineNamespaceLookups(type);
+ }
+
// Continue populating namespace?
AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type);
if (!metaClass) {
@@ -781,11 +775,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
m_itemToClass.insert(namespaceItem.data(), metaClass);
}
- if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
- qCDebug(lcShiboken)
- << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name());
- }
-
traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
pushScope(namespaceItem);
@@ -836,13 +825,10 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
QString qualifiedName = enumItem->qualifiedName().join(colonColon());
TypeEntry *typeEntry = nullptr;
+ const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr;
if (enumItem->accessPolicy() == CodeModel::Private) {
- QStringList names = enumItem->qualifiedName();
- const QString &enumName = names.constLast();
- QString nspace;
- if (names.size() > 1)
- nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon());
- typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0));
+ typeEntry = new EnumTypeEntry(enumItem->qualifiedName().constLast(),
+ QVersionNumber(0, 0), enclosingTypeEntry);
TypeDatabase::instance()->addType(typeEntry);
} else if (enumItem->enumKind() != AnonymousEnum) {
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
@@ -862,8 +848,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
QString enumName = enumItem->name();
QString className;
- if (enclosing)
- className = enclosing->typeEntry()->qualifiedCppName();
+ if (enclosingTypeEntry)
+ className = enclosingTypeEntry->qualifiedCppName();
QString rejectReason;
if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
@@ -873,8 +859,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
return nullptr;
}
- const bool rejectionWarning = !enclosing
- || (enclosing->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang);
+ const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode();
if (!typeEntry) {
if (rejectionWarning)
@@ -917,9 +902,6 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
break;
}
- if (ReportHandler::isDebug(ReportHandler::MediumDebug))
- qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName();
-
const EnumeratorList &enums = enumItem->enumerators();
for (const EnumeratorModelItem &value : enums) {
@@ -930,11 +912,6 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
metaEnumValue->setStringValue(value->stringValue());
metaEnumValue->setValue(value->value());
metaEnum->addEnumValue(metaEnumValue);
-
- if (ReportHandler::isDebug(ReportHandler::FullDebug)) {
- qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = "
- << metaEnumValue->value() << " = " << metaEnumValue->value();
- }
}
m_enums.insert(typeEntry, metaEnum);
@@ -945,25 +922,13 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
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 bool isScopedEnum = enumItem->enumKind() == EnumClass;
const EnumeratorList &enumerators = enumItem->enumerators();
for (const EnumeratorModelItem &e : enumerators) {
- QString name;
- if (enclosing) {
- name += enclosing->name();
- name += colonColon();
- }
- EnumValueTypeEntry *enumValue =
- new EnumValueTypeEntry(prefix + e->name(), e->stringValue(),
- enumTypeEntry, enumTypeEntry->version());
+ auto enumValue =
+ new EnumValueTypeEntry(e->name(), e->stringValue(),
+ enumTypeEntry, isScopedEnum,
+ enumTypeEntry->version());
TypeDatabase::instance()->addType(enumValue);
if (e->value().isNullValue())
enumTypeEntry->setNullValue(enumValue);
@@ -1030,6 +995,23 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
*metaClass += AbstractMetaAttributes::Public;
fillAddedFunctions(metaClass);
addAbstractMetaClass(metaClass, nullptr);
+ // Ensure base classes are set up when traversing functions for the
+ // type to be resolved.
+ if (setupInheritance(metaClass)) {
+ // Create an entry to look up up types obtained from parsing
+ // functions in reverse. As opposed to container specializations,
+ // which are generated into every instantiating module (indicated
+ // by ContainerTypeEntry::targetLangPackage() being empty), the
+ // correct index array of the module needs to be found by reverse
+ // mapping the instantiations to the typedef entry.
+ // Synthesize a AbstractMetaType which would be found by an
+ // instantiation.
+ auto sourceType = new AbstractMetaType;
+ sourceType->setTypeEntry(metaClass->templateBaseClass()->typeEntry());
+ sourceType->setInstantiations(metaClass->templateBaseClassInstantiations());
+ sourceType->decideUsagePattern();
+ m_typeSystemTypeDefs.append({AbstractMetaTypeCPtr(sourceType), metaClass});
+ }
}
}
@@ -1070,6 +1052,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
}
auto *metaClass = new AbstractMetaClass;
+ metaClass->setSourceLocation(classItem->sourceLocation());
metaClass->setTypeEntry(type);
if (classItem->isFinal())
@@ -1087,25 +1070,27 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
if (type->stream())
metaClass->setStream(true);
- if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
const QString message = type->isContainer()
? QStringLiteral("container: '%1'").arg(fullClassName)
: QStringLiteral("class: '%1'").arg(metaClass->fullName());
- qCDebug(lcShiboken) << message;
+ qCInfo(lcShiboken, "%s", qPrintable(message));
}
TemplateParameterList template_parameters = classItem->templateParameters();
QVector<TypeEntry *> template_args;
template_args.clear();
+ auto argumentParent = metaClass->typeEntry()->typeSystemTypeEntry();
for (int i = 0; i < template_parameters.size(); ++i) {
const TemplateParameterModelItem &param = template_parameters.at(i);
- TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name(), type->version());
+ auto param_type = new TemplateArgumentEntry(param->name(), type->version(),
+ argumentParent);
param_type->setOrdinal(i);
template_args.append(param_type);
}
metaClass->setTemplateArguments(template_args);
- parseQ_Property(metaClass, classItem->propertyDeclarations());
+ parseQ_Properties(metaClass, classItem->propertyDeclarations());
traverseEnums(classItem, metaClass, classItem->enumsDeclarations());
@@ -1220,10 +1205,9 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel
if (!metaType) {
const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
- if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'")
- .arg(cls->name(), fieldName, type);
+ if (cls->typeEntry()->generateCode()) {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgSkippingField(field, cls->name(), type)));
}
delete metaField;
return nullptr;
@@ -1231,7 +1215,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel
metaField->setType(metaType);
- AbstractMetaAttributes::Attributes attr = nullptr;
+ AbstractMetaAttributes::Attributes attr;
if (field->isStatic())
attr |= AbstractMetaAttributes::Static;
@@ -1295,41 +1279,16 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
if (!retType)
return;
- auto *metaType = new AbstractMetaType;
- metaType->setTypeEntry(retType);
+ auto metaType = new AbstractMetaType(retType);
+ metaType->decideUsagePattern();
metaFunction->replaceType(metaType);
}
-static bool _compareAbstractMetaTypes(const AbstractMetaType *type, const AbstractMetaType *other)
-{
- return (type != nullptr) == (other != nullptr)
- && (type == nullptr || *type == *other);
-}
-
-static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, const AbstractMetaFunction *other)
-{
- if (!func && !other)
- return true;
- if (!func || !other)
- return false;
- if (func->arguments().count() != other->arguments().count()
- || func->isConstant() != other->isConstant()
- || func->isStatic() != other->isStatic()
- || !_compareAbstractMetaTypes(func->type(), other->type())) {
- return false;
- }
- for (int i = 0; i < func->arguments().count(); ++i) {
- if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type()))
- return false;
- }
- return true;
-}
-
AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
AbstractMetaClass *currentClass)
{
- *constructorAttributes = nullptr;
+ *constructorAttributes = {};
AbstractMetaFunctionList result;
const FunctionList &scopeFunctionList = scopeItem->functions();
result.reserve(scopeFunctionList.size());
@@ -1346,29 +1305,6 @@ AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const Sco
return result;
}
-// For template classes, entries with more specific types may exist from out-of-
-// line definitions. If there is a declaration which matches it after fixing
-// the parameters, remove it as duplicate. For example:
-// template class<T> Vector { public:
-// Vector(const Vector &rhs);
-// };
-// template class<T>
-// Vector<T>::Vector(const Vector<T>&) {} // More specific, remove declaration.
-
-class DuplicatingFunctionPredicate : public std::unary_function<bool, const AbstractMetaFunction *> {
-public:
- explicit DuplicatingFunctionPredicate(const AbstractMetaFunction *f) : m_function(f) {}
-
- bool operator()(const AbstractMetaFunction *rhs) const
- {
- return rhs != m_function && rhs->name() == m_function->name()
- && _compareAbstractMetaFunctions(m_function, rhs);
- }
-
-private:
- const AbstractMetaFunction *m_function;
-};
-
void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
AbstractMetaClass *metaClass)
{
@@ -1377,7 +1313,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
classFunctionList(scopeItem, &constructorAttributes, metaClass);
metaClass->setAttributes(metaClass->attributes() | constructorAttributes);
- for (AbstractMetaFunction *metaFunction : functions){
+ for (AbstractMetaFunction *metaFunction : functions) {
metaFunction->setOriginalAttributes(metaFunction->attributes());
if (metaClass->isNamespace())
*metaFunction += AbstractMetaAttributes::Static;
@@ -1385,21 +1321,23 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
QPropertySpec *read = nullptr;
if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) {
// Property reader must be in the form "<type> name()"
- if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry())
+ if (read->typeEntry() == metaFunction->type()->typeEntry()
&& metaFunction->arguments().isEmpty()) {
*metaFunction += AbstractMetaAttributes::PropertyReader;
metaFunction->setPropertySpec(read);
}
} else if (QPropertySpec *write = metaClass->propertySpecForWrite(metaFunction->name())) {
// Property setter must be in the form "void name(<type>)"
- // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem
- if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) {
+ // Make sure the function was created with all arguments; some argument can be
+ // missing during the parsing because of errors in the typesystem.
+ if (metaFunction->isVoid() && metaFunction->arguments().size() == 1
+ && (write->typeEntry() == metaFunction->arguments().at(0)->type()->typeEntry())) {
*metaFunction += AbstractMetaAttributes::PropertyWriter;
metaFunction->setPropertySpec(write);
}
} else if (QPropertySpec *reset = metaClass->propertySpecForReset(metaFunction->name())) {
// Property resetter must be in the form "void name()"
- if ((!metaFunction->type()) && metaFunction->arguments().isEmpty()) {
+ if (metaFunction->isVoid() && metaFunction->arguments().isEmpty()) {
*metaFunction += AbstractMetaAttributes::PropertyResetter;
metaFunction->setPropertySpec(reset);
}
@@ -1418,13 +1356,6 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
metaClass->setHasNonPrivateConstructor(true);
}
- // Classes with virtual destructors should always have a shell class
- // (since we aren't registering the destructors, we need this extra check)
- if (metaFunction->isDestructor() && metaFunction->isVirtual()
- && metaFunction->visibility() != AbstractMetaAttributes::Private) {
- metaClass->setForceShellClass(true);
- }
-
if (!metaFunction->isDestructor()
&& !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) {
@@ -1500,8 +1431,6 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction
bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
{
- Q_ASSERT(!metaClass->isInterface());
-
if (m_setupInheritanceDone.contains(metaClass))
return true;
@@ -1541,61 +1470,23 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
TypeDatabase* types = TypeDatabase::instance();
- int primary = -1;
- int primaries = 0;
- for (int i = 0; i < baseClasses.size(); ++i) {
-
- if (types->isClassRejected(baseClasses.at(i)))
- continue;
-
- TypeEntry* baseClassEntry = types->findType(baseClasses.at(i));
- if (!baseClassEntry) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("class '%1' inherits from unknown base class '%2'")
- .arg(metaClass->name(), baseClasses.at(i));
- } else if (!baseClassEntry->designatedInterface()) { // true for primary base class
- primaries++;
- primary = i;
- }
- }
-
- if (primary >= 0) {
- AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary));
- if (!baseClass) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("unknown baseclass for '%1': '%2'")
- .arg(metaClass->name(), baseClasses.at(primary));
- return false;
- }
- metaClass->setBaseClass(baseClass);
- }
-
- for (int i = 0; i < baseClasses.size(); ++i) {
- if (types->isClassRejected(baseClasses.at(i)))
- continue;
-
- if (i != primary) {
- AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i));
- if (!baseClass) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i));
+ for (const auto &baseClassName : baseClasses) {
+ if (!types->isClassRejected(baseClassName)) {
+ auto typeEntry = types->findType(baseClassName);
+ if (typeEntry == nullptr || !typeEntry->isComplex()) {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgUnknownBase(metaClass, baseClassName)));
return false;
}
-
- setupInheritance(baseClass);
-
- QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name();
- AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName);
- if (!iface) {
+ auto baseClass = AbstractMetaClass::findClass(m_metaClasses, typeEntry);
+ if (!baseClass) {
qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName);
+ << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClassName);
return false;
}
- metaClass->addInterface(iface);
+ metaClass->addBaseClass(baseClass);
- const AbstractMetaClassList &interfaces = iface->interfaces();
- for (AbstractMetaClass* iface : interfaces)
- metaClass->addInterface(iface);
+ setupInheritance(baseClass);
}
}
@@ -1649,9 +1540,19 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunctionPtr &addedFunc,
AbstractMetaClass *metaClass)
{
- auto *metaFunction = new AbstractMetaFunction(addedFunc);
- metaFunction->setType(translateType(addedFunc->returnType()));
+ QString errorMessage;
+
+ AbstractMetaType *returnType = translateType(addedFunc->returnType(), &errorMessage);
+ if (!returnType) {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgAddedFunctionInvalidReturnType(addedFunc->name(),
+ addedFunc->returnType().name,
+ errorMessage)));
+ return nullptr;
+ }
+ auto metaFunction = new AbstractMetaFunction(addedFunc);
+ metaFunction->setType(returnType);
const auto &args = addedFunc->arguments();
AbstractMetaArgumentList metaArguments;
@@ -1659,11 +1560,12 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
for (int i = 0; i < args.count(); ++i) {
const AddedFunction::TypeInfo& typeInfo = args.at(i).typeInfo;
auto *metaArg = new AbstractMetaArgument;
- AbstractMetaType *type = translateType(typeInfo);
+ AbstractMetaType *type = translateType(typeInfo, &errorMessage);
if (Q_UNLIKELY(!type)) {
- qCWarning(lcShiboken,
- "Unable to translate type \"%s\" of argument %d of added function \"%s\".",
- qPrintable(typeInfo.name), i + 1, qPrintable(addedFunc->name()));
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgAddedFunctionInvalidArgType(addedFunc->name(),
+ typeInfo.name, i + 1,
+ errorMessage)));
delete metaFunction;
return nullptr;
}
@@ -1726,7 +1628,12 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction);
}
} else {
- metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction);
+ auto type = AbstractMetaFunction::NormalFunction;
+ if (metaFunction->name() == QLatin1String("__getattro__"))
+ type = AbstractMetaFunction::GetAttroFunction;
+ else if (metaFunction->name() == QLatin1String("__setattro__"))
+ type = AbstractMetaFunction::SetAttroFunction;
+ metaFunction->setFunctionType(type);
}
metaFunction->setDeclaringClass(metaClass);
@@ -1858,11 +1765,14 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
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)
+
+ if (rejected) {
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
+ qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).",
+ qPrintable(className), qPrintable(signature), qPrintable(rejectReason));
+ }
return nullptr;
+ }
if (functionItem->isFriend())
return nullptr;
@@ -1875,6 +1785,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
auto *metaFunction = new AbstractMetaFunction;
+ metaFunction->setSourceLocation(functionItem->sourceLocation());
if (deprecated)
*metaFunction += AbstractMetaAttributes::Deprecated;
@@ -1883,9 +1794,6 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
metaFunction->setConstant(functionItem->isConstant());
metaFunction->setExceptionSpecification(functionItem->exceptionSpecification());
- if (ReportHandler::isDebug(ReportHandler::MediumDebug))
- qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()";
-
metaFunction->setName(functionName);
metaFunction->setOriginalName(functionItem->name());
@@ -1921,10 +1829,12 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
QString errorMessage;
switch (metaFunction->functionType()) {
case AbstractMetaFunction::DestructorFunction:
+ metaFunction->setType(AbstractMetaType::createVoid());
break;
case AbstractMetaFunction::ConstructorFunction:
metaFunction->setExplicit(functionItem->isExplicit());
metaFunction->setName(currentClass->name());
+ metaFunction->setType(AbstractMetaType::createVoid());
break;
default: {
TypeInfo returnType = functionItem->type();
@@ -1935,17 +1845,14 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
return nullptr;
}
- AbstractMetaType *type = nullptr;
- if (!returnType.isVoid()) {
- type = translateType(returnType, currentClass, {}, &errorMessage);
- if (!type) {
- const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
- qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
- delete metaFunction;
- return nullptr;
- }
+ AbstractMetaType *type = translateType(returnType, currentClass, {}, &errorMessage);
+ if (!type) {
+ const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
+ delete metaFunction;
+ return nullptr;
}
metaFunction->setType(type);
@@ -1976,16 +1883,12 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
AbstractMetaType *metaType = translateType(arg->type(), currentClass, {}, &errorMessage);
if (!metaType) {
// If an invalid argument has a default value, simply remove it
- if (arg->defaultValue()) {
- if (!currentClass
- || (currentClass->typeEntry()->codeGeneration()
- & TypeEntry::GenerateTargetLang)) {
- qCWarning(lcShiboken).noquote().nospace()
- << "Stripping argument #" << (i + 1) << " of "
- << originalQualifiedSignatureWithReturn
- << " due to unmatched type \"" << arg->type().toString()
- << "\" with default expression \""
- << arg->defaultValueExpression() << "\".";
+ // unless the function is virtual (since the override in the
+ // wrapper can then not correctly be generated).
+ if (arg->defaultValue() && !functionItem->isVirtual()) {
+ if (!currentClass || currentClass->typeEntry()->generateCode()) {
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
}
break;
}
@@ -2049,8 +1952,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
fixArgumentNames(metaFunction, functionMods);
QString errorMessage;
if (!applyArrayArgumentModifications(functionMods, metaFunction, &errorMessage)) {
- qCWarning(lcShiboken, "While traversing %s: %s",
- qPrintable(className), qPrintable(errorMessage));
+ qCWarning(lcShiboken, "%s",
+ qPrintable(msgArrayModificationFailed(functionItem, className, errorMessage)));
}
}
@@ -2077,31 +1980,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
return metaFunction;
}
-AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction::TypeInfo &typeInfo)
+AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction::TypeInfo &typeInfo,
+ QString *errorMessage)
{
Q_ASSERT(!typeInfo.name.isEmpty());
TypeDatabase* typeDb = TypeDatabase::instance();
- TypeEntry* type;
QString typeName = typeInfo.name;
if (typeName == QLatin1String("void"))
- return nullptr;
+ return AbstractMetaType::createVoid();
- type = typeDb->findType(typeName);
+ TypeEntry *type = typeDb->findType(typeName);
+ if (!type)
+ type = typeDb->findFlagsType(typeName);
// test if the type is a template, like a container
bool isTemplate = false;
QStringList templateArgs;
if (!type && typeInfo.name.contains(QLatin1Char('<'))) {
- const QStringList& parsedType = parseTemplateType(typeInfo.name);
+ QStringList parsedType = parseTemplateType(typeInfo.name);
if (parsedType.isEmpty()) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Template type parsing failed for '%1'").arg(typeInfo.name);
- } else {
- templateArgs = parsedType.mid(1);
- isTemplate = (type = typeDb->findContainerType(parsedType[0]));
+ *errorMessage = QStringLiteral("Template type parsing failed for '%1'").arg(typeInfo.name);
+ return nullptr;
+ }
+ const QString name = parsedType.takeFirst();
+ templateArgs = parsedType;
+ type = typeDb->findContainerType(name);
+ if (!type) { // A template typedef?
+ if (auto candidate = typeDb->findType(name)) {
+ if (candidate->type() == TypeEntry::ObjectType || candidate->type() == TypeEntry::BasicValueType)
+ type = candidate;
+ }
}
+ isTemplate = type != nullptr;
}
if (!type) {
@@ -2112,34 +2024,36 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction:
if (it.key().endsWith(colonColon() + typeName))
candidates.append(it.key());
}
-
- QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName);
+ QTextStream str(errorMessage);
+ str << "Type '" << typeName << "' wasn't found in the type database.\n";
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');
+ str << "Declare it in the type system using the proper <*-type> tag.";
+ } else {
+ str << "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))
+ str << " " << candidate << '\n';
}
- qFatal("%s", qPrintable(msg));
+ return nullptr;
}
- auto *metaType = new AbstractMetaType;
- metaType->setTypeEntry(type);
+ // These are only implicit and should not appear in code...
+ auto *metaType = new AbstractMetaType(type);
metaType->setIndirections(typeInfo.indirections);
if (typeInfo.isReference)
metaType->setReferenceType(LValueReference);
metaType->setConstant(typeInfo.isConstant);
if (isTemplate) {
for (const QString& templateArg : qAsConst(templateArgs)) {
- AbstractMetaType *metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg));
+ AbstractMetaType *metaArgType = translateType(AddedFunction::TypeInfo::fromSignature(templateArg), errorMessage);
+ if (!metaArgType)
+ return nullptr;
metaType->addInstantiation(metaArgType);
}
metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
+ } else {
+ metaType->decideUsagePattern();
}
return metaType;
@@ -2156,6 +2070,66 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC
return type;
}
+// Helper for translateTypeStatic()
+TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
+ const QString &name,
+ AbstractMetaClass *currentClass,
+ AbstractMetaBuilderPrivate *d)
+{
+ // 5.1 - Try first using the current scope
+ if (currentClass) {
+ if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName))
+ return {type};
+
+ // 5.1.1 - Try using the class parents' scopes
+ if (d && !currentClass->baseClassNames().isEmpty()) {
+ const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
+ for (const AbstractMetaClass *cls : baseClasses) {
+ if (auto type = findTypeEntryUsingContext(cls, qualifiedName))
+ return {type};
+ }
+ }
+ }
+
+ // 5.2 - Try without scope
+ auto types = TypeDatabase::instance()->findCppTypes(qualifiedName);
+ if (!types.isEmpty())
+ return types;
+
+ // 6. No? Try looking it up as a flags type
+ if (auto type = TypeDatabase::instance()->findFlagsType(qualifiedName))
+ return {type};
+
+ // 7. No? Try looking it up as a container type
+ if (auto type = TypeDatabase::instance()->findContainerType(name))
+ return {type};
+
+ // 8. No? Check if the current class is a template and this type is one
+ // of the parameters.
+ if (currentClass) {
+ const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
+ for (TypeEntry *te : template_args) {
+ if (te->name() == qualifiedName)
+ return {te};
+ }
+ }
+ return {};
+}
+
+// Reverse lookup of AbstractMetaType representing a template specialization
+// found during traversing function arguments to its type system typedef'ed
+// class.
+const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType *t) const
+{
+ if (t->hasInstantiations()) {
+ auto pred = [t](const TypeClassEntry &e) { return e.type->compare(*t); };
+ auto it = std::find_if(m_typeSystemTypeDefs.cbegin(), m_typeSystemTypeDefs.cend(), pred);
+ if (it != m_typeSystemTypeDefs.cend())
+ return it->klass;
+ }
+ return nullptr;
+}
+
AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
AbstractMetaClass *currentClass,
TranslateTypeFlags flags,
@@ -2164,12 +2138,21 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return translateTypeStatic(_typei, currentClass, this, flags, errorMessage);
}
+static bool isNumber(const QString &s)
+{
+ return std::all_of(s.cbegin(), s.cend(),
+ [](QChar c) { return c.isDigit(); });
+}
+
AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
AbstractMetaClass *currentClass,
AbstractMetaBuilderPrivate *d,
TranslateTypeFlags flags,
QString *errorMessageIn)
{
+ if (_typei.isVoid())
+ return AbstractMetaType::createVoid();
+
// 1. Test the type info without resolving typedefs in case this is present in the
// type system
const bool resolveType = !flags.testFlag(AbstractMetaBuilder::DontResolveType);
@@ -2258,7 +2241,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo
if (_ok)
arrayType->setArrayElementCount(int(elems));
}
- arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version()));
+ auto elementTypeEntry = elementType->typeEntry();
+ arrayType->setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(),
+ elementTypeEntry->parent()));
arrayType->decideUsagePattern();
elementType = arrayType;
@@ -2286,47 +2271,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo
typeInfo.clearInstantiations();
}
- const TypeEntry *type = nullptr;
- // 5. Try to find the type
-
- // 5.1 - Try first using the current scope
- if (currentClass) {
- type = findTypeEntryUsingContext(currentClass, qualifiedName);
-
- // 5.1.1 - Try using the class parents' scopes
- if (!type && d && !currentClass->baseClassNames().isEmpty()) {
- const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
- for (const AbstractMetaClass *cls : baseClasses) {
- type = findTypeEntryUsingContext(cls, qualifiedName);
- if (type)
- break;
- }
- }
- }
-
- // 5.2 - Try without scope
- if (!type)
- type = TypeDatabase::instance()->findType(qualifiedName);
-
- // 6. No? Try looking it up as a flags type
- if (!type)
- type = TypeDatabase::instance()->findFlagsType(qualifiedName);
-
- // 7. No? Try looking it up as a container type
- if (!type)
- type = TypeDatabase::instance()->findContainerType(name);
-
- // 8. No? Check if the current class is a template and this type is one
- // of the parameters.
- if (!type && currentClass) {
- const QVector<TypeEntry *> &template_args = currentClass->templateArguments();
- for (TypeEntry *te : template_args) {
- if (te->name() == qualifiedName)
- type = te;
- }
- }
-
- if (!type) {
+ const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d);
+ if (types.isEmpty()) {
if (errorMessageIn) {
*errorMessageIn =
msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName));
@@ -2334,11 +2280,10 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo
return nullptr;
}
- // These are only implicit and should not appear in code...
- Q_ASSERT(!type->isInterface());
+ const TypeEntry *type = types.constFirst();
+ const TypeEntry::Type typeEntryType = type->type();
- auto *metaType = new AbstractMetaType;
- metaType->setTypeEntry(type);
+ QScopedPointer<AbstractMetaType> metaType(new AbstractMetaType);
metaType->setIndirectionsV(typeInfo.indirectionsV());
metaType->setReferenceType(typeInfo.referenceType());
metaType->setConstant(typeInfo.isConstant());
@@ -2349,23 +2294,88 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo
for (int t = 0, size = templateArguments.size(); t < size; ++t) {
const TypeInfo &ti = templateArguments.at(t);
AbstractMetaType *targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
+ // For non-type template parameters, create a dummy type entry on the fly
+ // as is done for classes.
+ if (!targType) {
+ const QString value = ti.qualifiedName().join(colonColon());
+ if (isNumber(value)) {
+ TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry());
+ targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
+ }
+ }
if (!targType) {
if (errorMessageIn)
*errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage);
- delete metaType;
return nullptr;
}
metaType->addInstantiation(targType, true);
}
+ if (types.size() > 1) {
+ const bool sameType = std::all_of(types.cbegin() + 1, types.cend(),
+ [typeEntryType](const TypeEntry *e) {
+ return e->type() == typeEntryType; });
+ if (!sameType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgAmbiguousVaryingTypesFound(qualifiedName, types);
+ return nullptr;
+ }
+ // Ambiguous primitive/smart pointer types are possible (when
+ // including type systems).
+ if (typeEntryType != TypeEntry::PrimitiveType
+ && typeEntryType != TypeEntry::SmartPointerType) {
+ if (errorMessageIn)
+ *errorMessageIn = msgAmbiguousTypesFound(qualifiedName, types);
+ return nullptr;
+ }
+ }
+
+ if (typeEntryType == TypeEntry::SmartPointerType) {
+ // Find a matching instantiation
+ if (metaType->instantiations().size() != 1) {
+ if (errorMessageIn)
+ *errorMessageIn = msgInvalidSmartPointerType(_typei);
+ return nullptr;
+ }
+ auto instantiationType = metaType->instantiations().constFirst()->typeEntry();
+ if (instantiationType->type() == TypeEntry::TemplateArgumentType) {
+ // Member functions of the template itself, SharedPtr(const SharedPtr &)
+ type = instantiationType;
+ } else {
+ auto it = std::find_if(types.cbegin(), types.cend(),
+ [instantiationType](const TypeEntry *e) {
+ auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e);
+ return smartPtr->matchesInstantiation(instantiationType);
+ });
+ if (it == types.cend()) {
+ if (errorMessageIn)
+ *errorMessageIn = msgCannotFindSmartPointerInstantion(_typei);
+ return nullptr;
+ }
+ type =*it;
+ }
+ }
+
+ metaType->setTypeEntry(type);
+
// The usage pattern *must* be decided *after* the possible template
// instantiations have been determined, or else the absence of
// such instantiations will break the caching scheme of
// AbstractMetaType::cppSignature().
metaType->decideUsagePattern();
- return metaType;
+ if (d) {
+ // Reverse lookup of type system typedefs. Replace by class.
+ if (auto klass = d->resolveTypeSystemTypeDef(metaType.data())) {
+ metaType.reset(new AbstractMetaType);
+ metaType->setTypeEntry(klass->typeEntry());
+ metaType->decideUsagePattern();
+ }
+ }
+
+ Q_ASSERT(metaType->typeUsagePattern() != AbstractMetaType::InvalidPattern);
+ return metaType.take();
}
AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei,
@@ -2655,18 +2665,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
const TypeInfo &info)
{
QVector<TypeInfo> targs = info.instantiations();
- QVector<AbstractMetaType *> templateTypes;
- QString errorMessage;
-
- if (subclass->isTypeDef()) {
- subclass->setHasCloneOperator(templateClass->hasCloneOperator());
- subclass->setHasEqualsOperator(templateClass->hasEqualsOperator());
- subclass->setHasHashFunction(templateClass->hasHashFunction());
- subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor());
- subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor());
- subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor());
- subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor());
- }
+ AbstractMetaTypeList templateTypes;
for (const TypeInfo &i : qAsConst(targs)) {
QString typeName = i.qualifiedName().join(colonColon());
@@ -2676,15 +2675,11 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
// "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) {
+ if (isNumber(typeName)) {
t = typeDb->findType(typeName);
if (!t) {
- t = new EnumValueTypeEntry(typeName, typeName, nullptr,
- QVersionNumber(0, 0));
- t->setCodeGeneration(0);
- typeDb->addType(t);
+ auto parent = subclass->typeEntry()->typeSystemTypeEntry();
+ t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
}
} else {
QStringList possibleNames;
@@ -2702,8 +2697,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
}
if (t) {
- auto *temporaryType = new AbstractMetaType;
- temporaryType->setTypeEntry(t);
+ auto *temporaryType = new AbstractMetaType(t);
temporaryType->setConstant(i.isConstant());
temporaryType->setReferenceType(i.referenceType());
temporaryType->setIndirectionsV(i.indirectionsV());
@@ -2716,6 +2710,28 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
}
}
+ subclass->setTemplateBaseClass(templateClass);
+ subclass->setTemplateBaseClassInstantiations(templateTypes);
+ subclass->setBaseClass(templateClass->baseClass());
+ return true;
+}
+
+void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *subclass)
+{
+ QString errorMessage;
+ auto templateClass = subclass->templateBaseClass();
+
+ if (subclass->isTypeDef()) {
+ subclass->setHasCloneOperator(templateClass->hasCloneOperator());
+ subclass->setHasEqualsOperator(templateClass->hasEqualsOperator());
+ subclass->setHasHashFunction(templateClass->hasHashFunction());
+ subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor());
+ subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor());
+ subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor());
+ subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor());
+ }
+
+ const auto &templateTypes = subclass->templateBaseClassInstantiations();
const AbstractMetaFunctionList &subclassFuncs = subclass->functions();
const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions();
for (const AbstractMetaFunction *function : templateClassFunctions) {
@@ -2729,7 +2745,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
QScopedPointer<AbstractMetaFunction> f(function->copy());
f->setArguments(AbstractMetaArgumentList());
- if (function->type()) { // Non-void
+ if (!function->isVoid()) {
AbstractMetaType *returnType = inheritTemplateType(templateTypes, function->type());
if (!returnType)
continue;
@@ -2818,59 +2834,44 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
f->replaceType(fieldType);
subclass->addField(f.take());
}
-
- subclass->setTemplateBaseClass(templateClass);
- subclass->setTemplateBaseClassInstantiations(templateTypes);
- subclass->setInterfaces(templateClass->interfaces());
- subclass->setBaseClass(templateClass->baseClass());
-
- return true;
}
-void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass,
- const QStringList &declarations)
+void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
+ const QStringList &declarations)
{
const QStringList scopes = currentScope()->qualifiedName();
-
- for (int i = 0; i < declarations.size(); ++i) {
- const auto propertyTokens = declarations.at(i).splitRef(QLatin1Char(' '));
-
- AbstractMetaType *type = nullptr;
- for (int j = scopes.size(); j >= 0; --j) {
- QStringList qualifiedName = scopes.mid(0, j);
- qualifiedName.append(propertyTokens.at(0).toString());
- TypeInfo info;
- info.setQualifiedName(qualifiedName);
-
- type = translateType(info, metaClass);
- if (type)
- break;
- }
-
- if (!type) {
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("Unable to decide type of property: '%1' in class '%2'")
- .arg(propertyTokens.at(0).toString(), metaClass->name());
- continue;
+ QString errorMessage;
+ int i = 0;
+ for (; i < declarations.size(); ++i) {
+ if (auto spec = QPropertySpec::parseQ_Property(this, metaClass, declarations.at(i), scopes, &errorMessage)) {
+ spec->setIndex(i);
+ metaClass->addPropertySpec(spec);
+ } else {
+ QString message;
+ QTextStream str(&message);
+ str << metaClass->sourceLocation() << errorMessage;
+ qCWarning(lcShiboken, "%s", qPrintable(message));
}
+ }
- auto *spec = new QPropertySpec(type->typeEntry());
- spec->setName(propertyTokens.at(1).toString());
- spec->setIndex(i);
+ // User-added properties
+ auto typeEntry = metaClass->typeEntry();
+ for (const TypeSystemProperty &tp : typeEntry->properties()) {
+ QPropertySpec *spec = nullptr;
+ if (metaClass->propertySpecByName(tp.name))
+ errorMessage = msgPropertyExists(metaClass->name(), tp.name);
+ else
+ spec = QPropertySpec::fromTypeSystemProperty(this, metaClass, tp, scopes, &errorMessage);
- for (int pos = 2; pos + 1 < propertyTokens.size(); pos += 2) {
- if (propertyTokens.at(pos) == QLatin1String("READ"))
- spec->setRead(propertyTokens.at(pos + 1).toString());
- else if (propertyTokens.at(pos) == QLatin1String("WRITE"))
- spec->setWrite(propertyTokens.at(pos + 1).toString());
- else if (propertyTokens.at(pos) == QLatin1String("DESIGNABLE"))
- spec->setDesignable(propertyTokens.at(pos + 1).toString());
- else if (propertyTokens.at(pos) == QLatin1String("RESET"))
- spec->setReset(propertyTokens.at(pos + 1).toString());
+ if (spec) {
+ spec->setIndex(i++);
+ metaClass->addPropertySpec(spec);
+ } else {
+ QString message;
+ QTextStream str(&message);
+ str << typeEntry->sourceLocation() << errorMessage;
+ qCWarning(lcShiboken, "%s", qPrintable(message));
}
-
- metaClass->addPropertySpec(spec);
- delete type;
}
}
@@ -2899,11 +2900,9 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls)
QQueue<AbstractMetaClass*> baseClasses;
if (cls->baseClass())
baseClasses.enqueue(cls->baseClass());
- baseClasses << cls->interfaces().toList();
while (!baseClasses.isEmpty()) {
AbstractMetaClass* currentClass = baseClasses.dequeue();
- baseClasses << currentClass->interfaces().toList();
if (currentClass->baseClass())
baseClasses.enqueue(currentClass->baseClass());
@@ -2948,7 +2947,7 @@ static void writeRejectLogFile(const QString &name,
for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) {
- s << QString(72, QLatin1Char('*')) << endl;
+ s << QString(72, QLatin1Char('*')) << Qt::endl;
switch (reason) {
case AbstractMetaBuilder::NotInTypeSystem:
s << "Not in type system";
@@ -2981,16 +2980,16 @@ static void writeRejectLogFile(const QString &name,
break;
}
- s << endl;
+ s << Qt::endl;
for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
it != rejects.constEnd(); ++it) {
if (it.value() != reason)
continue;
- s << " - " << it.key() << endl;
+ s << " - " << it.key() << Qt::endl;
}
- s << QString(72, QLatin1Char('*')) << endl << endl;
+ s << QString(72, QLatin1Char('*')) << Qt::endl << Qt::endl;
}
}
@@ -3016,6 +3015,19 @@ static ClassIndexHash::ConstIterator findByTypeEntry(const ClassIndexHash &map,
return it;
}
+// Add a dependency of the class associated with typeEntry on clazz
+static void addClassDependency(const TypeEntry *typeEntry,
+ const AbstractMetaClass *clazz,
+ int classIndex, const ClassIndexHash &map,
+ Graph *graph)
+{
+ if (typeEntry->isComplex() && typeEntry != clazz->typeEntry()) {
+ const auto it = findByTypeEntry(map, typeEntry);
+ if (it != map.cend() && it.key()->enclosingClass() != clazz)
+ graph->addEdge(it.value(), classIndex);
+ }
+}
+
AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassList &classList,
const Dependencies &additionalDependencies) const
{
@@ -3055,10 +3067,6 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const
const AbstractMetaClassList &bases = getBaseClasses(clazz);
for (AbstractMetaClass *baseClass : bases) {
- // Fix polymorphic expression
- if (clazz->baseClass() == baseClass)
- clazz->setBaseClass(baseClass);
-
const auto baseIt = map.constFind(baseClass);
if (baseIt!= map.cend())
graph.addEdge(baseIt.value(), classIndex);
@@ -3072,15 +3080,17 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const
// ("QString s = QString()"), add a dependency.
if (!arg->originalDefaultValueExpression().isEmpty()
&& arg->type()->isValue()) {
- auto typeEntry = arg->type()->typeEntry();
- if (typeEntry->isComplex() && typeEntry != clazz->typeEntry()) {
- auto ait = findByTypeEntry(map, typeEntry);
- if (ait != map.cend() && ait.key()->enclosingClass() != clazz)
- graph.addEdge(ait.value(), classIndex);
- }
+ addClassDependency(arg->type()->typeEntry(), clazz, classIndex,
+ map, &graph);
}
}
}
+ // Member fields need to be initialized
+ const AbstractMetaFieldList &fields = clazz->fields();
+ for (AbstractMetaField *field : fields) {
+ addClassDependency(field->type()->typeEntry(), clazz, classIndex,
+ map, &graph);
+ }
}
AbstractMetaClassList result;
@@ -3099,8 +3109,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const
} else {
for (int i : qAsConst(unmappedResult)) {
Q_ASSERT(reverseMap.contains(i));
- if (!reverseMap[i]->isInterface())
- result << reverseMap[i];
+ result << reverseMap[i];
}
}
@@ -3151,9 +3160,9 @@ AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractM
return ret;
}
-void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader)
+void AbstractMetaBuilder::setGlobalHeaders(const QFileInfoList &globalHeaders)
{
- d->m_globalHeader = QFileInfo(globalHeader);
+ d->m_globalHeaders = globalHeaders;
}
void AbstractMetaBuilder::setHeaderPaths(const HeaderPaths &hp)
@@ -3191,23 +3200,26 @@ static bool matchHeader(const QString &headerPath, const QString &fileName)
&& fileName.startsWith(headerPath, caseSensitivity);
}
-void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const
+void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &path) const
{
- auto it = m_resolveIncludeHash.find(fileName);
+ auto it = m_resolveIncludeHash.find(path);
if (it == m_resolveIncludeHash.end()) {
- QFileInfo info(fileName);
- if (m_globalHeader.fileName() == info.fileName())
+ QFileInfo info(path);
+ const QString fileName = info.fileName();
+ if (std::any_of(m_globalHeaders.cbegin(), m_globalHeaders.cend(),
+ [fileName] (const QFileInfo &fi) {
+ return fi.fileName() == fileName; })) {
return;
+ }
int bestMatchLength = 0;
for (const auto &headerPath : m_headerPaths) {
- if (headerPath.size() > bestMatchLength && matchHeader(headerPath, fileName))
+ if (headerPath.size() > bestMatchLength && matchHeader(headerPath, path))
bestMatchLength = headerPath.size();
}
const QString include = bestMatchLength > 0
- ? fileName.right(fileName.size() - bestMatchLength - 1)
- : info.fileName();
- it = m_resolveIncludeHash.insert(fileName, {Include::IncludePath, include});
+ ? path.right(path.size() - bestMatchLength - 1) : fileName;
+ it = m_resolveIncludeHash.insert(path, {Include::IncludePath, include});
}
te->setInclude(it.value());
}
@@ -3232,7 +3244,7 @@ static void debugFormatSequence(QDebug &d, const char *key, const Container& c,
void AbstractMetaBuilder::formatDebug(QDebug &debug) const
{
- debug << "m_globalHeader=" << d->m_globalHeader.absoluteFilePath();
+ debug << "m_globalHeader=" << d->m_globalHeaders;
debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n");
debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n");
if (const int scopeCount = d->m_scopes.size()) {