aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp697
1 files changed, 384 insertions, 313 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index dd71b4fa7..f07fb96c6 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -57,7 +57,7 @@ using namespace Qt::StringLiterals;
static QString stripTemplateArgs(const QString &name)
{
- int pos = name.indexOf(u'<');
+ const auto pos = name.indexOf(u'<');
return pos < 0 ? name : name.left(pos);
}
@@ -67,6 +67,31 @@ static void fixArgumentIndexes(AbstractMetaArgumentList *list)
(*list)[i].setArgumentIndex(i);
}
+bool operator<(const RejectEntry &re1, const RejectEntry &re2)
+{
+ return re1.reason != re2.reason
+ ? (re1.reason < re2.reason) : (re1.sortkey < re2.sortkey);
+}
+
+QTextStream &operator<<(QTextStream &str, const RejectEntry &re)
+{
+ str << re.signature;
+ if (!re.message.isEmpty())
+ str << ": " << re.message;
+ return str;
+}
+
+static void applyCachedFunctionModifications(const AbstractMetaFunctionPtr &metaFunction,
+ const FunctionModificationList &functionMods)
+{
+ for (const FunctionModification &mod : functionMods) {
+ if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
+ metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
+ if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
+ metaFunction->setAllowThreadModification(mod.allowThread());
+ }
+}
+
bool AbstractMetaBuilderPrivate::m_useGlobalHeader = false;
bool AbstractMetaBuilderPrivate::m_codeModelTestMode = false;
@@ -136,7 +161,12 @@ const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEn
return d->m_enums;
}
-void AbstractMetaBuilderPrivate::checkFunctionModifications()
+const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() const
+{
+ return d->m_typedefTargetToName;
+}
+
+void AbstractMetaBuilderPrivate::checkFunctionModifications() const
{
const auto &entries = TypeDatabase::instance()->entries();
@@ -220,7 +250,7 @@ void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &f
void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceModelItem &nsItem)
{
- const FunctionList &streamOps = nsItem->findFunctions(u"operator<<"_s);
+ const FunctionList &streamOps = nsItem->findFunctions("operator<<");
for (const FunctionModelItem &item : streamOps)
registerToStringCapability(item, nullptr);
for (const NamespaceModelItem &ni : nsItem->namespaces())
@@ -276,15 +306,18 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
firstArgumentIsSelf = false;
}
}
- if (!baseoperandClass)
+ if (!baseoperandClass) {
+ rejectFunction(item, currentClass, AbstractMetaBuilder::UnmatchedOperator,
+ u"base operand class not found."_s);
return;
+ }
if (item->isSpaceshipOperator() && !item->isDeleted()) {
AbstractMetaClass::addSynthesizedComparisonOperators(baseoperandClass);
return;
}
- AbstractMetaFunction *metaFunction = traverseFunction(item, baseoperandClass);
+ auto metaFunction = traverseFunction(item, baseoperandClass);
if (metaFunction == nullptr)
return;
@@ -317,7 +350,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
}
metaFunction->setFlags(flags);
metaFunction->setAccess(Access::Public);
- AbstractMetaClass::addFunction(baseoperandClass, AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(baseoperandClass, metaFunction);
if (!metaFunction->arguments().isEmpty()) {
const auto include = metaFunction->arguments().constFirst().type().typeEntry()->include();
baseoperandClass->typeEntry()->addArgumentInclude(include);
@@ -338,7 +371,7 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
if (streamedClass == nullptr)
return false;
- AbstractMetaFunction *streamFunction = traverseFunction(item, streamedClass);
+ auto streamFunction = traverseFunction(item, streamedClass);
if (!streamFunction)
return false;
@@ -353,7 +386,6 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
streamFunction->setArguments(arguments);
- *streamFunction += AbstractMetaFunction::FinalInTargetLang;
streamFunction->setAccess(Access::Public);
AbstractMetaClassPtr funcClass;
@@ -369,7 +401,7 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
funcClass = streamClass;
}
- AbstractMetaClass::addFunction(funcClass, AbstractMetaFunctionCPtr(streamFunction));
+ AbstractMetaClass::addFunction(funcClass, streamFunction);
auto funcTe = funcClass->typeEntry();
if (funcClass == streamClass)
funcTe->addArgumentInclude(streamedClass->typeEntry()->include());
@@ -394,8 +426,8 @@ void AbstractMetaBuilderPrivate::sortLists()
// this is a temporary solution before new type revision implementation
// We need move QMetaObject register before QObject.
Dependencies additionalDependencies;
- if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QObject")) {
- if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, u"QMetaObject")) {
+ if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QObject")) {
+ if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QMetaObject")) {
Dependency dependency;
dependency.parent = qMetaObjectClass;
dependency.child = qObjectClass;
@@ -421,7 +453,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
unsigned clangFlags)
{
clang::Builder builder;
- builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes());
+ builder.setForceProcessSystemIncludes(TypeDatabase::instance()->forceProcessSystemIncludes());
if (addCompilerSupportArguments) {
if (level == LanguageLevel::Default)
level = clang::emulatedCompilerLanguageLevel();
@@ -429,7 +461,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
+ clang::languageLevelOption(level));
}
FileModelItem result = clang::parse(arguments, addCompilerSupportArguments,
- clangFlags, builder)
+ level, clangFlags, builder)
? builder.dom() : FileModelItem();
const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics();
if (const auto diagnosticsCount = diagnostics.size()) {
@@ -448,7 +480,7 @@ static QStringList functionCandidates(const AbstractMetaFunctionCList &list,
const QString &signature)
{
QString name = signature;
- const int parenPos = name.indexOf(u'(');
+ const auto parenPos = name.indexOf(u'(');
if (parenPos > 0)
name.truncate(parenPos);
QStringList result;
@@ -469,8 +501,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
// Start the generation...
const ClassList &typeValues = dom->classes();
- ReportHandler::startProgress("Generating class model ("
- + QByteArray::number(typeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated class model ("
+ + QByteArray::number(typeValues.size()) + ").");
for (const ClassModelItem &item : typeValues) {
if (const auto cls = traverseClass(dom, item, nullptr))
addAbstractMetaClass(cls, item.get());
@@ -479,8 +511,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
// We need to know all global enums
const EnumList &enums = dom->enums();
- ReportHandler::startProgress("Generating enum model ("
- + QByteArray::number(enums.size()) + ")...");
+ ReportHandler::startProgress("Generated enum model ("
+ + QByteArray::number(enums.size()) + ").");
for (const EnumModelItem &item : enums) {
auto metaEnum = traverseEnum(item, nullptr, QSet<QString>());
if (metaEnum.has_value()) {
@@ -490,16 +522,16 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
const auto &namespaceTypeValues = dom->namespaces();
- ReportHandler::startProgress("Generating namespace model ("
- + QByteArray::number(namespaceTypeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated namespace model ("
+ + QByteArray::number(namespaceTypeValues.size()) + ").");
for (const NamespaceModelItem &item : namespaceTypeValues)
traverseNamespace(dom, item);
// Go through all typedefs to see if we have defined any
// specific typedefs to be used as classes.
const TypeDefList typeDefs = dom->typeDefs();
- ReportHandler::startProgress("Resolving typedefs ("
- + QByteArray::number(typeDefs.size()) + ")...");
+ ReportHandler::startProgress("Resolved typedefs ("
+ + QByteArray::number(typeDefs.size()) + ").");
for (const TypeDefModelItem &typeDef : typeDefs) {
if (const auto cls = traverseTypeDef(dom, typeDef, nullptr))
addAbstractMetaClass(cls, typeDef.get());
@@ -523,24 +555,23 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
if (!funcEntry || !funcEntry->generateCode())
continue;
- AbstractMetaFunction *metaFunc = traverseFunction(func, nullptr);
- if (!metaFunc)
+ auto metaFuncPtr = traverseFunction(func, nullptr);
+ if (!metaFuncPtr)
continue;
- AbstractMetaFunctionCPtr metaFuncPtr(metaFunc);
- if (!funcEntry->hasSignature(metaFunc->minimalSignature()))
+ if (!funcEntry->hasSignature(metaFuncPtr->minimalSignature()))
continue;
- metaFunc->setTypeEntry(funcEntry);
- applyFunctionModifications(metaFunc);
- metaFunc->applyTypeModifications();
+ metaFuncPtr->setTypeEntry(funcEntry);
+ applyFunctionModifications(metaFuncPtr);
+ metaFuncPtr->applyTypeModifications();
setInclude(funcEntry, func->fileName());
m_globalFunctions << metaFuncPtr;
}
- ReportHandler::startProgress("Fixing class inheritance...");
+ ReportHandler::startProgress("Fixed class inheritance.");
for (const auto &cls : std::as_const(m_metaClasses)) {
if (cls->needsInheritanceSetup()) {
setupInheritance(cls);
@@ -553,7 +584,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
}
- ReportHandler::startProgress("Detecting inconsistencies in class model...");
+ ReportHandler::startProgress("Checked for inconsistencies in class model.");
for (const auto &cls : std::as_const(m_metaClasses)) {
AbstractMetaClass::fixFunctions(cls);
@@ -571,10 +602,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
const auto &allEntries = types->entries();
- ReportHandler::startProgress("Detecting inconsistencies in typesystem ("
- + QByteArray::number(allEntries.size()) + ")...");
+ ReportHandler::startProgress("Checked for inconsistencies in typesystem ("
+ + QByteArray::number(allEntries.size()) + ").");
for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
- TypeEntryPtr entry = it.value();
+ const TypeEntryPtr &entry = it.value();
if (!entry->isPrimitive()) {
if ((entry->isValue() || entry->isObject())
&& !types->shouldDropTypeEntry(entry->qualifiedCppName())
@@ -621,7 +652,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
{
- const FunctionList &hashFunctions = dom->findFunctions(u"qHash"_s);
+ const FunctionList &hashFunctions = dom->findFunctions("qHash");
for (const FunctionModelItem &item : hashFunctions)
registerHashFunction(item, nullptr);
}
@@ -644,11 +675,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
}
}
- ReportHandler::startProgress("Checking inconsistencies in function modifications...");
+ ReportHandler::startProgress("Checked for inconsistencies in function modifications.");
checkFunctionModifications();
- ReportHandler::startProgress("Writing log files...");
+ ReportHandler::startProgress("Wrote log files.");
for (const auto &cls : std::as_const(m_metaClasses)) {
// setupEquals(cls);
@@ -734,14 +765,17 @@ AbstractMetaClassPtr
namespaceName.append(namespaceItem->name());
if (TypeDatabase::instance()->isClassRejected(namespaceName)) {
- m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled);
- return nullptr;
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, QString{}});
+ return {};
}
auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName());
if (!type) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName)));
+ const QString rejectReason = msgNamespaceNoTypeEntry(namespaceItem, namespaceName);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, rejectReason});
return nullptr;
}
@@ -852,31 +886,35 @@ std::optional<AbstractMetaEnum>
if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
if (typeEntry)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
- m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ m_rejectedEnums.insert({AbstractMetaBuilder::GenerationDisabled, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode();
if (!typeEntry) {
+ const QString rejectReason = msgNoEnumTypeEntry(enumItem, className);
if (rejectionWarning)
- qCWarning(lcShiboken, "%s", qPrintable(msgNoEnumTypeEntry(enumItem, className)));
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
if (!typeEntry->isEnum()) {
- if (rejectionWarning) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNoEnumTypeConflict(enumItem, className, typeEntry)));
- }
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ const QString rejectReason = msgNoEnumTypeConflict(enumItem, className, typeEntry);
+ if (rejectionWarning)
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
AbstractMetaEnum metaEnum;
metaEnum.setEnumKind(enumItem->enumKind());
metaEnum.setDeprecated(enumItem->isDeprecated());
+ metaEnum.setUnderlyingType(enumItem->underlyingType());
metaEnum.setSigned(enumItem->isSigned());
if (enumsDeclarations.contains(qualifiedName)
|| enumsDeclarations.contains(enumName)) {
@@ -888,22 +926,27 @@ std::optional<AbstractMetaEnum>
metaEnum.setAccess(enumItem->accessPolicy());
if (metaEnum.access() == Access::Private)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
-
+ // PYSIDE-2088, MSVC signedness issue in Qt
+ const bool castToUnsigned = enumItem->isSigned()
+ && enumTypeEntry->cppType().contains(u"unsigned"_s);
const EnumeratorList &enums = enumItem->enumerators();
- for (const EnumeratorModelItem &value : enums) {
+ for (const EnumeratorModelItem &valueItem : enums) {
AbstractMetaEnumValue metaEnumValue;
- metaEnumValue.setName(value->name());
+ metaEnumValue.setName(valueItem->name());
// Deciding the enum value...
- metaEnumValue.setStringValue(value->stringValue());
- metaEnumValue.setValue(value->value());
- metaEnumValue.setDeprecated(value->isDeprecated());
+ metaEnumValue.setStringValue(valueItem->stringValue());
+ const auto value = valueItem->value();
+ metaEnumValue.setValue(castToUnsigned ? value.toUnsigned() : value);
+ metaEnumValue.setDeprecated(valueItem->isDeprecated());
metaEnum.addEnumValue(metaEnumValue);
}
- if (!metaEnum.typeEntry()->include().isValid())
- setInclude(metaEnum.typeEntry(), enumItem->fileName());
+ if (!metaEnum.typeEntry()->include().isValid()) {
+ auto te = std::const_pointer_cast<EnumTypeEntry>(metaEnum.typeEntry());
+ setInclude(te, enumItem->fileName());
+ }
// Register all enum values on Type database
const bool isScopedEnum = enumItem->enumKind() == EnumClass;
@@ -923,9 +966,31 @@ std::optional<AbstractMetaEnum>
return metaEnum;
}
-AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &,
- const TypeDefModelItem &typeDef,
- const AbstractMetaClassPtr &currentClass)
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
+{
+ auto result = traverseTypeDefHelper(dom, typeDef, currentClass);
+ if (!result && typeDef->type().isPlain()) {
+ const auto &type = typeDef->type();
+ QString fullName;
+ if (currentClass)
+ fullName += currentClass->qualifiedCppName() + "::"_L1;
+ fullName += typeDef->name();
+ QString targetName = typeDef->type().toString();
+ m_typedefTargetToName.insert(targetName, fullName);
+ const QByteArray normalized = QMetaObject::normalizedType(targetName.toUtf8().constData());
+ if (targetName != QLatin1StringView(normalized))
+ m_typedefTargetToName.insert(QString::fromUtf8(normalized), fullName);
+ }
+ return result;
+}
+
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDefHelper(const FileModelItem &,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
{
TypeDatabase *types = TypeDatabase::instance();
QString className = stripTemplateArgs(typeDef->name());
@@ -985,7 +1050,7 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
{
const auto &entries = TypeDatabase::instance()->typedefEntries();
for (auto it = entries.begin(), end = entries.end(); it != end; ++it) {
- TypedefEntryPtr te = it.value();
+ const TypedefEntryPtr &te = it.value();
auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setTypeDef(true);
metaClass->setTypeEntry(te->target());
@@ -1048,7 +1113,7 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt
QTextStream(&fullClassName) << "anonymous struct at " << classItem->fileName()
<< ':' << classItem->startLine();
}
- m_rejectedClasses.insert(fullClassName, reason);
+ m_rejectedClasses.insert({reason, fullClassName, fullClassName, QString{}});
return nullptr;
}
@@ -1152,20 +1217,20 @@ void AbstractMetaBuilderPrivate::traverseClassMembers(const ClassModelItem &item
traverseScopeMembers(item, metaClass);
}
-void AbstractMetaBuilderPrivate::traverseUsingMembers(const AbstractMetaClassPtr &metaClass)
+void AbstractMetaBuilderPrivate::traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const
{
const _CodeModelItem *item = m_classToItem.value(metaClass);
if (item == nullptr || item->kind() != _CodeModelItem::Kind_Class)
return;
- auto classItem = static_cast<const _ClassModelItem *>(item);
+ const auto *classItem = static_cast<const _ClassModelItem *>(item);
for (const auto &um : classItem->usingMembers()) {
QString className = um.className;
- int pos = className.indexOf(u'<'); // strip "QList<value>"
+ auto pos = className.indexOf(u'<'); // strip "QList<value>"
if (pos != -1)
className.truncate(pos);
if (auto baseClass = findBaseClass(metaClass, className)) {
QString name = um.memberName;
- const int lastQualPos = name.lastIndexOf(u"::"_s);
+ const auto lastQualPos = name.lastIndexOf(u"::"_s);
if (lastQualPos != -1)
name.remove(0, lastQualPos + 2);
metaClass->addUsingMember({name, baseClass, um.access});
@@ -1194,7 +1259,7 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelIt
static inline QString fieldSignatureWithType(const VariableModelItem &field)
{
- return field->name() + QStringLiteral(" -> ") + field->type().toString();
+ return field->name() + " -> "_L1 + field->type().toString();
}
static inline QString qualifiedFieldSignatureWithType(const QString &className,
@@ -1219,8 +1284,9 @@ std::optional<AbstractMetaField>
QString rejectReason;
if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) {
- m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason,
- AbstractMetaBuilder::GenerationDisabled);
+ const QString signature = qualifiedFieldSignatureWithType(className, field);
+ m_rejectedFields.insert({AbstractMetaBuilder::GenerationDisabled,
+ signature, signature, rejectReason});
return {};
}
@@ -1281,13 +1347,13 @@ void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item
}
}
-void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction)
+void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(const AbstractMetaFunctionPtr &metaFunction)
{
if (!metaFunction->isConversionOperator())
return;
TypeDatabase *types = TypeDatabase::instance();
- static const QRegularExpression operatorRegExp(QStringLiteral("^operator "));
+ static const QRegularExpression operatorRegExp("^operator "_L1);
Q_ASSERT(operatorRegExp.isValid());
QString castTo = metaFunction->name().remove(operatorRegExp).trimmed();
@@ -1305,13 +1371,13 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
metaFunction->setType(metaType);
}
-AbstractMetaFunctionRawPtrList
+AbstractMetaFunctionList
AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
const AbstractMetaClassPtr &currentClass)
{
*constructorAttributes = {};
- AbstractMetaFunctionRawPtrList result;
+ AbstractMetaFunctionList result;
const FunctionList &scopeFunctionList = scopeItem->functions();
result.reserve(scopeFunctionList.size());
const bool isNamespace = currentClass->isNamespace();
@@ -1321,7 +1387,7 @@ AbstractMetaFunctionRawPtrList
} else if (function->isSpaceshipOperator() && !function->isDeleted()) {
if (currentClass)
AbstractMetaClass::addSynthesizedComparisonOperators(currentClass);
- } else if (auto *metaFunction = traverseFunction(function, currentClass)) {
+ } else if (auto metaFunction = traverseFunction(function, currentClass)) {
result.append(metaFunction);
} else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) {
auto arguments = function->arguments();
@@ -1333,17 +1399,17 @@ AbstractMetaFunctionRawPtrList
return result;
}
-void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
+void AbstractMetaBuilderPrivate::traverseFunctions(const ScopeModelItem& scopeItem,
const AbstractMetaClassPtr &metaClass)
{
AbstractMetaClass::Attributes constructorAttributes;
- const AbstractMetaFunctionRawPtrList functions =
+ const AbstractMetaFunctionList functions =
classFunctionList(scopeItem, &constructorAttributes, metaClass);
metaClass->setAttributes(metaClass->attributes() | constructorAttributes);
- for (AbstractMetaFunction *metaFunction : functions) {
+ for (const auto &metaFunction : functions) {
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name());
if (propertyFunction.index >= 0) {
@@ -1384,39 +1450,30 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
}
}
- const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate();
- const bool isInvalidConstructor = metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
- && metaFunction->isPrivate();
- if (isInvalidConstructor)
+ if (metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
+ && metaFunction->isPrivate()) {
metaClass->setHasPrivateConstructor(true);
- if ((isInvalidDestructor || isInvalidConstructor)
- && !metaClass->hasNonPrivateConstructor()) {
- *metaClass += AbstractMetaClass::FinalInTargetLang;
- } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) {
- *metaClass -= AbstractMetaClass::FinalInTargetLang;
- metaClass->setHasNonPrivateConstructor(true);
}
+ if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT
+ metaClass->setHasNonPrivateConstructor(true);
if (!metaFunction->isDestructor()
&& !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) {
- if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction))
- qCWarning(lcShiboken, "%s", qPrintable(msgSignalOverloaded(metaClass, metaFunction)));
+ if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction.get()))
+ qCWarning(lcShiboken, "%s", qPrintable(msgSignalOverloaded(metaClass,
+ metaFunction.get())));
if (metaFunction->isConversionOperator())
fixReturnTypeOfConversionOperator(metaFunction);
- AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, metaFunction);
applyFunctionModifications(metaFunction);
} else if (metaFunction->isDestructor()) {
metaClass->setHasPrivateDestructor(metaFunction->isPrivate());
metaClass->setHasProtectedDestructor(metaFunction->isProtected());
metaClass->setHasVirtualDestructor(metaFunction->isVirtual());
}
- if (!metaFunction->ownerClass()) {
- delete metaFunction;
- metaFunction = nullptr;
- }
}
fillAddedFunctions(metaClass);
@@ -1478,7 +1535,7 @@ QStringList AbstractMetaBuilder::definitionNames(const QString &name,
return result;
}
-void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func)
+void AbstractMetaBuilderPrivate::applyFunctionModifications(const AbstractMetaFunctionPtr &func)
{
AbstractMetaFunction& funcRef = *func;
for (const FunctionModification &mod : func->modifications(func->implementingClass())) {
@@ -1486,22 +1543,13 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction
func->setOriginalName(func->name());
func->setName(mod.renamedToName());
} else if (mod.isAccessModifier()) {
- funcRef -= AbstractMetaFunction::Friendly;
-
if (mod.isPublic())
funcRef.modifyAccess(Access::Public);
else if (mod.isProtected())
funcRef.modifyAccess(Access::Protected);
else if (mod.isPrivate())
funcRef.modifyAccess(Access::Private);
- else if (mod.isFriendly())
- funcRef += AbstractMetaFunction::Friendly;
}
-
- if (mod.isFinal())
- funcRef += AbstractMetaFunction::FinalInTargetLang;
- else if (mod.isNonFinal())
- funcRef -= AbstractMetaFunction::FinalInTargetLang;
}
}
@@ -1522,7 +1570,8 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me
&info, &baseContainerType);
if (templ) {
setupInheritance(templ);
- inheritTemplate(metaClass, templ, info);
+ if (!inheritTemplate(metaClass, templ, info))
+ return false;
metaClass->typeEntry()->setBaseContainerType(templ->typeEntry());
return true;
}
@@ -1539,9 +1588,9 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me
return true;
}
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("template baseclass '%1' of '%2' is not known")
- .arg(baseClasses.constFirst(), metaClass->name());
+ qCWarning(lcShiboken, "template baseclass '%s' of '%s' is not known",
+ qPrintable(baseClasses.constFirst()),
+ qPrintable(metaClass->name()));
return false;
}
@@ -1576,7 +1625,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me
} else {
QString message;
QTextStream(&message) << "Class \"" << defaultSuperclassName
- << "\" specified as \"default-superclass\" of \"" << metaClass->name()
+ << R"(" specified as "default-superclass" of ")" << metaClass->name()
<< "\" could not be found in the code model.";
qCWarning(lcShiboken, "%s", qPrintable(message));
}
@@ -1624,15 +1673,14 @@ static AbstractMetaFunction::FunctionType functionTypeFromName(const QString &);
bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunctionPtr &addedFunc,
QString *errorMessage)
{
- AbstractMetaFunction *metaFunction =
- traverseAddedFunctionHelper(addedFunc, nullptr, errorMessage);
+ auto metaFunction = traverseAddedFunctionHelper(addedFunc, nullptr, errorMessage);
if (metaFunction == nullptr)
return false;
- m_globalFunctions << AbstractMetaFunctionCPtr(metaFunction);
+ m_globalFunctions << metaFunction;
return true;
}
-AbstractMetaFunction *
+AbstractMetaFunctionPtr
AbstractMetaBuilderPrivate::traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc,
const AbstractMetaClassPtr &metaClass /* = {} */,
QString *errorMessage)
@@ -1643,10 +1691,10 @@ AbstractMetaFunction *
msgAddedFunctionInvalidReturnType(addedFunc->name(),
addedFunc->returnType().qualifiedName(),
*errorMessage, metaClass);
- return nullptr;
+ return {};
}
- auto *metaFunction = new AbstractMetaFunction(addedFunc);
+ auto metaFunction = std::make_shared<AbstractMetaFunction>(addedFunc);
metaFunction->setType(returnType.value());
metaFunction->setFunctionType(functionTypeFromName(addedFunc->name()));
@@ -1664,8 +1712,7 @@ AbstractMetaFunction *
msgAddedFunctionInvalidArgType(addedFunc->name(),
arg.typeInfo.qualifiedName(), i + 1,
*errorMessage, metaClass);
- delete metaFunction;
- return nullptr;
+ return {};
}
type->decideUsagePattern();
@@ -1703,6 +1750,7 @@ AbstractMetaFunction *
// Find the correct default values
const FunctionModificationList functionMods = metaFunction->modifications(metaClass);
+ applyCachedFunctionModifications(metaFunction, functionMods);
for (qsizetype i = 0; i < metaArguments.size(); ++i) {
AbstractMetaArgument &metaArg = metaArguments[i];
@@ -1721,14 +1769,13 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
const AbstractMetaClassPtr &metaClass,
QString *errorMessage)
{
- AbstractMetaFunction *metaFunction =
- traverseAddedFunctionHelper(addedFunc, metaClass, errorMessage);
+ auto metaFunction = traverseAddedFunctionHelper(addedFunc, metaClass, errorMessage);
if (metaFunction == nullptr)
return false;
const AbstractMetaArgumentList fargs = metaFunction->arguments();
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
if (metaFunction->name() == metaClass->name()) {
metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
if (fargs.size() == 1) {
@@ -1742,12 +1789,13 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
metaFunction->setDeclaringClass(metaClass);
metaFunction->setImplementingClass(metaClass);
- AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, metaFunction);
metaClass->setHasNonPrivateConstructor(true);
return true;
}
-void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods)
+void AbstractMetaBuilderPrivate::fixArgumentNames(const AbstractMetaFunctionPtr &func,
+ const FunctionModificationList &mods)
{
AbstractMetaArgumentList &arguments = func->arguments();
@@ -1866,7 +1914,7 @@ static AbstractMetaFunction::FunctionType functionTypeFromName(const QString &na
// Apply the <array> modifications of the arguments
static bool applyArrayArgumentModifications(const FunctionModificationList &functionMods,
- AbstractMetaFunction *func,
+ const AbstractMetaFunctionPtr &func,
QString *errorMessage)
{
for (const FunctionModification &mod : functionMods) {
@@ -1902,7 +1950,7 @@ static AbstractMetaType createViewOnType(const AbstractMetaType &metaType,
// (std::span<T, int N>) is mapped onto a std::vector<T>,
// remove the superfluous template parameters and strip 'const'.
const auto vcte = std::static_pointer_cast<const ContainerTypeEntry>(viewOnTypeEntry);
- const auto instantiations = metaType.instantiations();
+ const auto &instantiations = metaType.instantiations();
AbstractMetaTypeList viewInstantiations;
const auto size = std::min(vcte->templateParameterCount(), instantiations.size());
for (qsizetype i = 0; i < size; ++i) {
@@ -1914,11 +1962,27 @@ static AbstractMetaType createViewOnType(const AbstractMetaType &metaType,
return result;
}
-AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem,
- const AbstractMetaClassPtr &currentClass)
+void AbstractMetaBuilderPrivate::rejectFunction(const FunctionModelItem &functionItem,
+ const AbstractMetaClassPtr &currentClass,
+ AbstractMetaBuilder::RejectReason reason,
+ const QString &rejectReason)
+{
+ QString sortKey;
+ if (currentClass)
+ sortKey += currentClass->typeEntry()->qualifiedCppName() + u"::"_s;
+ sortKey += functionSignature(functionItem); // Sort without return type
+ const QString signatureWithType = functionItem->type().toString() + u' ' + sortKey;
+ m_rejectedFunctions.insert({reason, signatureWithType, sortKey, rejectReason});
+}
+
+AbstractMetaFunctionPtr
+ AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem,
+ const AbstractMetaClassPtr &currentClass)
{
+ const auto *tdb = TypeDatabase::instance();
+
if (!functionItem->templateParameters().isEmpty())
- return nullptr;
+ return {};
if (functionItem->isDeleted()) {
switch (functionItem->functionType()) {
@@ -1932,7 +1996,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
default:
break;
}
- return nullptr;
+ return {};
}
const QString &functionName = functionItem->name();
const QString className = currentClass != nullptr ?
@@ -1942,7 +2006,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
// Skip enum helpers generated by Q_ENUM
if ((currentClass == nullptr || currentClass->isNamespace())
&& (functionName == u"qt_getEnumMetaObject" || functionName == u"qt_getEnumName")) {
- return nullptr;
+ return {};
}
// Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT
@@ -1950,46 +2014,45 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (currentClass != nullptr) {
if (functionName == u"qt_check_for_QGADGET_macro"
|| functionName.startsWith(u"qt_meta")) {
- return nullptr;
+ return {};
}
if (functionName == u"metaObject" && className != u"QObject")
- return nullptr;
+ return {};
}
} // PySide extensions
- // Store original signature with unresolved typedefs for message/log purposes
- const QString originalQualifiedSignatureWithReturn =
- qualifiedFunctionSignatureWithType(functionItem, className);
-
QString rejectReason;
- if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- return nullptr;
+ if (tdb->isFunctionRejected(className, functionName, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
+ return {};
}
- const QString &signature = functionSignature(functionItem);
- const bool rejected =
- TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason);
- if (rejected) {
+ const QString &signature = functionSignature(functionItem);
+ if (tdb->isFunctionRejected(className, signature, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).",
qPrintable(className), qPrintable(signature), qPrintable(rejectReason));
}
- return nullptr;
+ return {};
}
if (functionItem->isFriend())
- return nullptr;
+ return {};
- const bool deprecated = functionItem->isDeprecated();
+ const auto cppAttributes = functionItem->attributes();
+ const bool deprecated = cppAttributes.testFlag(FunctionAttribute::Deprecated);
if (deprecated && m_skipDeprecated) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + u" is deprecated."_s,
- AbstractMetaBuilder::GenerationDisabled);
- return nullptr;
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, u" is deprecated."_s);
+ return {};
}
AbstractMetaFunction::Flags flags;
- auto *metaFunction = new AbstractMetaFunction(functionName);
+ auto metaFunction = std::make_shared<AbstractMetaFunction>(functionName);
+ metaFunction->setCppAttributes(cppAttributes);
const QByteArray cSignature = signature.toUtf8();
const QString unresolvedSignature =
QString::fromUtf8(QMetaObject::normalizedSignature(cSignature.constData()));
@@ -1997,35 +2060,12 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (functionItem->isHiddenFriend())
flags.setFlag(AbstractMetaFunction::Flag::HiddenFriend);
metaFunction->setSourceLocation(functionItem->sourceLocation());
- if (deprecated)
- *metaFunction += AbstractMetaFunction::Deprecated;
// Additional check for assignment/move assignment down below
metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType()));
metaFunction->setConstant(functionItem->isConstant());
metaFunction->setExceptionSpecification(functionItem->exceptionSpecification());
- if (functionItem->isAbstract())
- *metaFunction += AbstractMetaFunction::Abstract;
-
- if (functionItem->isVirtual()) {
- *metaFunction += AbstractMetaFunction::VirtualCppMethod;
- if (functionItem->isOverride())
- *metaFunction += AbstractMetaFunction::OverriddenCppMethod;
- if (functionItem->isFinal())
- *metaFunction += AbstractMetaFunction::FinalCppMethod;
- } else {
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
- if (functionItem->isInvokable())
- *metaFunction += AbstractMetaFunction::Invokable;
-
- if (functionItem->isStatic()) {
- *metaFunction += AbstractMetaFunction::Static;
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
// Access rights
metaFunction->setAccess(functionItem->accessPolicy());
@@ -2035,27 +2075,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
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();
- if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- delete metaFunction;
- return nullptr;
+ if (tdb->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
+ return {};
}
- auto type = translateType(returnType, currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (functionItem->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto type = translateType(returnType, currentClass, flags, &errorMessage);
if (!type.has_value()) {
const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
- delete metaFunction;
- return nullptr;
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedReturnType, reason);
+ return {};
}
metaFunction->setType(type.value());
@@ -2083,32 +2126,37 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
for (qsizetype i = 0; i < arguments.size(); ++i) {
const ArgumentModelItem &arg = arguments.at(i);
- if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
- delete metaFunction;
- return nullptr;
+ if (tdb->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
+ return {};
}
- auto metaTypeO = translateType(arg->type(), currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (arg->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto metaTypeO = translateType(arg->type(), currentClass, flags, &errorMessage);
if (!metaTypeO.has_value()) {
// If an invalid argument has a default value, simply remove it
// unless the function is virtual (since the override in the
// wrapper can then not correctly be generated).
- if (arg->defaultValue() && !functionItem->isVirtual()) {
+ if (arg->defaultValue()
+ && !functionItem->attributes().testFlag(FunctionAttribute::Virtual)) {
if (!currentClass || currentClass->typeEntry()->generateCode()) {
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
+ qPrintable(msgStrippingArgument(functionItem, i, signature,
+ arg, errorMessage)));
}
break;
}
const QString reason = msgUnmatchedParameterType(arg, i, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
- + u": "_s + reason;
- m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
- delete metaFunction;
- return nullptr;
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedArgumentType, reason);
+ return {};
}
auto metaType = metaTypeO.value();
@@ -2131,15 +2179,10 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
AbstractMetaArgumentList &metaArguments = metaFunction->arguments();
const FunctionModificationList functionMods = currentClass
- ? AbstractMetaFunction::findClassModifications(metaFunction, currentClass)
- : AbstractMetaFunction::findGlobalModifications(metaFunction);
+ ? AbstractMetaFunction::findClassModifications(metaFunction.get(), currentClass)
+ : AbstractMetaFunction::findGlobalModifications(metaFunction.get());
- for (const FunctionModification &mod : functionMods) {
- if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
- metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
- if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
- metaFunction->setAllowThreadModification(mod.allowThread());
- }
+ applyCachedFunctionModifications(metaFunction, functionMods);
// Find the correct default values
for (qsizetype i = 0, size = metaArguments.size(); i < size; ++i) {
@@ -2162,7 +2205,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
&& metaFunction->argumentName(i + 1, false, currentClass).isEmpty()) {
qCWarning(lcShiboken, "%s",
qPrintable(msgUnnamedArgumentDefaultExpression(currentClass, i + 1,
- className, metaFunction)));
+ className, metaFunction.get())));
}
}
@@ -2215,11 +2258,13 @@ static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClassCPtr &meta
// Helper for findTypeEntries/translateTypeStatic()
TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName,
const QString &name,
+ TranslateTypeFlags flags,
const AbstractMetaClassCPtr &currentClass,
AbstractMetaBuilderPrivate *d)
{
// 5.1 - Try first using the current scope
- if (currentClass) {
+ if (currentClass != nullptr
+ && !flags.testFlag(AbstractMetaBuilder::NoClassScopeLookup)) {
if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName))
return {type};
@@ -2262,11 +2307,13 @@ TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &
// and does some error checking.
TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
const QString &name,
+ TranslateTypeFlags flags,
const AbstractMetaClassCPtr &currentClass,
AbstractMetaBuilderPrivate *d,
QString *errorMessage)
{
- TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, currentClass, d);
+ TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, flags,
+ currentClass, d);
if (types.isEmpty()) {
if (errorMessage != nullptr)
*errorMessage = msgCannotFindTypeEntry(qualifiedName);
@@ -2314,7 +2361,7 @@ TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualif
AbstractMetaClassCPtr AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const
{
if (t.hasInstantiations()) {
- auto pred = [t](const TypeClassEntry &e) { return e.type.equals(t); };
+ auto pred = [t](const TypeClassEntry &e) { return e.type == t; };
auto it = std::find_if(m_typeSystemTypeDefs.cbegin(), m_typeSystemTypeDefs.cend(), pred);
if (it != m_typeSystemTypeDefs.cend())
return it->klass;
@@ -2522,6 +2569,13 @@ static bool isNumber(const QString &s)
[](QChar c) { return c.isDigit(); });
}
+// A type entry relevant only for non type template "X<5>"
+static bool isNonTypeTemplateArgument(const TypeEntryCPtr &te)
+{
+ const auto type = te->type();
+ return type == TypeEntry::EnumValue || type == TypeEntry::ConstantValueType;
+}
+
std::optional<AbstractMetaType>
AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
const AbstractMetaClassCPtr &currentClass,
@@ -2578,7 +2632,7 @@ std::optional<AbstractMetaType>
bool isConstCharStarCase =
oneDimensionalArrayOfUnspecifiedSize
&& typeInfo.qualifiedName().size() == 1
- && typeInfo.qualifiedName().at(0) == QStringLiteral("char")
+ && typeInfo.qualifiedName().at(0) == "char"_L1
&& typeInfo.indirections() == 0
&& typeInfo.isConstant()
&& typeInfo.referenceType() == NoReference
@@ -2651,7 +2705,16 @@ std::optional<AbstractMetaType>
typeInfo.clearInstantiations();
}
- const TypeEntryCList types = findTypeEntries(qualifiedName, name, currentClass, d, errorMessageIn);
+ TypeEntryCList types = findTypeEntries(qualifiedName, name, flags,
+ currentClass, d, errorMessageIn);
+ if (!flags.testFlag(AbstractMetaBuilder::TemplateArgument)) {
+ // Avoid clashes between QByteArray and enum value QMetaType::QByteArray
+ // unless we are looking for template arguments.
+ auto end = std::remove_if(types.begin(), types.end(),
+ isNonTypeTemplateArgument);
+ types.erase(end, types.end());
+ }
+
if (types.isEmpty()) {
if (errorMessageIn != nullptr)
*errorMessageIn = msgUnableToTranslateType(_typei, *errorMessageIn);
@@ -2671,7 +2734,9 @@ std::optional<AbstractMetaType>
const auto &templateArguments = typeInfo.instantiations();
for (qsizetype t = 0, size = templateArguments.size(); t < size; ++t) {
const TypeInfo &ti = templateArguments.at(t);
- auto targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
+ auto targType = translateTypeStatic(ti, currentClass, d,
+ flags | AbstractMetaBuilder::TemplateArgument,
+ &errorMessage);
// For non-type template parameters, create a dummy type entry on the fly
// as is done for classes.
if (!targType.has_value()) {
@@ -2780,7 +2845,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
// This is a very lame way to handle expression evaluation,
// but it is not critical and will do for the time being.
- static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ static const QRegularExpression variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$"_L1);
Q_ASSERT(variableNameRegExp.isValid());
if (!variableNameRegExp.match(stringValue).hasMatch()) {
ok = true;
@@ -2817,9 +2882,10 @@ static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidat
}
QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type,
- const QString &expr) const
+ const QString &expr,
+ const AbstractMetaClassCPtr &klass) const
{
- return d->fixEnumDefault(type, expr);
+ return d->fixEnumDefault(type, expr, klass);
}
void AbstractMetaBuilder::setCodeModelTestMode(bool b)
@@ -2857,7 +2923,7 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const Abstract
return expr;
if (type.isFlags() || type.isEnum()) {
- expr = fixEnumDefault(type, expr);
+ expr = fixEnumDefault(type, expr, implementingClass);
} else if (type.isContainer() && expr.contains(u'<')) {
// Expand a container of a nested class, fex
// "QList<FormatRange>()" -> "QList<QTextLayout::FormatRange>()"
@@ -3054,80 +3120,103 @@ std::optional<AbstractMetaType>
AbstractMetaClassPtr
AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te,
const AbstractMetaClassCPtr &templateClass,
- const AbstractMetaTypeList &templateTypes,
- InheritTemplateFlags flags)
+ const AbstractMetaTypeList &templateTypes)
{
auto result = std::make_shared<AbstractMetaClass>();
result->setTypeDef(true);
result->setTypeEntry(te);
if (!AbstractMetaBuilderPrivate::inheritTemplate(result, templateClass,
- templateTypes, flags)) {
+ templateTypes)) {
return {};
}
AbstractMetaBuilderPrivate::inheritTemplateFunctions(result);
return result;
}
+
+static std::optional<AbstractMetaType>
+ inheritTemplateParameter(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
+ const TypeInfo &info, QString *errorMessage)
+{
+ QString typeName = info.qualifiedName().join("::"_L1);
+ TypeDatabase *typeDb = TypeDatabase::instance();
+ TypeEntryPtr t;
+ // 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.
+ if (isNumber(typeName)) {
+ t = typeDb->findType(typeName);
+ if (!t) {
+ auto parent = typeSystemTypeEntry(subclass->typeEntry());
+ t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
+ }
+ } else {
+ QStringList possibleNames;
+ possibleNames << subclass->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << templateClass->qualifiedCppName() + "::"_L1 + typeName;
+ if (subclass->enclosingClass())
+ possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << typeName;
+
+ for (const QString &possibleName : std::as_const(possibleNames)) {
+ t = typeDb->findType(possibleName);
+ if (t)
+ break;
+ }
+ }
+
+ if (!t) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "The corresponding type was not found in the typesystem.");
+ return std::nullopt;
+ }
+
+ if (t->isContainer()) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "Template inheritance from nested containers is not supported");
+ return std::nullopt;
+ }
+ AbstractMetaType result(t);
+ result.setConstant(info.isConstant());
+ result.setReferenceType(info.referenceType());
+ result.setIndirectionsV(info.indirectionsV());
+ result.decideUsagePattern();
+ return result;
+}
+
bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
const AbstractMetaClassCPtr &templateClass,
const TypeInfo &info)
{
AbstractMetaTypeList templateTypes;
+ QString errorMessage;
for (const TypeInfo &i : info.instantiations()) {
- QString typeName = i.qualifiedName().join(u"::"_s);
- TypeDatabase *typeDb = TypeDatabase::instance();
- TypeEntryPtr t;
- // 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.
- if (isNumber(typeName)) {
- t = typeDb->findType(typeName);
- if (!t) {
- auto parent = typeSystemTypeEntry(subclass->typeEntry());
- t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
- }
+ const auto typeO = inheritTemplateParameter(subclass, templateClass, i, &errorMessage);
+ if (typeO.has_value()) {
+ templateTypes.append(typeO.value());
} else {
- QStringList possibleNames;
- possibleNames << subclass->qualifiedCppName() + u"::"_s + typeName;
- possibleNames << templateClass->qualifiedCppName() + u"::"_s + typeName;
- if (subclass->enclosingClass())
- possibleNames << subclass->enclosingClass()->qualifiedCppName() + u"::"_s + typeName;
- possibleNames << typeName;
-
- for (const QString &possibleName : std::as_const(possibleNames)) {
- t = typeDb->findType(possibleName);
- if (t)
- break;
- }
- }
-
- if (t) {
- AbstractMetaType temporaryType(t);
- temporaryType.setConstant(i.isConstant());
- temporaryType.setReferenceType(i.referenceType());
- temporaryType.setIndirectionsV(i.indirectionsV());
- temporaryType.decideUsagePattern();
- templateTypes << temporaryType;
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "Ignoring template parameter " << typeName << " from "
- << info.toString() << ". The corresponding type was not found in the typesystem.";
+ errorMessage = msgInheritTemplateIssue(subclass, info, errorMessage);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
}
}
+ if (templateTypes.isEmpty()) {
+ errorMessage = msgInheritTemplateIssue(subclass, info,
+ "No template parameters could be inherited"_L1);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
+ return false;
+ }
return inheritTemplate(subclass, templateClass, templateTypes);
}
bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
const AbstractMetaClassCPtr &templateClass,
- const AbstractMetaTypeList &templateTypes,
- InheritTemplateFlags flags)
+ const AbstractMetaTypeList &templateTypes)
{
subclass->setTemplateBaseClass(templateClass);
- if (flags.testFlag(InheritTemplateFlag::SetEnclosingClass))
- subclass->setEnclosingClass(templateClass->enclosingClass());
subclass->setTemplateBaseClassInstantiations(templateTypes);
subclass->setBaseClass(templateClass->baseClass());
return true;
@@ -3217,7 +3306,7 @@ AbstractMetaFunctionPtr
}
QString errorMessage;
- if (!applyArrayArgumentModifications(f->modifications(subclass), f.get(),
+ if (!applyArrayArgumentModifications(f->modifications(subclass), f,
&errorMessage)) {
qCWarning(lcShiboken, "While specializing %s (%s): %s",
qPrintable(subclass->name()), qPrintable(templateClass->name()),
@@ -3310,7 +3399,7 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(const AbstractMetaClassPtr &m
if (spec.has_value()) {
spec->setIndex(i);
metaClass->addPropertySpec(spec.value());
- } else {
+ } else if (!errorMessage.isEmpty()) {
QString message;
QTextStream str(&message);
str << metaClass->sourceLocation() << errorMessage;
@@ -3356,8 +3445,18 @@ void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClass
}
static void writeRejectLogFile(const QString &name,
- const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
-{
+ const AbstractMetaBuilderPrivate::RejectSet &rejects)
+{
+ static const QHash<AbstractMetaBuilder::RejectReason, QByteArray> descriptions ={
+ {AbstractMetaBuilder::NotInTypeSystem, "Not in type system"_ba},
+ {AbstractMetaBuilder::GenerationDisabled, "Generation disabled by type system"_ba},
+ {AbstractMetaBuilder::RedefinedToNotClass, "Type redefined to not be a class"_ba},
+ {AbstractMetaBuilder::UnmatchedReturnType, "Unmatched return type"_ba},
+ {AbstractMetaBuilder::UnmatchedArgumentType, "Unmatched argument type"_ba},
+ {AbstractMetaBuilder::UnmatchedOperator, "Unmatched operator"_ba},
+ {AbstractMetaBuilder::Deprecated, "Deprecated"_ba}
+ };
+
QFile f(name);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
qCWarning(lcShiboken, "%s", qPrintable(msgCannotOpenForWriting(f)));
@@ -3366,53 +3465,19 @@ static void writeRejectLogFile(const QString &name,
QTextStream s(&f);
-
- for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) {
- s << QByteArray(72, '*') << '\n';
- switch (reason) {
- case AbstractMetaBuilder::NotInTypeSystem:
- s << "Not in type system";
- break;
- case AbstractMetaBuilder::GenerationDisabled:
- s << "Generation disabled by type system";
- break;
- case AbstractMetaBuilder::RedefinedToNotClass:
- s << "Type redefined to not be a class";
- break;
-
- case AbstractMetaBuilder::UnmatchedReturnType:
- s << "Unmatched return type";
- break;
-
- case AbstractMetaBuilder::UnmatchedArgumentType:
- s << "Unmatched argument type";
- break;
-
- case AbstractMetaBuilder::ApiIncompatible:
- s << "Incompatible API";
- break;
-
- case AbstractMetaBuilder::Deprecated:
- s << "Deprecated";
- break;
-
- default:
- s << "unknown reason";
- break;
- }
-
- 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() << Qt::endl;
+ int lastReason = -1;
+ for (const auto &e : rejects) {
+ if (e.reason != lastReason) {
+ const QByteArray description = descriptions.value(e.reason, "Unknown reason"_ba);
+ const QByteArray underline(description.size(), '*');
+ if (lastReason != -1)
+ s << '\n';
+ s << underline << '\n' << description << '\n' << underline << "\n\n";
+ lastReason = e.reason;
}
- s << QByteArray(72, '*') << "\n\n";
+ s << " - " << e << '\n';
}
-
}
void AbstractMetaBuilderPrivate::dumpLog() const
@@ -3490,16 +3555,22 @@ static QList<std::shared_ptr<MetaClass> >
if (!result.isValid() && graph.nodeCount()) {
QTemporaryFile tempFile(QDir::tempPath() + u"/cyclic_depXXXXXX.dot"_s);
tempFile.setAutoRemove(false);
- tempFile.open();
- graph.dumpDot(tempFile.fileName(),
- [] (const AbstractMetaClassCPtr &c) { return c->name(); });
+ const bool ok = tempFile.open();
+ if (ok) {
+ graph.dumpDot(tempFile.fileName(),
+ [] (const AbstractMetaClassCPtr &c) { return c->name(); });
+ }
QString message;
QTextStream str(&message);
str << "Cyclic dependency of classes found:";
- for (auto c : result.cyclic)
+ for (const auto &c : result.cyclic)
str << ' ' << c->name();
- str << ". Graph can be found at \"" << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ str << '.';
+ if (ok) {
+ str << " Graph can be found at \""
+ << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ }
qCWarning(lcShiboken, "%s", qPrintable(message));
}