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.cpp242
1 files changed, 86 insertions, 156 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index d76c788ec..c879727c3 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -32,6 +32,7 @@
#include <clangparser/clangbuilder.h>
#include <clangparser/clangutils.h>
+#include <clangparser/compilersupport.h>
#include "parser/codemodel.h"
@@ -158,18 +159,18 @@ AbstractMetaEnumList AbstractMetaBuilder::globalEnums() const
return d->m_globalEnums;
}
-QSet<QString> AbstractMetaBuilder::qtMetaTypeDeclaredTypeNames() const
-{
- return d->m_qmetatypeDeclaredTypenames;
-}
-
-static QString msgNoFunctionForModification(const QString &signature, const QString &className,
+static QString msgNoFunctionForModification(const QString &signature,
+ const QString &originalSignature,
+ const QString &className,
const QStringList &possibleSignatures,
const AbstractMetaFunctionList &allFunctions)
{
QString result;
QTextStream str(&result);
- str << "signature '" << signature << "' for function modification in '"
+ str << "signature '" << signature << '\'';
+ if (!originalSignature.isEmpty() && originalSignature != signature)
+ str << " (specified as '" << originalSignature << "')";
+ str << " for function modification in '"
<< className << "' not found.";
if (possibleSignatures.isEmpty()) {
str << " No candidates were found. Member functions: ";
@@ -231,7 +232,9 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
if (!found) {
qCWarning(lcShiboken).noquote().nospace()
- << msgNoFunctionForModification(signature, clazz->qualifiedCppName(),
+ << msgNoFunctionForModification(signature,
+ modification.originalSignature(),
+ clazz->qualifiedCppName(),
possibleSignatures, functions);
}
}
@@ -436,10 +439,15 @@ void AbstractMetaBuilderPrivate::sortLists()
cls->sortFunctions();
}
-FileModelItem AbstractMetaBuilderPrivate::buildDom(const QByteArrayList &arguments,
+FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
+ LanguageLevel level,
unsigned clangFlags)
{
clang::Builder builder;
+ if (level == LanguageLevel::Default)
+ level = clang::emulatedCompilerLanguageLevel();
+ arguments.prepend(QByteArrayLiteral("-std=")
+ + clang::languageLevelOption(level));
FileModelItem result = clang::parse(arguments, clangFlags, builder)
? builder.dom() : FileModelItem();
const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics();
@@ -708,6 +716,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
const AddedFunctionList &globalUserFunctions = types->globalUserFunctions();
for (const AddedFunction &addedFunc : globalUserFunctions) {
AbstractMetaFunction* metaFunc = traverseFunction(addedFunc);
+ if (Q_UNLIKELY(!metaFunc)) {
+ qFatal("Unable to traverse added global function \"%s\".",
+ qPrintable(addedFunc.name()));
+ }
metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction);
m_globalFunctions << metaFunc;
}
@@ -715,9 +727,11 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
std::puts("");
}
-bool AbstractMetaBuilder::build(const QByteArrayList &arguments, unsigned clangFlags)
+bool AbstractMetaBuilder::build(const QByteArrayList &arguments,
+ LanguageLevel level,
+ unsigned clangFlags)
{
- const FileModelItem dom = d->buildDom(arguments, clangFlags);
+ const FileModelItem dom = d->buildDom(arguments, level, clangFlags);
if (dom.isNull())
return false;
if (ReportHandler::isDebug(ReportHandler::MediumDebug))
@@ -1027,16 +1041,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
ComplexTypeEntry* type = TypeDatabase::instance()->findComplexType(fullClassName);
AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason;
- if (fullClassName == QLatin1String("QMetaTypeId")) {
- // QtScript: record which types have been declared
- int lpos = classItem->name().indexOf(QLatin1Char('<'));
- int rpos = classItem->name().lastIndexOf(QLatin1Char('>'));
- if ((lpos != -1) && (rpos != -1)) {
- QString declaredTypename = classItem->name().mid(lpos + 1, rpos - lpos - 1);
- m_qmetatypeDeclaredTypenames.insert(declaredTypename);
- }
- }
-
if (TypeDatabase::instance()->isClassRejected(fullClassName)) {
reason = AbstractMetaBuilder::GenerationDisabled;
} else if (!type) {
@@ -1352,45 +1356,6 @@ static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, cons
return true;
}
-// Fix the arguments of template classes that take the class itself, for example:
-// "QList(const QList &)" to "QList(const QList<T> &)".
-static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass)
-{
- const QVector<TypeEntry *> &templateTypes = metaClass->templateArguments();
- if (templateTypes.isEmpty())
- return false;
-
- const QStringList classType = metaClass->typeEntry()->qualifiedCppName().split(colonColon());
- QStringList fixedClassType = classType;
- fixedClassType.last().append(QLatin1Char('<'));
- for (int i = 0, count = templateTypes.size(); i < count; ++i) {
- if (i)
- fixedClassType.last().append(QLatin1String(", "));
- fixedClassType.last().append(templateTypes.at(i)->qualifiedCppName());
- }
- fixedClassType.last().append(QLatin1String(" >"));
-
- bool templateTypeFixed = false;
- TypeInfo functionType = function->type();
- if (functionType.qualifiedName() == classType) {
- templateTypeFixed = true;
- functionType.setQualifiedName(fixedClassType);
- function->setType(functionType);
- }
-
- ArgumentList arguments = function->arguments();
- for (int i = 0; i < arguments.size(); ++i) {
- ArgumentModelItem arg = arguments.at(i);
- TypeInfo type = arg->type();
- if (type.qualifiedName() == classType) {
- type.setQualifiedName(fixedClassType);
- arg->setType(type);
- templateTypeFixed = true;
- }
- }
- return templateTypeFixed;
-}
-
AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem,
bool *constructorRejected)
{
@@ -1430,49 +1395,12 @@ private:
const AbstractMetaFunction *m_function;
};
-AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(const ScopeModelItem &scopeItem,
- AbstractMetaClass *metaClass,
- bool *constructorRejected)
-{
- AbstractMetaFunctionList result;
- AbstractMetaFunctionList unchangedFunctions;
-
- *constructorRejected = false;
- const FunctionList &scopeFunctionList = scopeItem->functions();
- result.reserve(scopeFunctionList.size());
- unchangedFunctions.reserve(scopeFunctionList.size());
- for (FunctionModelItem function : scopeFunctionList) {
- // This fixes method's arguments and return types that are templates
- // but the template variable wasn't declared in the C++ header.
- const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass);
- if (AbstractMetaFunction *metaFunction = traverseFunction(function)) {
- result.append(metaFunction);
- if (!templateTypeFixed)
- unchangedFunctions.append(metaFunction);
- } else if (function->functionType() == CodeModel::Constructor) {
- *constructorRejected = true;
- }
- }
-
- const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.cbegin();
- const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.cend();
- for (int i = result.size() - 1; i >= 0; --i) {
- AbstractMetaFunction *function = result.at(i);
- if (!unchangedFunctions.contains(function)
- && unchangedEnd != std::find_if(unchangedBegin, unchangedEnd, DuplicatingFunctionPredicate(function))) {
- delete result.takeAt(i);
- }
- }
- return result;
-}
-
void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
AbstractMetaClass *metaClass)
{
bool constructorRejected = false;
- const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty()
- ? classFunctionList(scopeItem, &constructorRejected)
- : templateClassFunctionList(scopeItem, metaClass, &constructorRejected);
+ const AbstractMetaFunctionList functions =
+ classFunctionList(scopeItem, &constructorRejected);
if (constructorRejected)
*metaClass += AbstractMetaAttributes::HasRejectedConstructor;
@@ -1564,8 +1492,12 @@ void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass
{
// Add the functions added by the typesystem
const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions();
- for (const AddedFunction &addedFunc : addedFunctions)
- traverseFunction(addedFunc, metaClass);
+ for (const AddedFunction &addedFunc : addedFunctions) {
+ if (!traverseFunction(addedFunc, metaClass)) {
+ qFatal("Unable to traverse function \"%s\" added to \"%s\".",
+ qPrintable(addedFunc.name()), qPrintable(metaClass->name()));
+ }
+ }
}
void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func)
@@ -1612,7 +1544,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
// we only support our own containers and ONLY if there is only one baseclass
if (baseClasses.size() == 1 && baseClasses.constFirst().contains(QLatin1Char('<'))) {
- TypeParser::Info info;
+ TypeInfo info;
ComplexTypeEntry* baseContainerType;
AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType);
if (templ) {
@@ -1746,6 +1678,13 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
AddedFunction::TypeInfo& typeInfo = args[i];
AbstractMetaArgument *metaArg = new AbstractMetaArgument;
AbstractMetaType *type = translateType(typeInfo);
+ 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()));
+ delete metaFunction;
+ return nullptr;
+ }
type->decideUsagePattern();
metaArg->setType(type);
metaArg->setArgumentIndex(i);
@@ -2343,8 +2282,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return nullptr;
QString errorMessage;
- TypeParser::Info typeInfo = TypeParser::parse(typei.toString(), &errorMessage);
- if (typeInfo.is_busted) {
+ TypeInfo typeInfo = TypeParser::parse(typei.toString(), &errorMessage);
+ if (typeInfo.qualifiedName().isEmpty()) {
qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString()
<< "\": " << errorMessage;
return 0;
@@ -2354,43 +2293,43 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
// 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with
// NativePointerPattern usage.
bool oneDimensionalArrayOfUnspecifiedSize =
- typeInfo.arrays.size() == 1
- && typeInfo.arrays[0].isEmpty();
+ typeInfo.arrayElements().size() == 1
+ && typeInfo.arrayElements().at(0).isEmpty();
bool isConstCharStarCase =
oneDimensionalArrayOfUnspecifiedSize
- && typeInfo.qualified_name.size() == 1
- && typeInfo.qualified_name[0] == QStringLiteral("char")
- && typeInfo.indirections == 0
- && typeInfo.is_constant == 1
- && typeInfo.is_busted == 0
- && typeInfo.referenceType == NoReference
- && typeInfo.template_instantiations.size() == 0;
+ && typeInfo.qualifiedName().size() == 1
+ && typeInfo.qualifiedName().at(0) == QStringLiteral("char")
+ && typeInfo.indirections() == 0
+ && typeInfo.isConstant()
+ && typeInfo.referenceType() == NoReference
+ && typeInfo.arguments().isEmpty();
if (isConstCharStarCase)
- typeInfo.indirections += typeInfo.arrays.size();
+ typeInfo.setIndirections(typeInfo.indirections() + typeInfo.arrayElements().size());
// 2.2 Handle regular arrays.
- if (typeInfo.arrays.size() > 0 && !isConstCharStarCase) {
+ if (!typeInfo.arrayElements().isEmpty() && !isConstCharStarCase) {
TypeInfo newInfo;
- //newInfo.setArguments(typei.arguments());
- newInfo.setIndirections(typei.indirections());
- newInfo.setConstant(typei.isConstant());
- newInfo.setFunctionPointer(typei.isFunctionPointer());
- newInfo.setQualifiedName(typei.qualifiedName());
- newInfo.setReferenceType(typei.referenceType());
- newInfo.setVolatile(typei.isVolatile());
+ //newInfo.setArguments(typeInfo.arguments());
+ newInfo.setIndirections(typeInfo.indirections());
+ newInfo.setConstant(typeInfo.isConstant());
+ newInfo.setFunctionPointer(typeInfo.isFunctionPointer());
+ newInfo.setQualifiedName(typeInfo.qualifiedName());
+ newInfo.setReferenceType(typeInfo.referenceType());
+ newInfo.setVolatile(typeInfo.isVolatile());
AbstractMetaType *elementType = translateType(newInfo);
if (!elementType)
return nullptr;
- for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) {
+ for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
AbstractMetaType *arrayType = new AbstractMetaType;
arrayType->setArrayElementType(elementType);
- if (!typeInfo.arrays.at(i).isEmpty()) {
+ const QString &arrayElement = typeInfo.arrayElements().at(i);
+ if (!arrayElement.isEmpty()) {
bool _ok;
- const qint64 elems = findOutValueFromString(typeInfo.arrays.at(i), _ok);
+ const qint64 elems = findOutValueFromString(arrayElement, _ok);
if (_ok)
arrayType->setArrayElementCount(int(elems));
}
@@ -2403,7 +2342,7 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return elementType;
}
- QStringList qualifierList = typeInfo.qualified_name;
+ QStringList qualifierList = typeInfo.qualifiedName();
if (qualifierList.isEmpty()) {
qCWarning(lcShiboken).noquote().nospace()
<< QStringLiteral("horribly broken type '%1'").arg(_typei.toString());
@@ -2468,21 +2407,16 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
AbstractMetaType *metaType = new AbstractMetaType;
metaType->setTypeEntry(type);
- metaType->setIndirections(typeInfo.indirections);
- metaType->setReferenceType(typeInfo.referenceType);
- metaType->setConstant(typeInfo.is_constant);
+ metaType->setIndirections(typeInfo.indirections());
+ metaType->setReferenceType(typeInfo.referenceType());
+ metaType->setConstant(typeInfo.isConstant());
metaType->setOriginalTypeDescription(_typei.toString());
- for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) {
- TypeInfo info;
- info.setConstant(ta.is_constant);
- info.setReferenceType(ta.referenceType);
- info.setIndirections(ta.indirections);
-
- info.setFunctionPointer(false);
- info.setQualifiedName(ta.instantiationName().split(colonColon()));
-
- AbstractMetaType *targType = translateType(info);
+ const auto &templateArguments = typeInfo.arguments();
+ for (int t = 0, size = templateArguments.size(); t < size; ++t) {
+ TypeInfo ti = templateArguments.at(t);
+ ti.setQualifiedName(ti.instantiationName());
+ AbstractMetaType *targType = translateType(ti);
if (!targType) {
delete metaType;
return nullptr;
@@ -2671,13 +2605,9 @@ bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringL
AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
const AbstractMetaClass *context,
- TypeParser::Info *info,
+ TypeInfo *info,
ComplexTypeEntry **baseContainerType) const
{
- TypeParser::Info localInfo;
- if (!info)
- info = &localInfo;
-
TypeDatabase* types = TypeDatabase::instance();
QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon());
@@ -2686,14 +2616,15 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &
for (int i = scope.size(); i >= 0; --i) {
QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString();
QString completeName = prefix + name;
- const TypeParser::Info parsed = TypeParser::parse(completeName, &errorMessage);
- if (parsed.is_busted) {
+ const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage);
+ QString qualifiedName = parsed.qualifiedName().join(colonColon());
+ if (qualifiedName.isEmpty()) {
qWarning().noquote().nospace() << "Unable to parse type \"" << completeName
<< "\" while looking for template \"" << name << "\": " << errorMessage;
continue;
}
- *info = parsed;
- QString qualifiedName = info->qualified_name.join(colonColon());
+ if (info)
+ *info = parsed;
AbstractMetaClass* templ = 0;
for (AbstractMetaClass *c : qAsConst(m_templates)) {
@@ -2795,9 +2726,9 @@ AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector<
bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
const AbstractMetaClass *templateClass,
- const TypeParser::Info &info)
+ const TypeInfo &info)
{
- QVector<TypeParser::Info> targs = info.template_instantiations;
+ QVector<TypeInfo> targs = info.arguments();
QVector<AbstractMetaType *> templateTypes;
if (subclass->isTypeDef()) {
@@ -2810,8 +2741,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor());
}
- for (const TypeParser::Info &i : qAsConst(targs)) {
- QString typeName = i.qualified_name.join(colonColon());
+ for (const TypeInfo &i : qAsConst(targs)) {
+ QString typeName = i.qualifiedName().join(colonColon());
QStringList possibleNames;
possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
@@ -2831,9 +2762,9 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
if (t) {
AbstractMetaType *temporaryType = new AbstractMetaType;
temporaryType->setTypeEntry(t);
- temporaryType->setConstant(i.is_constant);
- temporaryType->setReferenceType(i.referenceType);
- temporaryType->setIndirections(i.indirections);
+ temporaryType->setConstant(i.isConstant());
+ temporaryType->setReferenceType(i.referenceType());
+ temporaryType->setIndirections(i.indirections());
temporaryType->decideUsagePattern();
templateTypes << temporaryType;
} else {
@@ -3285,7 +3216,6 @@ static void debugFormatSequence(QDebug &d, const char *key, const Container& c,
void AbstractMetaBuilder::formatDebug(QDebug &debug) const
{
debug << "m_globalHeader=" << d->m_globalHeader.absoluteFilePath();
- debugFormatSequence(debug, "qtMetaTypeDeclaredTypeNames", d->m_qmetatypeDeclaredTypenames);
debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n");
debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n");
if (const int scopeCount = d->m_scopes.size()) {