aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2')
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt7
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp242
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h8
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h12
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp21
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.h5
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp23
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp152
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.h15
-rw-r--r--sources/shiboken2/ApiExtractor/header_paths.h38
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp14
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h3
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.cpp388
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testutil.h2
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.cpp126
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.h25
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp10
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h4
-rw-r--r--sources/shiboken2/CMakeLists.txt40
-rw-r--r--sources/shiboken2/generator/generator.cpp13
-rw-r--r--sources/shiboken2/generator/generator.h52
-rw-r--r--sources/shiboken2/generator/main.cpp80
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp8
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp15
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h3
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp111
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h27
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp11
-rw-r--r--sources/shiboken2/libshiboken/pep384_issue33738.cpp121
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp93
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h16
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp5
-rw-r--r--sources/shiboken2/libshiboken/sbkpython.h1
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp10
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.h4
-rw-r--r--sources/shiboken2/libshiboken/voidptr.cpp9
-rw-r--r--sources/shiboken2/tests/dumpcodemodel/main.cpp26
38 files changed, 843 insertions, 902 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt
index a3301a068..b67a352f0 100644
--- a/sources/shiboken2/ApiExtractor/CMakeLists.txt
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -31,13 +31,6 @@ add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
add_definitions(-DRXX_ALLOCATOR_INIT_0)
-# Pass the path to the clang includes dir, so it headers like stdarg.h.
-if(UNIX AND NOT APPLE)
- add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="${CLANG_BUILTIN_INCLUDES_DIR}")
-else()
- add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="")
-endif()
-
set(apiextractor_SRC
apiextractor.cpp
abstractmetabuilder.cpp
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()) {
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
index bd1236375..a0ca71b94 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
@@ -32,6 +32,8 @@
#include "abstractmetalang_typedefs.h"
#include "dependency.h"
+#include "clangparser/compilersupport.h"
+
QT_FORWARD_DECLARE_CLASS(QIODevice)
class AbstractMetaBuilderPrivate;
@@ -59,8 +61,6 @@ public:
AbstractMetaClassList smartPointers() const;
AbstractMetaFunctionList globalFunctions() const;
AbstractMetaEnumList globalEnums() const;
- // QtScript
- QSet<QString> qtMetaTypeDeclaredTypeNames() const;
/**
* Sorts a list of classes topologically, if an AbstractMetaClass object
@@ -71,7 +71,9 @@ public:
AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR,
const Dependencies &additionalDependencies = Dependencies()) const;
- bool build(const QByteArrayList &arguments, unsigned clangFlags = 0);
+ bool build(const QByteArrayList &arguments,
+ LanguageLevel level = LanguageLevel::Default,
+ unsigned clangFlags = 0);
void setLogDirectory(const QString& logDir);
/**
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
index 959734462..59e3cfc94 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
@@ -46,7 +46,9 @@ public:
AbstractMetaBuilderPrivate();
~AbstractMetaBuilderPrivate();
- static FileModelItem buildDom(const QByteArrayList &arguments, unsigned clangFlags);
+ static FileModelItem buildDom(QByteArrayList arguments,
+ LanguageLevel level,
+ unsigned clangFlags);
void traverseDom(const FileModelItem &dom);
void dumpLog() const;
@@ -122,18 +124,17 @@ public:
AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo);
AbstractMetaType *translateType(const TypeInfo &type,
bool resolveType = true);
-
qint64 findOutValueFromString(const QString &stringValue, bool &ok);
AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context,
- TypeParser::Info *info = Q_NULLPTR,
+ TypeInfo *info = Q_NULLPTR,
ComplexTypeEntry **baseContainerType = Q_NULLPTR) const;
AbstractMetaClassList getBaseClasses(const AbstractMetaClass *metaClass) const;
bool ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const;
bool inheritTemplate(AbstractMetaClass *subclass,
const AbstractMetaClass *templateClass,
- const TypeParser::Info &info);
+ const TypeInfo &info);
AbstractMetaType *inheritTemplateType(const QVector<AbstractMetaType *> &templateTypes,
const AbstractMetaType *metaType,
bool *ok = Q_NULLPTR);
@@ -181,9 +182,6 @@ public:
QSet<AbstractMetaClass *> m_setupInheritanceDone;
- // QtScript
- QSet<QString> m_qmetatypeDeclaredTypenames;
-
QString m_logDirectory;
QFileInfo m_globalHeader;
};
diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp
index 4c4eaff6c..171011cd4 100644
--- a/sources/shiboken2/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp
@@ -159,12 +159,6 @@ ContainerTypeEntryList ApiExtractor::containerTypes() const
return TypeDatabase::instance()->containerTypes();
}
-QSet<QString> ApiExtractor::qtMetaTypeDeclaredTypeNames() const
-{
- Q_ASSERT(m_builder);
- return m_builder->qtMetaTypeDeclaredTypeNames();
-}
-
static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry)
{
const AbstractMetaEnum* result = 0;
@@ -259,8 +253,9 @@ bool ApiExtractor::run()
for (const HeaderPath &headerPath : qAsConst(m_includePaths))
arguments.append(HeaderPath::includeOption(headerPath));
arguments.append(QFile::encodeName(preprocessedCppFileName));
- qCDebug(lcShiboken) << __FUNCTION__ << arguments;
- const bool result = m_builder->build(arguments);
+ qCDebug(lcShiboken) << __FUNCTION__ << arguments
+ << "level=" << int(m_languageLevel);
+ const bool result = m_builder->build(arguments, m_languageLevel);
if (!result)
autoRemove = false;
if (!autoRemove) {
@@ -270,6 +265,16 @@ bool ApiExtractor::run()
return result;
}
+LanguageLevel ApiExtractor::languageLevel() const
+{
+ return m_languageLevel;
+}
+
+void ApiExtractor::setLanguageLevel(const LanguageLevel languageLevel)
+{
+ m_languageLevel = languageLevel;
+}
+
#ifndef QT_NO_DEBUG_STREAM
template <class Container>
static void debugFormatSequence(QDebug &d, const char *key, const Container& c)
diff --git a/sources/shiboken2/ApiExtractor/apiextractor.h b/sources/shiboken2/ApiExtractor/apiextractor.h
index 702d3994c..674e5a742 100644
--- a/sources/shiboken2/ApiExtractor/apiextractor.h
+++ b/sources/shiboken2/ApiExtractor/apiextractor.h
@@ -36,6 +36,7 @@
#include "header_paths.h"
#include "typedatabase_typedefs.h"
#include "typesystem_typedefs.h"
+#include "clangparser/compilersupport.h"
#include <QStringList>
class AbstractMetaBuilder;
@@ -75,6 +76,8 @@ public:
void setLogDirectory(const QString& logDir);
bool setApiVersion(const QString& package, const QString& version);
void setDropTypeEntries(QString dropEntries);
+ LanguageLevel languageLevel() const;
+ void setLanguageLevel(const LanguageLevel languageLevel);
AbstractMetaEnumList globalEnums() const;
AbstractMetaFunctionList globalFunctions() const;
@@ -83,7 +86,6 @@ public:
AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const;
PrimitiveTypeEntryList primitiveTypes() const;
ContainerTypeEntryList containerTypes() const;
- QSet<QString> qtMetaTypeDeclaredTypeNames() const;
const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const;
const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const;
@@ -99,6 +101,7 @@ private:
HeaderPaths m_includePaths;
AbstractMetaBuilder* m_builder;
QString m_logDirectory;
+ LanguageLevel m_languageLevel = LanguageLevel::Default;
// disable copy
ApiExtractor(const ApiExtractor&);
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
index a6b6f2af3..5192e9e76 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
@@ -379,6 +379,27 @@ static QStringList parseArrayArgs(const CXType &type, QString *typeName)
return result;
}
+// Create qualified name "std::list<std::string>" -> ("std", "list<std::string>")
+static QStringList qualifiedName(const QString &t)
+{
+ QStringList result;
+ int end = t.indexOf(QLatin1Char('<'));
+ if (end == -1)
+ end = t.indexOf(QLatin1Char('('));
+ if (end == -1)
+ end = t.size();
+ int lastPos = 0;
+ while (true) {
+ const int nextPos = t.indexOf(colonColon(), lastPos);
+ if (nextPos < 0 || nextPos >= end)
+ break;
+ result.append(t.mid(lastPos, nextPos - lastPos));
+ lastPos = nextPos + 2;
+ }
+ result.append(t.right(t.size() - lastPos));
+ return result;
+}
+
TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
{
if (type.kind == CXType_Pointer) { // Check for function pointers, first.
@@ -439,7 +460,7 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
typeName = typeName.trimmed();
- typeInfo.setQualifiedName(typeName.split(colonColon()));
+ typeInfo.setQualifiedName(qualifiedName(typeName));
// 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types?
return typeInfo;
}
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
index ddafcdb04..301b4211e 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
@@ -196,11 +196,6 @@ static CXTranslationUnit createTranslationUnit(CXIndex index,
| CXTranslationUnit_Incomplete;
static const QByteArrayList defaultArgs = {
-#if defined(Q_CC_MSVC) && _MSC_VER > 1900
- "-std=c++1z", // Fixes constexpr errors in MSVC2017 library headers with Clang 4.1
-#else
- "-std=c++14", // ! otherwise, t.h is parsed as "C"
-#endif
#ifndef Q_OS_WIN
"-fPIC",
#endif
diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
index 655454898..820909713 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
@@ -29,17 +29,30 @@
#include "compilersupport.h"
#include "header_paths.h"
+#include <reporthandler.h>
+
#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
+#include <QtCore/QStandardPaths>
#include <QtCore/QStringList>
#include <QtCore/QVersionNumber>
+#include <clang-c/Index.h>
+
#include <string.h>
#include <algorithm>
#include <iterator>
namespace clang {
+QVersionNumber libClangVersion()
+{
+ return QVersionNumber(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR);
+}
+
static bool runProcess(const QString &program, const QStringList &arguments,
QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr)
{
@@ -106,9 +119,9 @@ static HeaderPaths gppInternalIncludePaths(const QString &compiler)
if (line.startsWith(QByteArrayLiteral("End of search list"))) {
isIncludeDir = false;
} else {
- HeaderPath headerPath(line.trimmed());
+ HeaderPath headerPath{line.trimmed(), HeaderType::System};
if (headerPath.path.endsWith(frameworkPath())) {
- headerPath.m_isFramework = true;
+ headerPath.type = HeaderType::FrameworkSystem;
headerPath.path.truncate(headerPath.path.size() - frameworkPath().size());
}
result.append(headerPath);
@@ -127,7 +140,8 @@ static void detectVulkan(HeaderPaths *headerPaths)
static const char *vulkanVariables[] = {"VULKAN_SDK", "VK_SDK_PATH"};
for (const char *vulkanVariable : vulkanVariables) {
if (qEnvironmentVariableIsSet(vulkanVariable)) {
- headerPaths->append(HeaderPath(qgetenv(vulkanVariable) + QByteArrayLiteral("/include")));
+ const QByteArray path = qgetenv(vulkanVariable) + QByteArrayLiteral("/include");
+ headerPaths->append(HeaderPath{path, HeaderType::System});
break;
}
}
@@ -154,6 +168,68 @@ static inline bool isRedHat74()
static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); }
#endif
+// The clang builtin includes directory is used to find the definitions for
+// intrinsic functions and builtin types. It is necessary to use the clang
+// includes to prevent redefinition errors. The default toolchain includes
+// should be picked up automatically by clang without specifying
+// them implicitly.
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+# define NEED_CLANG_BUILTIN_INCLUDES 1
+#else
+# define NEED_CLANG_BUILTIN_INCLUDES 0
+#endif
+
+#if NEED_CLANG_BUILTIN_INCLUDES
+static QString findClang()
+{
+ for (const char *envVar : {"LLVM_INSTALL_DIR", "CLANG_INSTALL_DIR"}) {
+ if (qEnvironmentVariableIsSet(envVar)) {
+ const QString path = QFile::decodeName(qgetenv(envVar));
+ if (QFileInfo::exists(path))
+ return path;
+ }
+ }
+ const QString llvmConfig =
+ QStandardPaths::findExecutable(QLatin1String("llvm-config"));
+ if (!llvmConfig.isEmpty()) {
+ QByteArray stdOut;
+ if (runProcess(llvmConfig, QStringList{QLatin1String("--prefix")}, &stdOut)) {
+ const QString path = QFile::decodeName(stdOut.trimmed());
+ if (QFileInfo::exists(path))
+ return path;
+ }
+ }
+ return QString();
+}
+
+static QString findClangBuiltInIncludesDir()
+{
+ // Find the include directory of the highest version.
+ const QString clangPath = findClang();
+ if (!clangPath.isEmpty()) {
+ QString candidate;
+ QVersionNumber lastVersionNumber(1, 0, 0);
+ QDir clangDir(clangPath + QLatin1String("/lib/clang"));
+ const QFileInfoList versionDirs =
+ clangDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ for (const QFileInfo &fi : versionDirs) {
+ const QString fileName = fi.fileName();
+ if (fileName.at(0).isDigit()) {
+ const QVersionNumber versionNumber = QVersionNumber::fromString(fileName.at(0));
+ if (!versionNumber.isNull() && versionNumber > lastVersionNumber) {
+ candidate = fi.absoluteFilePath();
+ lastVersionNumber = versionNumber;
+ }
+ }
+ }
+ if (!candidate.isEmpty())
+ return candidate + QStringLiteral("/include");
+ }
+ return QString();
+}
+#endif // NEED_CLANG_BUILTIN_INCLUDES
+
// Returns clang options needed for emulating the host compiler
QByteArrayList emulatedCompilerOptions()
{
@@ -168,16 +244,21 @@ QByteArrayList emulatedCompilerOptions()
#elif defined(Q_CC_GNU)
HeaderPaths headerPaths;
- // The clang builtin includes directory is used to find the definitions for intrinsic functions
- // and builtin types. It is necessary to use the clang includes to prevent redefinition errors.
- // The default toolchain includes should be picked up automatically by clang without specifying
- // them implicitly.
- QByteArray clangBuiltinIncludesDir(CLANG_BUILTIN_INCLUDES_DIR);
-
- if (!clangBuiltinIncludesDir.isEmpty()) {
- result.append(QByteArrayLiteral("-isystem"));
- result.append(clangBuiltinIncludesDir);
+#if NEED_CLANG_BUILTIN_INCLUDES
+ const QString clangBuiltinIncludesDir =
+ QDir::toNativeSeparators(findClangBuiltInIncludesDir());
+ if (clangBuiltinIncludesDir.isEmpty()) {
+ qCWarning(lcShiboken, "Unable to locate Clang's built-in include directory "
+ "(neither by checking the environment variables LLVM_INSTALL_DIR, CLANG_INSTALL_DIR "
+ " nor running llvm-config). This may lead to parse errors.");
+ } else {
+ qCInfo(lcShiboken, "CLANG builtins includes directory: %s",
+ qPrintable(clangBuiltinIncludesDir));
+ headerPaths.append(HeaderPath{QFile::encodeName(clangBuiltinIncludesDir),
+ HeaderType::System});
}
+#endif // NEED_CLANG_BUILTIN_INCLUDES
+
// Append the c++ include paths since Clang is unable to find <list> etc
// on RHEL 7.4 with g++ 6.3. A fix for this has been added to Clang 5.0,
// so, the code can be removed once Clang 5.0 is the minimum version.
@@ -193,10 +274,51 @@ QByteArrayList emulatedCompilerOptions()
#endif
detectVulkan(&headerPaths);
std::transform(headerPaths.cbegin(), headerPaths.cend(),
- std::back_inserter(result), [](const HeaderPath &p) {
- return HeaderPath::includeOption(p, true);
- });
+ std::back_inserter(result), HeaderPath::includeOption);
return result;
}
+LanguageLevel emulatedCompilerLanguageLevel()
+{
+#if defined(Q_CC_MSVC) && _MSC_VER > 1900
+ // Fixes constexpr errors in MSVC2017 library headers with Clang 4.1..5.X (0.45 == Clang 6).
+ if (libClangVersion() < QVersionNumber(0, 45))
+ return LanguageLevel::Cpp1Z;
+#endif // Q_CC_MSVC && _MSC_VER > 1900
+ return LanguageLevel::Cpp14; // otherwise, t.h is parsed as "C"
+}
+
+struct LanguageLevelMapping
+{
+ const char *option;
+ LanguageLevel level;
+};
+
+static const LanguageLevelMapping languageLevelMapping[] =
+{
+ {"c++11", LanguageLevel::Cpp11},
+ {"c++14", LanguageLevel::Cpp14},
+ {"c++17", LanguageLevel::Cpp17},
+ {"c++20", LanguageLevel::Cpp20},
+ {"c++1z", LanguageLevel::Cpp1Z}
+};
+
+const char *languageLevelOption(LanguageLevel l)
+{
+ for (const LanguageLevelMapping &m : languageLevelMapping) {
+ if (m.level == l)
+ return m.option;
+ }
+ return nullptr;
+}
+
+LanguageLevel languageLevelFromOption(const char *o)
+{
+ for (const LanguageLevelMapping &m : languageLevelMapping) {
+ if (!strcmp(m.option, o))
+ return m.level;
+ }
+ return LanguageLevel::Default;
+}
+
} // namespace clang
diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h
index 68d09f6f5..d9e213e73 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h
+++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h
@@ -31,10 +31,25 @@
#include <QtCore/QByteArrayList>
+QT_FORWARD_DECLARE_CLASS(QVersionNumber)
+
+enum class LanguageLevel {
+ Default,
+ Cpp11,
+ Cpp14,
+ Cpp17,
+ Cpp20,
+ Cpp1Z
+};
+
namespace clang {
+QVersionNumber libClangVersion();
QByteArrayList emulatedCompilerOptions();
+LanguageLevel emulatedCompilerLanguageLevel();
+const char *languageLevelOption(LanguageLevel l);
+LanguageLevel languageLevelFromOption(const char *);
} // namespace clang
#endif // COMPILERSUPPORT_H
diff --git a/sources/shiboken2/ApiExtractor/header_paths.h b/sources/shiboken2/ApiExtractor/header_paths.h
index 4681f14de..01d830921 100644
--- a/sources/shiboken2/ApiExtractor/header_paths.h
+++ b/sources/shiboken2/ApiExtractor/header_paths.h
@@ -33,30 +33,36 @@
#include <QList>
#include <QString>
+enum class HeaderType
+{
+ Standard,
+ System, // -isystem
+ Framework, // macOS framework path
+ FrameworkSystem // macOS framework system path
+};
+
class HeaderPath {
public:
- explicit HeaderPath(const QByteArray &p = QByteArray()) : path(p), m_isFramework(false) {}
- explicit HeaderPath(const QString &s = QString(), bool isFramework = false) :
- path(s.toLatin1()), m_isFramework(isFramework) {}
-
QByteArray path;
- bool m_isFramework; // macOS framework path
+ HeaderType type;
- static QByteArray includeOption(const HeaderPath &p, bool systemInclude = false)
+ static QByteArray includeOption(const HeaderPath &p)
{
QByteArray option;
-
- if (p.m_isFramework) {
- if (systemInclude)
- option = QByteArrayLiteral("-iframework");
- else
- option = QByteArrayLiteral("-F");
- } else if (systemInclude) {
- option = QByteArrayLiteral("-isystem");
- } else {
+ switch (p.type) {
+ case HeaderType::Standard:
option = QByteArrayLiteral("-I");
+ break;
+ case HeaderType::System:
+ option = QByteArrayLiteral("-isystem");
+ break;
+ case HeaderType::Framework:
+ option = QByteArrayLiteral("-F");
+ break;
+ case HeaderType::FrameworkSystem:
+ option = QByteArrayLiteral("-iframework");
+ break;
}
-
return option + p.path;
}
};
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
index 0af4905f4..60a699337 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
@@ -238,6 +238,20 @@ QString TypeInfo::toString() const
return tmp;
}
+QStringList TypeInfo::instantiationName() const
+{
+ QStringList result = m_qualifiedName;
+ if (const int argumentCount = m_arguments.size()) {
+ QString &last = result.last();
+ for (int i = 0; i < argumentCount; ++i) {
+ last += i ? QLatin1String(", ") : QLatin1String("< ");
+ last += m_arguments.at(i).toString();
+ }
+ last += QLatin1String(" >");
+ }
+ return result;
+}
+
bool TypeInfo::operator==(const TypeInfo &other) const
{
if (arrayElements().count() != other.arrayElements().count())
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h
index d0d7b677c..d93aa10d9 100644
--- a/sources/shiboken2/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h
@@ -98,6 +98,7 @@ QDebug operator<<(QDebug d, const CodeModel *m);
class TypeInfo
{
+ friend class TypeParser;
public:
TypeInfo() : flags(0), m_referenceType(NoReference) {}
@@ -184,6 +185,8 @@ public:
QString toString() const;
+ QStringList instantiationName() const;
+
static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs);
static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope);
diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
index ea506f3b5..8d869e3f9 100644
--- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
+++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
@@ -35,35 +35,37 @@
void TestTemplates::testTemplateWithNamespace()
{
- const char cppCode[] = "\n\
- template<typename T> struct QList {}; \n\
- struct Url {\n\
- void name();\n\
- };\n\
- namespace Internet {\n\
- struct Url{};\n\
- struct Bookmarks {\n\
- QList<Url> list();\n\
- };\n\
- }";
- const char xmlCode0[] = "\n\
- <typesystem package='Pakcage.Network'>\n\
- <value-type name='Url'/>\n\
- </typesystem>";
+ const char cppCode[] = R"CPP(
+template<typename T> struct QList {};
+struct Url {
+ void name();
+};
+namespace Internet {
+ struct Url{};
+ struct Bookmarks {
+ QList<Url> list();
+ };
+};
+)CPP";
+
+ const char xmlCode0[] = R"XML(
+<typesystem package='Package.Network'>
+ <value-type name='Url'/>
+</typesystem>)XML";
QTemporaryFile file;
QVERIFY(file.open());
file.write(xmlCode0);
file.close();
- QString xmlCode1 = QString::fromLatin1("\n\
- <typesystem package='Package.Internet'>\n\
- <load-typesystem name='%1' generate='no'/>\n\
- <container-type name='QList' type='list'/>\n\
- <namespace-type name='Internet' generate='no'/>\n\
- <value-type name='Internet::Url'/>\n\
- <value-type name='Internet::Bookmarks'/>\n\
- </typesystem>").arg(file.fileName());
+ QString xmlCode1 = QString::fromLatin1(R"XML(
+<typesystem package='Package.Internet'>
+ <load-typesystem name='%1' generate='no'/>
+ <container-type name='QList' type='list'/>
+ <namespace-type name='Internet' generate='no'/>
+ <value-type name='Internet::Url'/>
+ <value-type name='Internet::Bookmarks'/>
+</typesystem>)XML").arg(file.fileName());
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false));
QVERIFY(!builder.isNull());
@@ -79,26 +81,27 @@ void TestTemplates::testTemplateWithNamespace()
void TestTemplates::testTemplateOnContainers()
{
- const char cppCode[] = "\n\
- struct Base {};\n\
- template<typename T> struct QList {}; \n\
- namespace Namespace {\n\
- enum SomeEnum { E1, E2 };\n\
- template<SomeEnum type> struct A {\n\
- A<type> foo(const QList<A<type> >& a);\n\
- };\n\
- typedef A<E1> B;\n\
- }\n\
- ";
- const char xmlCode[] = "\n\
- <typesystem package=\"Package\">\n\
- <container-type name='QList' type='list'/>\n\
- <namespace-type name='Namespace'/>\n\
- <enum-type name='Namespace::SomeEnum'/>\n\
- <object-type name='Base'/>\n\
- <object-type name='Namespace::A' generate='no'/>\n\
- <object-type name='Namespace::B'/>\n\
- </typesystem>";
+ const char cppCode[] = R"CPP(
+struct Base {};
+template<typename T> struct QList {};
+namespace Namespace {
+ enum SomeEnum { E1, E2 };
+ template<SomeEnum type> struct A {
+ A<type> foo(const QList<A<type> >& a);
+ };
+ typedef A<E1> B;
+}
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package="Package">
+ <container-type name='QList' type='list'/>
+ <namespace-type name='Namespace'/>
+ <enum-type name='Namespace::SomeEnum'/>
+ <object-type name='Base'/>
+ <object-type name='Namespace::A' generate='no'/>
+ <object-type name='Namespace::B'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -124,18 +127,17 @@ void TestTemplates::testTemplateOnContainers()
void TestTemplates::testTemplateValueAsArgument()
{
- const char cppCode[] = "\n\
- template<typename T> struct List {};\n\
- void func(List<int> arg) {}\n\
- ";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <primitive-type name='int'/>\n\
- <container-type name='List' type='list'/>\n\
- <function signature='func(List&lt;int&gt;)'/>\n\
- </typesystem>\n\
- ";
+ const char cppCode[] = R"CPP(
+template<typename T> struct List {};
+void func(List<int> arg) {}
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <primitive-type name='int'/>
+ <container-type name='List' type='list'/>
+ <function signature='func(List&lt;int&gt;)'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -149,18 +151,17 @@ void TestTemplates::testTemplateValueAsArgument()
void TestTemplates::testTemplatePointerAsArgument()
{
- const char cppCode[] = "\n\
- template<typename T> struct List {};\n\
- void func(List<int>* arg) {}\n\
- ";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <primitive-type name='int'/>\n\
- <container-type name='List' type='list'/>\n\
- <function signature='func(List&lt;int&gt;*)'/>\n\
- </typesystem>\n\
- ";
+ const char cppCode[] = R"CPP(
+template<typename T> struct List {};
+void func(List<int>* arg) {}
+)CPP";
+
+ const char xmlCode[] = R"XML(
+ <typesystem package='Package'>
+ <primitive-type name='int'/>
+ <container-type name='List' type='list'/>
+ <function signature='func(List&lt;int&gt;*)'/>
+ </typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -174,18 +175,17 @@ void TestTemplates::testTemplatePointerAsArgument()
void TestTemplates::testTemplateReferenceAsArgument()
{
- const char cppCode[] = "\n\
- template<typename T> struct List {};\n\
- void func(List<int>& arg) {}\n\
- ";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <primitive-type name='int'/>\n\
- <container-type name='List' type='list'/>\n\
- <function signature='func(List&lt;int&gt;&amp;)'/>\n\
- </typesystem>\n\
- ";
+ const char cppCode[] = R"CPP(
+template<typename T> struct List {};
+void func(List<int>& arg) {}
+ )CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <primitive-type name='int'/>
+ <container-type name='List' type='list'/>
+ <function signature='func(List&lt;int&gt;&amp;)'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -199,19 +199,20 @@ void TestTemplates::testTemplateReferenceAsArgument()
void TestTemplates::testTemplateParameterFixup()
{
- const char cppCode[] = "\n\
- template<typename T>\n\
- struct List {\n\
- struct Iterator {};\n\
- void append(List l);\n\
- void erase(List::Iterator it);\n\
- };\n";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <container-type name='List' type='list'/>\n\
- <value-type name='List::Iterator'/>\n\
- </typesystem>\n";
+ const char cppCode[] = R"CPP(
+template<typename T>
+struct List {
+ struct Iterator {};
+ void append(List l);
+ void erase(List::Iterator it);
+};
+)CPP";
+
+ const char xmlCode[] = R"XML(
+ <typesystem package='Package'>
+ <container-type name='List' type='list'/>
+ <value-type name='List::Iterator'/>
+ </typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -234,26 +235,25 @@ void TestTemplates::testTemplateParameterFixup()
void TestTemplates::testInheritanceFromContainterTemplate()
{
- const char cppCode[] = "\n\
- template<typename T>\n\
- struct ListContainer {\n\
- inline void push_front(const T& t);\n\
- inline T& front();\n\
- };\n\
- struct FooBar {};\n\
- struct FooBars : public ListContainer<FooBar> {};\n\
- ";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <container-type name='ListContainer' type='list'/>\n\
- <value-type name='FooBar'/>\n\
- <value-type name='FooBars'>\n\
- <modify-function signature='push_front(FooBar)' remove='all'/>\n\
- <modify-function signature='front()' remove='all'/>\n\
- </value-type>\n\
- </typesystem>\n\
- ";
+ const char cppCode[] = R"CPP(
+template<typename T>
+struct ListContainer {
+ inline void push_front(const T& t);
+ inline T& front();
+};
+struct FooBar {};
+struct FooBars : public ListContainer<FooBar> {};
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <container-type name='ListContainer' type='list'/>
+ <value-type name='FooBar'/>
+ <value-type name='FooBars'>
+ <modify-function signature='push_front(FooBar)' remove='all'/>
+ <modify-function signature='front()' remove='all'/>
+ </value-type>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -271,25 +271,26 @@ void TestTemplates::testInheritanceFromContainterTemplate()
void TestTemplates::testTemplateInheritanceMixedWithForwardDeclaration()
{
- const char cppCode[] = "\n\
- enum SomeEnum { E1, E2 };\n\
- template<SomeEnum type> struct Future;\n\
- template<SomeEnum type>\n\
- struct A {\n\
- A();\n\
- void method();\n\
- friend struct Future<type>;\n\
- };\n\
- typedef A<E1> B;\n\
- template<SomeEnum type> struct Future {};\n\
- ";
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <enum-type name='SomeEnum'/>\n\
- <value-type name='A' generate='no'/>\n\
- <value-type name='B'/>\n\
- <value-type name='Future' generate='no'/>\n\
- </typesystem>";
+ const char cppCode[] = R"CPP(
+enum SomeEnum { E1, E2 };
+template<SomeEnum type> struct Future;
+template<SomeEnum type>
+struct A {
+ A();
+ void method();
+ friend struct Future<type>;
+};
+typedef A<E1> B;
+template<SomeEnum type> struct Future {};
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <enum-type name='SomeEnum'/>
+ <value-type name='A' generate='no'/>
+ <value-type name='B'/>
+ <value-type name='Future' generate='no'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -305,28 +306,29 @@ void TestTemplates::testTemplateInheritanceMixedWithForwardDeclaration()
void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration()
{
- const char cppCode[] = "\n\
- namespace Namespace {\n\
- enum SomeEnum { E1, E2 };\n\
- template<SomeEnum type> struct Future;\n\
- template<SomeEnum type>\n\
- struct A {\n\
- A();\n\
- void method();\n\
- friend struct Future<type>;\n\
- };\n\
- typedef A<E1> B;\n\
- template<SomeEnum type> struct Future {};\n\
- };\n\
- ";
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <namespace-type name='Namespace'/>\n\
- <enum-type name='Namespace::SomeEnum'/>\n\
- <value-type name='Namespace::A' generate='no'/>\n\
- <value-type name='Namespace::B'/>\n\
- <value-type name='Namespace::Future' generate='no'/>\n\
- </typesystem>";
+ const char cppCode[] = R"CPP(
+namespace Namespace {
+enum SomeEnum { E1, E2 };
+template<SomeEnum type> struct Future;
+template<SomeEnum type>
+struct A {
+ A();
+ void method();
+ friend struct Future<type>;
+};
+typedef A<E1> B;
+template<SomeEnum type> struct Future {};
+};
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <namespace-type name='Namespace'/>
+ <enum-type name='Namespace::SomeEnum'/>
+ <value-type name='Namespace::A' generate='no'/>
+ <value-type name='Namespace::B'/>
+ <value-type name='Namespace::Future' generate='no'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -342,28 +344,27 @@ void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclarati
void TestTemplates::testTypedefOfInstantiationOfTemplateClass()
{
- const char cppCode[] = "\n\
- namespace NSpace {\n\
- enum ClassType {\n\
- TypeOne\n\
- };\n\
- template<ClassType CLASS_TYPE>\n\
- struct BaseTemplateClass {\n\
- inline ClassType getClassType() const { CLASS_TYPE; }\n\
- };\n\
- typedef BaseTemplateClass<TypeOne> TypeOneClass;\n\
- }\n\
- ";
-
- const char xmlCode[] = "\n\
- <typesystem package='Package'>\n\
- <namespace-type name='NSpace'>\n\
- <enum-type name='ClassType'/>\n\
- <object-type name='BaseTemplateClass' generate='no'/>\n\
- <object-type name='TypeOneClass'/>\n\
- </namespace-type>\n\
- </typesystem>\n\
- ";
+ const char cppCode[] = R"CPP(
+namespace NSpace {
+enum ClassType {
+ TypeOne
+};
+template<ClassType CLASS_TYPE>
+struct BaseTemplateClass {
+ inline ClassType getClassType() const { CLASS_TYPE; }
+};
+typedef BaseTemplateClass<TypeOne> TypeOneClass;
+}
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Package'>
+ <namespace-type name='NSpace'>
+ <enum-type name='ClassType'/>
+ <object-type name='BaseTemplateClass' generate='no'/>
+ <object-type name='TypeOneClass'/>
+ </namespace-type>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
QVERIFY(!builder.isNull());
@@ -395,24 +396,25 @@ void TestTemplates::testTypedefOfInstantiationOfTemplateClass()
void TestTemplates::testContainerTypeIncompleteArgument()
{
- const char* cppCode ="\n\
- template<typename T>\n\
- class Vector {\n\
- void method(const Vector& vector);\n\
- Vector otherMethod();\n\
- };\n\
- template <typename T>\n\
- void Vector<T>::method(const Vector<T>& vector) {}\n\
- template <typename T>\n\
- Vector<T> Vector<T>::otherMethod() { return Vector<T>(); }\n\
- typedef Vector<int> IntVector;\n\
- ";
- const char* xmlCode = "\n\
- <typesystem package='Foo'>\n\
- <primitive-type name='int'/>\n\
- <container-type name='Vector' type='vector'/>\n\
- <value-type name='IntVector'/>\n\
- </typesystem>";
+ const char cppCode[] = R"CPP(
+template<typename T>
+class Vector {
+ void method(const Vector& vector);
+ Vector otherMethod();
+};
+template <typename T>
+void Vector<T>::method(const Vector<T>& vector) {}
+template <typename T>
+Vector<T> Vector<T>::otherMethod() { return Vector<T>(); }
+typedef Vector<int> IntVector;
+)CPP";
+
+ const char xmlCode[] = R"XML(
+<typesystem package='Foo'>
+ <primitive-type name='int'/>
+ <container-type name='Vector' type='vector'/>
+ <value-type name='IntVector'/>
+</typesystem>)XML";
QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true));
QVERIFY(!builder.isNull());
diff --git a/sources/shiboken2/ApiExtractor/tests/testutil.h b/sources/shiboken2/ApiExtractor/tests/testutil.h
index 3d2dd19ea..6152793f5 100644
--- a/sources/shiboken2/ApiExtractor/tests/testutil.h
+++ b/sources/shiboken2/ApiExtractor/tests/testutil.h
@@ -67,7 +67,7 @@ namespace TestUtil
tempSource.write(cppCode, qint64(strlen(cppCode)));
tempSource.close();
AbstractMetaBuilder *builder = new AbstractMetaBuilder;
- if (!builder->build(arguments, 0)) {
+ if (!builder->build(arguments)) {
delete builder;
return Q_NULLPTR;
}
diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp
index 9ef4be346..02c85421b 100644
--- a/sources/shiboken2/ApiExtractor/typeparser.cpp
+++ b/sources/shiboken2/ApiExtractor/typeparser.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include "typeparser.h"
+#include <codemodel.h>
#include <QtCore/QDebug>
#include <QtCore/QStack>
@@ -155,19 +156,12 @@ QString Scanner::msgParseError(const QString &why) const
+ QString(m_chars, m_length) + QStringLiteral("\": ") + why;
}
-static TypeParser::Info invalidInfo()
-{
- TypeParser::Info result;
- result.is_busted = true;
- return result;
-}
-
-TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
+TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
{
Scanner scanner(str);
- Info info;
- QStack<Info *> stack;
+ TypeInfo info;
+ QStack<TypeInfo *> stack;
stack.push(&info);
bool colon_prefix = false;
@@ -177,7 +171,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
Scanner::Token tok = scanner.nextToken(errorMessage);
while (tok != Scanner::NoToken) {
if (tok == Scanner::InvalidToken)
- return invalidInfo();
+ return TypeInfo();
// switch (tok) {
// case Scanner::StarToken: printf(" - *\n"); break;
@@ -197,16 +191,16 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
switch (tok) {
case Scanner::StarToken:
- ++stack.top()->indirections;
+ ++stack.top()->m_indirections;
break;
case Scanner::AmpersandToken:
- switch (stack.top()->referenceType) {
+ switch (stack.top()->referenceType()) {
case NoReference:
- stack.top()->referenceType = LValueReference;
+ stack.top()->setReferenceType(LValueReference);
break;
case LValueReference:
- stack.top()->referenceType = RValueReference;
+ stack.top()->setReferenceType(RValueReference);
break;
case RValueReference:
const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers"));
@@ -214,18 +208,18 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
*errorMessage = message;
else
qWarning().noquote().nospace() << message;
- return invalidInfo();
+ return TypeInfo();
}
break;
case Scanner::LessThanToken:
- stack.top()->template_instantiations << Info();
- stack.push(&stack.top()->template_instantiations.last());
+ stack.top()->m_arguments << TypeInfo();
+ stack.push(&stack.top()->m_arguments.last());
break;
case Scanner::CommaToken:
stack.pop();
- stack.top()->template_instantiations << Info();
- stack.push(&stack.top()->template_instantiations.last());
+ stack.top()->m_arguments << TypeInfo();
+ stack.push(&stack.top()->m_arguments.last());
break;
case Scanner::GreaterThanToken:
@@ -237,7 +231,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
break;
case Scanner::ConstToken:
- stack.top()->is_constant = true;
+ stack.top()->m_constant = true;
break;
case Scanner::OpenParenToken: // function pointers not supported
@@ -247,17 +241,17 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
*errorMessage = message;
else
qWarning().noquote().nospace() << message;
- return invalidInfo();
+ return TypeInfo();
}
case Scanner::Identifier:
if (in_array) {
array = scanner.identifier();
- } else if (colon_prefix || stack.top()->qualified_name.isEmpty()) {
- stack.top()->qualified_name << scanner.identifier();
+ } else if (colon_prefix || stack.top()->m_qualifiedName.isEmpty()) {
+ stack.top()->m_qualifiedName << scanner.identifier();
colon_prefix = false;
} else {
- stack.top()->qualified_name.last().append(QLatin1Char(' ') + scanner.identifier());
+ stack.top()->m_qualifiedName.last().append(QLatin1Char(' ') + scanner.identifier());
}
break;
@@ -267,7 +261,7 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
case Scanner::SquareEnd:
in_array = false;
- stack.top()->arrays += array;
+ stack.top()->m_arrayElements += array;
break;
@@ -280,83 +274,3 @@ TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage)
return info;
}
-
-QString TypeParser::Info::instantiationName() const
-{
- QString s(qualified_name.join(QLatin1String("::")));
- if (!template_instantiations.isEmpty()) {
- QStringList insts;
- for (const Info &info : template_instantiations)
- insts << info.toString();
- s += QLatin1String("< ") + insts.join(QLatin1String(", ")) + QLatin1String(" >");
- }
-
- return s;
-}
-
-QString TypeParser::Info::toString() const
-{
- QString s;
-
- if (is_constant)
- s += QLatin1String("const ");
- s += instantiationName();
- for (int i = 0; i < arrays.size(); ++i)
- s += QLatin1Char('[') + arrays.at(i) + QLatin1Char(']');
- s += QString(indirections, QLatin1Char('*'));
- switch (referenceType) {
- case NoReference:
- break;
- case LValueReference:
- s += QLatin1Char('&');
- break;
- case RValueReference:
- s += QLatin1String("&&");
- break;
- }
- return s;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-
-static void formatTypeInfo(QDebug &d, const TypeParser::Info &i)
-{
- if (i.is_busted) {
- d << "busted";
- return;
- }
-
- d << '"' << i.qualified_name << '"';
- if (!i.arrays.isEmpty()) {
- d << ", arrays=";
- for (const QString &a : i.arrays)
- d << '[' << a << ']';
- }
- if (!i.template_instantiations.isEmpty()) {
- d << ", template_instantiations=[";
- for (int t = 0, size = i.template_instantiations.size(); t < size; ++t) {
- if (t)
- d << ", ";
- formatTypeInfo(d, i.template_instantiations.at(t));
- }
- d << ']';
- }
- if (i.referenceType != NoReference)
- d << ", refType=" << i.referenceType;
- if (i.is_constant)
- d << ", [const]";
- if (i.indirections > 0)
- d << ", indirections=" << i.indirections;
-}
-
-QDebug operator<<(QDebug d, const TypeParser::Info &i)
-{
- QDebugStateSaver saver(d);
- d.noquote();
- d.nospace();
- d << "TypeParser::Info(";
- formatTypeInfo(d, i);
- d << ')';
- return d;
-}
-#endif // !QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken2/ApiExtractor/typeparser.h b/sources/shiboken2/ApiExtractor/typeparser.h
index e51a2c21a..3b538017a 100644
--- a/sources/shiboken2/ApiExtractor/typeparser.h
+++ b/sources/shiboken2/ApiExtractor/typeparser.h
@@ -31,36 +31,15 @@
#include "parser/codemodel_enums.h"
-#include <QtCore/QList>
#include <QtCore/QString>
-#include <QtCore/QStringList>
#include <QtCore/QVector>
-QT_FORWARD_DECLARE_CLASS(QDebug)
+class TypeInfo;
class TypeParser
{
public:
- struct Info
- {
- Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { }
- QStringList qualified_name;
- QStringList arrays;
- QVector<Info> template_instantiations;
- ReferenceType referenceType;
- uint is_constant : 1;
- uint is_busted : 1;
- uint indirections : 6;
-
- QString toString() const;
- QString instantiationName() const;
- };
-
- static Info parse(const QString &str, QString *errorMessage = Q_NULLPTR);
+ static TypeInfo parse(const QString &str, QString *errorMessage = nullptr);
};
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const TypeParser::Info &);
-#endif
-
#endif // TYPEPARSER_H
diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp
index 52f05ce5b..baaec6d30 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystem.cpp
@@ -1717,9 +1717,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
", was=%1").arg(topElement.type, 0, 16);
return false;
}
- QString signature = attributes[QLatin1String("signature")];
+ const QString originalSignature = attributes[QLatin1String("signature")];
- signature = TypeDatabase::normalizedSignature(signature);
+ QString signature = TypeDatabase::normalizedSignature(originalSignature);
if (signature.isEmpty()) {
m_error = QLatin1String("No signature for the added function");
return false;
@@ -1754,6 +1754,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
FunctionModification mod;
if (!mod.setSignature(m_currentSignature, &m_error))
return false;
+ mod.setOriginalSignature(originalSignature);
m_contextStack.top()->functionMods << mod;
}
break;
@@ -1763,9 +1764,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
", was=%1").arg(topElement.type, 0, 16);
return false;
}
- QString signature = attributes[QLatin1String("signature")];
+ const QString originalSignature = attributes[QLatin1String("signature")];
- signature = TypeDatabase::normalizedSignature(signature);
+ const QString signature = TypeDatabase::normalizedSignature(originalSignature);
if (signature.isEmpty()) {
m_error = QLatin1String("No signature for modified function");
return false;
@@ -1780,6 +1781,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
FunctionModification mod;
if (!mod.setSignature(signature, &m_error))
return false;
+ mod.setOriginalSignature(originalSignature);
m_currentSignature = signature;
QString access = attributes[QLatin1String("access")].toLower();
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index 79e60cd75..186c4b24d 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -356,6 +356,9 @@ struct FunctionModification: public Modification
bool setSignature(const QString &s, QString *errorMessage = nullptr);
QString signature() const { return m_signature.isEmpty() ? m_signaturePattern.pattern() : m_signature; }
+ void setOriginalSignature(const QString &s) { m_originalSignature = s; }
+ QString originalSignature() const { return m_originalSignature; }
+
QString toString() const;
QString association;
@@ -365,6 +368,7 @@ struct FunctionModification: public Modification
private:
QString m_signature;
+ QString m_originalSignature;
QRegularExpression m_signaturePattern;
bool m_thread = false;
bool m_allowThread = false;
diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt
index 852e14c1a..1af84fca1 100644
--- a/sources/shiboken2/CMakeLists.txt
+++ b/sources/shiboken2/CMakeLists.txt
@@ -113,46 +113,6 @@ endif()
message(STATUS "CLANG: ${CLANG_DIR}, ${CLANG_LIBRARY} detected by ${CLANG_DIR_SOURCE}")
-# Find highest version clang builtin includes folder to pass along to shiboken.
-set(CLANG_BUILTIN_INCLUDES_DIR_PREFIX ${CLANG_DIR}/lib/clang)
-file(GLOB CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES "${CLANG_BUILTIN_INCLUDES_DIR_PREFIX}/*")
-
-# Collect only directories, and not files, and only directories starting with a number.
-set(CLANG_BUILTIN_INCLUDES_DIR_VERSIONS "")
-foreach(candidate ${CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES})
- get_filename_component(candidate_basename ${candidate} NAME)
- if (IS_DIRECTORY ${candidate} AND ${candidate_basename} MATCHES "^[0-9]") # starts with number
- list(APPEND CLANG_BUILTIN_INCLUDES_DIR_VERSIONS ${candidate})
- endif()
-endforeach()
-
-# Sort in alphabetical order the list of version folders.
-list(SORT CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
-
-# Reverse it so the first element is the highest version.
-list(REVERSE CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
-
-message(STATUS
- "Found the following CLANG builtins includes directories: ${CLANG_BUILTIN_INCLUDES_DIR_VERSIONS} \
- Considered the following directories: ${CLANG_BUILTIN_INCLUDES_DIR_CANDIDATES}")
-if(CLANG_BUILTIN_INCLUDES_DIR_VERSIONS)
- # Get highest version.
- list(GET CLANG_BUILTIN_INCLUDES_DIR_VERSIONS 0 CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION)
- if (CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION)
- # Set the final variable to the full include path to pass along to shiboken.
- set(CLANG_BUILTIN_INCLUDES_DIR "${CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION}/include")
- endif()
-endif()
-
-message(STATUS "CLANG builtins includes directory chosen: ${CLANG_BUILTIN_INCLUDES_DIR}")
-
-# We don't exit with a hard error here, because it is uncertain whether all clang extra include
-# paths follow the same layout across OSes and distros.
-if (NOT CLANG_BUILTIN_INCLUDES_DIR)
- message(WARNING "No CLANG builtins includes directory found. This may lead to shiboken \
- execution failure.")
-endif()
-
set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include)
set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY})
diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp
index ded504905..1e2f03932 100644
--- a/sources/shiboken2/generator/generator.cpp
+++ b/sources/shiboken2/generator/generator.cpp
@@ -46,7 +46,6 @@ struct Generator::GeneratorPrivate {
// License comment
QString licenseComment;
QString packageName;
- int numGenerated;
QStringList instantiatedContainersNames;
QStringList instantiatedSmartPointerNames;
QVector<const AbstractMetaType *> instantiatedContainers;
@@ -56,7 +55,6 @@ struct Generator::GeneratorPrivate {
Generator::Generator() : m_d(new GeneratorPrivate)
{
- m_d->numGenerated = 0;
}
Generator::~Generator()
@@ -249,11 +247,6 @@ const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType*
return m_d->apiextractor->findAbstractMetaEnum(metaType);
}
-QSet< QString > Generator::qtMetaTypeDeclaredTypeNames() const
-{
- return m_d->apiextractor->qtMetaTypeDeclaredTypeNames();
-}
-
QString Generator::licenseComment() const
{
return m_d->licenseComment;
@@ -285,11 +278,6 @@ void Generator::setOutputDirectory(const QString &outDir)
m_d->outDir = outDir;
}
-int Generator::numGenerated() const
-{
- return m_d->numGenerated;
-}
-
inline void touchFile(const QString &filePath)
{
QFile toucher(filePath);
@@ -337,7 +325,6 @@ bool Generator::generateFileForContext(GeneratorContext &context)
break;
}
- ++m_d->numGenerated;
return true;
}
diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h
index e48f86f6f..010ed868c 100644
--- a/sources/shiboken2/generator/generator.h
+++ b/sources/shiboken2/generator/generator.h
@@ -143,37 +143,21 @@ public:
/// Optiosn used around the generator code
enum Option {
NoOption = 0x00000000,
- BoxedPrimitive = 0x00000001,
- ExcludeConst = 0x00000002,
- ExcludeReference = 0x00000004,
- UseNativeIds = 0x00000008,
-
- EnumAsInts = 0x00000010,
- SkipName = 0x00000020,
- NoCasts = 0x00000040,
- SkipReturnType = 0x00000080,
- OriginalName = 0x00000100,
- ShowStatic = 0x00000200,
- UnderscoreSpaces = 0x00000400,
- ForceEnumCast = 0x00000800,
- ArrayAsPointer = 0x00001000,
- VirtualCall = 0x00002000,
- SkipTemplateParameters = 0x00004000,
- SkipAttributes = 0x00008000,
- OriginalTypeDescription = 0x00010000,
- SkipRemovedArguments = 0x00020000,
- IncludeDefaultExpression = 0x00040000,
- NoReturnStatement = 0x00080000,
- NoBlockedSlot = 0x00100000,
-
- SuperCall = 0x00200000,
-
- GlobalRefJObject = 0x00100000,
-
- SkipDefaultValues = 0x00400000,
-
- WriteSelf = 0x00800000,
- ExcludeMethodConst = 0x01000000,
+ ExcludeConst = 0x00000001,
+ ExcludeReference = 0x00000002,
+
+ EnumAsInts = 0x00000004,
+ SkipName = 0x00000008,
+ SkipReturnType = 0x00000010,
+ OriginalName = 0x00000020,
+ VirtualCall = 0x00000040,
+ OriginalTypeDescription = 0x00000080,
+ SkipRemovedArguments = 0x00000100,
+
+ SkipDefaultValues = 0x00000200,
+
+ WriteSelf = 0x00000400,
+ ExcludeMethodConst = 0x00000800,
ForceValueType = ExcludeReference | ExcludeConst
};
@@ -241,9 +225,6 @@ public:
QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
const AbstractMetaClass *smartPointerClass) const;
- /// Returns the number of generated items
- int numGenerated() const;
-
/// Returns the generator's name. Used for cosmetic purposes.
virtual const char* name() const = 0;
@@ -284,9 +265,6 @@ public:
void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);
- // QtScript
- QSet<QString> qtMetaTypeDeclaredTypeNames() const;
-
/**
* Returns the license comment to be prepended to each source file generated.
*/
diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp
index 69f59a1b4..7ee43710e 100644
--- a/sources/shiboken2/generator/main.cpp
+++ b/sources/shiboken2/generator/main.cpp
@@ -46,8 +46,10 @@
#define PATH_SPLITTER ":"
#endif
+static inline QString languageLevelOption() { return QStringLiteral("language-level"); }
static inline QString includePathOption() { return QStringLiteral("include-paths"); }
static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); }
+static inline QString systemIncludePathOption() { return QStringLiteral("system-include-paths"); }
static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); }
static inline QString helpOption() { return QStringLiteral("help"); }
static const char helpHint[] = "Note: use --help or -h for more information.\n";
@@ -171,8 +173,10 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
QStringList includePaths;
QStringList frameworkIncludePaths;
+ QStringList systemIncludePaths;
QStringList typesystemPaths;
QStringList apiVersions;
+ QString languageLevel;
while (!projectFile.atEnd()) {
line = projectFile.readLine().trimmed();
@@ -193,8 +197,12 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
includePaths << QDir::toNativeSeparators(value);
else if (key == "framework-include-path")
frameworkIncludePaths << QDir::toNativeSeparators(value);
+ else if (key == "system-include-paths")
+ systemIncludePaths << QDir::toNativeSeparators(value);
else if (key == "typesystem-path")
typesystemPaths << QDir::toNativeSeparators(value);
+ else if (key == "language-level")
+ languageLevel = value;
else if (key == "api-version")
apiVersions << value;
else if (key == "header-file")
@@ -211,11 +219,17 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
if (!frameworkIncludePaths.isEmpty())
args.insert(frameworkIncludePathOption(),
frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER)));
+ if (!systemIncludePaths.isEmpty()) {
+ args.insert(systemIncludePathOption(),
+ systemIncludePaths.join(QLatin1String(PATH_SPLITTER)));
+ }
if (!typesystemPaths.isEmpty())
args.insert(typesystemPathOption(), typesystemPaths.join(QLatin1String(PATH_SPLITTER)));
if (!apiVersions.isEmpty())
args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|')));
+ if (!languageLevel.isEmpty())
+ args.insert(languageLevelOption(), languageLevel);
return true;
}
@@ -284,7 +298,7 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &
const QString option = arg.left(split);
const QString value = arg.mid(split + 1).trimmed();
if (option == includePathOption() || option == frameworkIncludePathOption()
- || option == typesystemPathOption()) {
+ || option == systemIncludePathOption() || option == typesystemPathOption()) {
addPathOptionValue(option, value, args);
} else {
args.insert(option, value);
@@ -297,10 +311,14 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &
addPathOptionValue(includePathOption(), arg.mid(1), args);
else if (arg.startsWith(QLatin1Char('F')))
addPathOptionValue(frameworkIncludePathOption(), arg.mid(1), args);
+ else if (arg.startsWith(QLatin1String("isystem")))
+ addPathOptionValue(systemIncludePathOption(), arg.mid(7), args);
else if (arg.startsWith(QLatin1Char('T')))
addPathOptionValue(typesystemPathOption(), arg.mid(1), args);
else if (arg == QLatin1String("h"))
args.insert(helpOption(), QString());
+ else if (arg.startsWith(QLatin1String("std=")))
+ args.insert(languageLevelOption(), arg.mid(4));
else
args.insert(arg, QString());
return;
@@ -338,6 +356,13 @@ static inline Generators shibokenGenerators()
return result;
}
+static inline QString languageLevelDescription()
+{
+ return QLatin1String("C++ Language level (c++11..c++17, default=")
+ + QLatin1String(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ + QLatin1Char(')');
+}
+
void printUsage()
{
QTextStream s(stdout);
@@ -358,6 +383,9 @@ void printUsage()
<< qMakePair(QLatin1String("-F") + pathSyntax, QString())
<< qMakePair(QLatin1String("framework-include-paths=") + pathSyntax,
QLatin1String("Framework include paths used by the C++ parser"))
+ << qMakePair(QLatin1String("-isystem") + pathSyntax, QString())
+ << qMakePair(QLatin1String("system-include-paths=") + pathSyntax,
+ QLatin1String("System include paths used by the C++ parser"))
<< qMakePair(QLatin1String("generator-set=<\"generator module\">"),
QLatin1String("generator-set to be used. e.g. qtdoc"))
<< qMakePair(QLatin1String("-h"), QString())
@@ -366,6 +394,8 @@ void printUsage()
<< qMakePair(QLatin1String("-I") + pathSyntax, QString())
<< qMakePair(QLatin1String("include-paths=") + pathSyntax,
QLatin1String("Include paths used by the C++ parser"))
+ << qMakePair(languageLevelOption() + QLatin1String("=, -std=<level>"),
+ languageLevelDescription())
<< qMakePair(QLatin1String("license-file=<license-file>"),
QLatin1String("File used for copyright headers of generated files"))
<< qMakePair(QLatin1String("no-suppress-warnings"),
@@ -414,6 +444,18 @@ static QString msgInvalidVersion(const QString &package, const QString &version)
+ QLatin1String("\" specified for package ") + package + QLatin1Char('.');
}
+static void parseIncludePathOption(const QString &option, HeaderType headerType,
+ ArgsHandler &args,
+ ApiExtractor &extractor)
+{
+ const QString path = args.removeArg(option);
+ if (!path.isEmpty()) {
+ const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER));
+ for (const QString &s : includePathListList)
+ extractor.addIncludePath(HeaderPath{QFile::encodeName(s), headerType});
+ }
+}
+
int main(int argc, char *argv[])
{
QElapsedTimer timer;
@@ -525,23 +567,12 @@ int main(int argc, char *argv[])
if (!path.isEmpty())
extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER)));
- path = argsHandler.removeArg(QLatin1String("include-paths"));
- if (!path.isEmpty()) {
- const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER));
- for (const QString &s : qAsConst(includePathListList)) {
- const bool isFramework = false;
- extractor.addIncludePath(HeaderPath(s, isFramework));
- }
- }
-
- path = argsHandler.removeArg(QLatin1String("framework-include-paths"));
- if (!path.isEmpty()) {
- const QStringList frameworkPathList = path.split(QLatin1String(PATH_SPLITTER));
- const bool isFramework = true;
- for (const QString &s : qAsConst(frameworkPathList)) {
- extractor.addIncludePath(HeaderPath(s, isFramework));
- }
- }
+ parseIncludePathOption(includePathOption(), HeaderType::Standard,
+ argsHandler, extractor);
+ parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework,
+ argsHandler, extractor);
+ parseIncludePathOption(systemIncludePathOption(), HeaderType::System,
+ argsHandler, extractor);
QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1"));
const QFileInfo cppFileNameFi(cppFileName);
@@ -574,6 +605,18 @@ int main(int argc, char *argv[])
argsHandler.removeArg(od.first);
}
+ const QString languageLevel = argsHandler.removeArg(languageLevelOption());
+ if (!languageLevel.isEmpty()) {
+ const QByteArray languageLevelBA = languageLevel.toLatin1();
+ const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
+ if (level == LanguageLevel::Default) {
+ std::cout << "Invalid argument for language level: \""
+ << languageLevelBA.constData() << "\"\n" << helpHint;
+ return EXIT_FAILURE;
+ }
+ extractor.setLanguageLevel(level);
+ }
+
if (!argsHandler.noArgs()) {
errorPrint(argsHandler.errorMessage());
std::cout << helpHint;
@@ -587,6 +630,7 @@ int main(int argc, char *argv[])
extractor.setCppFileName(cppFileNameFi.absoluteFilePath());
extractor.setTypeSystem(typeSystemFileName);
+
if (!extractor.run()) {
errorPrint(QLatin1String("Error running ApiExtractor."));
return EXIT_FAILURE;
diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
index 489d498f9..3ed278871 100644
--- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
@@ -521,7 +521,13 @@ QString QtXmlToSphinx::readFromLocations(const QStringList &locations, const QSt
const QString &identifier, QString *errorMessage)
{
QString result;
- const QString resolvedPath = resolveFile(locations, path);
+ QString resolvedPath;
+ if (path.endsWith(QLatin1String(".cpp"))) {
+ const QString pySnippet = path.left(path.size() - 3) + QLatin1String("py");
+ resolvedPath = resolveFile(locations, pySnippet);
+ }
+ if (resolvedPath.isEmpty())
+ resolvedPath = resolveFile(locations, path);
if (resolvedPath.isEmpty()) {
QTextStream(errorMessage) << "Could not resolve \"" << path << "\" in \""
<< locations.join(QLatin1String("\", \""));
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index bd654f17c..568b5fd27 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -1446,15 +1446,6 @@ void CppGenerator::writeCustomConverterRegister(QTextStream& s, const CustomConv
}
}
-void CppGenerator::writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar)
-{
- s << INDENT << "// Add user defined container conversion to type converter." << endl;
- QString typeName = fixedCppTypeName(container);
- QString toCpp = pythonToCppFunctionName(typeName, typeName);
- QString isConv = convertibleToCppFunctionName(typeName, typeName);
- writeAddPythonToCppConversion(s, converterVar, toCpp, isConv);
-}
-
void CppGenerator::writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType)
{
writeCppToPythonFunction(s, containerType);
@@ -1988,7 +1979,7 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData)
QString strArg;
AbstractMetaType* argType = arg->type();
if (isCString(argType)) {
- strArg = QLatin1String("\" SBK_STR_NAME \"");
+ strArg = QLatin1String("\" SBK_BYTES_NAME \"");
} else if (argType->isPrimitive()) {
const PrimitiveTypeEntry* ptp = reinterpret_cast<const PrimitiveTypeEntry*>(argType->typeEntry());
while (ptp->referencedTypeEntry())
@@ -2025,7 +2016,9 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData)
else if (strArg == QLatin1String("PyString"))
strArg = QLatin1String("str");
else if (strArg == QLatin1String("PyBytes"))
- strArg = QLatin1String("\" SBK_STR_NAME \"");
+ strArg = QLatin1String("\" SBK_BYTES_NAME \"");
+ else if (strArg == QLatin1String("PyByteArray"))
+ strArg = QLatin1String("bytearray");
else if (strArg == QLatin1String("PySequence"))
strArg = QLatin1String("list");
else if (strArg == QLatin1String("PyTuple"))
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h
index 4dbd31828..1b59bcda7 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.h
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h
@@ -64,14 +64,12 @@ private:
void writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass,
GeneratorContext &classContext);
void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar);
- void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar);
void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType);
void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
GeneratorContext &context);
void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, GeneratorContext &classContext);
- void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass);
void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads,
GeneratorContext &classContext);
void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData);
@@ -266,7 +264,6 @@ private:
GeneratorContext &context);
void writeRichCompareFunction(QTextStream &s, GeneratorContext &context);
- void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass);
void writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums);
void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum);
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 976b34141..80096cbf2 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -639,14 +639,6 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString arg
+ QLatin1String(", reinterpret_cast<SbkObject *>(") + argName + QLatin1String(")))");
}
-QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func, Options) const
-{
- if (func->ownerClass() && func->isConstructor())
- return func->ownerClass()->qualifiedCppName() + QLatin1Char('*');
-
- return translateTypeForWrapperMethod(func->type(), func->implementingClass());
-}
-
void ShibokenGenerator::writeToPythonConversion(QTextStream & s, const AbstractMetaType* type,
const AbstractMetaClass * /* context */,
const QString& argumentName)
@@ -876,17 +868,6 @@ static QString msgUnknownOperator(const AbstractMetaFunction* func)
static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); }
-QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func)
-{
- if (!func->isOperatorOverload())
- return QString();
- const QString pythonOp = pythonOperatorFunctionName(func->originalName());
- if (pythonOp == unknownOperator())
- qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func);
- return QLatin1String("Sbk") + func->ownerClass()->name()
- + QLatin1Char('_') + pythonOp;
-}
-
QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative)
{
if (toNative->sourceType())
@@ -1014,12 +995,6 @@ bool ShibokenGenerator::isPyInt(const AbstractMetaType* type)
return isPyInt(type->typeEntry());
}
-bool ShibokenGenerator::isPairContainer(const AbstractMetaType* type)
-{
- return type->isContainer()
- && static_cast<const ContainerTypeEntry *>(type->typeEntry())->type() == ContainerTypeEntry::PairContainer;
-}
-
bool ShibokenGenerator::isWrapperType(const TypeEntry* type)
{
if (type->isComplex())
@@ -1238,18 +1213,6 @@ QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type, Abstra
return type + QLatin1String("_Check");
}
-QString ShibokenGenerator::guessCPythonIsConvertible(const QString& type)
-{
- if (type == QLatin1String("PyTypeObject"))
- return QLatin1String("PyType_Check");
-
- AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type);
- if (metaType && !metaType->typeEntry()->isCustom())
- return cpythonIsConvertibleFunction(metaType);
-
- return type + QLatin1String("_Check");
-}
-
QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type,
bool /* genericNumberType */,
bool /* checkExact */)
@@ -2096,16 +2059,6 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa
code.replace(rep.first, rep.second);
}
-bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func)
-{
- CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
- for (const CodeSnip &snip : qAsConst(snips)) {
- if (snip.code().contains(QLatin1String("%CPPSELF")))
- return true;
- }
- return false;
-}
-
bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func)
{
CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode);
@@ -2296,20 +2249,6 @@ QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) co
return result.toLower() + QLatin1String("_python.h");
}
-QString ShibokenGenerator::extendedIsConvertibleFunctionName(const TypeEntry* targetType) const
-{
- QString p = targetType->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
- return QStringLiteral("ExtendedIsConvertible_%1_%2").arg(p, targetType->name());
-}
-
-QString ShibokenGenerator::extendedToCppFunctionName(const TypeEntry* targetType) const
-{
- QString p = targetType->targetLangPackage();
- p.replace(QLatin1Char('.'), QLatin1Char('_'));
- return QStringLiteral("ExtendedToCpp_%1_%2").arg(p, targetType->name());
-}
-
bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass)
{
@@ -2490,8 +2429,18 @@ QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(c
QMap<QString, AbstractMetaFunctionList> results;
for (AbstractMetaFunction *func : qAsConst(lst)) {
- if (isGroupable(func))
- results[func->name()].append(func);
+ if (isGroupable(func)) {
+ AbstractMetaFunctionList &list = results[func->name()];
+ // If there are virtuals methods in the mix (PYSIDE-570,
+ // QFileSystemModel::index(QString,int) and
+ // QFileSystemModel::index(int,int,QModelIndex)) override, make sure
+ // the overriding method of the most-derived class is seen first
+ // and inserted into the "seenSignatures" set.
+ if (func->isVirtual())
+ list.prepend(func);
+ else
+ list.append(func);
+ }
}
return results;
}
@@ -2539,25 +2488,6 @@ AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractM
return results;
}
-QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction)
-{
- AbstractMetaFunctionList overloads = getFunctionOverloads(metaFunction->ownerClass(), metaFunction->name());
-
- int minArgs = std::numeric_limits<int>::max();
- int maxArgs = 0;
- for (const AbstractMetaFunction* func : qAsConst(overloads)) {
- int numArgs = 0;
- const AbstractMetaArgumentList &arguments = func->arguments();
- for (const AbstractMetaArgument *arg : arguments) {
- if (!func->argumentRemoved(arg->argumentIndex() + 1))
- numArgs++;
- }
- maxArgs = std::max(maxArgs, numArgs);
- minArgs = std::min(minArgs, numArgs);
- }
- return qMakePair(minArgs, maxArgs);
-}
-
Generator::OptionDescriptions ShibokenGenerator::options() const
{
return OptionDescriptions()
@@ -2759,23 +2689,6 @@ bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadD
|| overloadData.hasArgumentWithDefaultValue();
}
-Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType* metaType)
-{
- // exclude const on Objects
- Options flags;
- const TypeEntry* type = metaType->typeEntry();
- bool isCStr = isCString(metaType);
- if (metaType->indirections() && !isCStr) {
- flags = ExcludeConst;
- } else if (metaType->isContainer()
- || (type->isPrimitive() && !isCStr)
- // const refs become just the value, but pure refs must remain pure.
- || (type->isValue() && metaType->isConstant() && metaType->referenceType() == LValueReference)) {
- flags = ExcludeConst | ExcludeReference;
- }
- return flags;
-}
-
QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg)
{
if (!arg->defaultValueExpression().isEmpty())
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
index 3271d741d..cb1bdd11f 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -106,11 +106,6 @@ public:
*/
AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName);
/**
- * Returns the minimun and maximun number of arguments which this function and all overloads
- * can accept. Arguments removed by typesystem are considered as well.
- */
- QPair<int, int> getMinMaxArguments(const AbstractMetaFunction* metaFunction);
- /**
* Write a function argument in the C++ in the text stream \p s.
* This function just call \code s << argumentString(); \endcode
* \param s text stream used to write the output.
@@ -197,14 +192,6 @@ public:
}
/**
- * Verifies if any of the function's code injections of the "target"
- * type needs the type system variable "%CPPSELF".
- * \param func the function to check
- * \return true if the function's target code snippets use "%CPPSELF"
- */
- bool injectedCodeUsesCppSelf(const AbstractMetaFunction* func);
-
- /**
* Verifies if any of the function's code injections of the "native"
* type needs the type system variable "%PYSELF".
* \param func the function to check
@@ -310,8 +297,6 @@ public:
static QString pythonRichCompareOperatorId(QString cppOpFuncName);
static QString pythonRichCompareOperatorId(const AbstractMetaFunction* func);
- static QString cpythonOperatorFunctionName(const AbstractMetaFunction* func);
-
static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative);
static QString fixedCppTypeName(const AbstractMetaType* type);
static QString fixedCppTypeName(const TypeEntry* type, QString typeName = QString());
@@ -321,7 +306,6 @@ public:
static bool isNumber(const AbstractMetaType* type);
static bool isPyInt(const TypeEntry* type);
static bool isPyInt(const AbstractMetaType* type);
- static bool isPairContainer(const AbstractMetaType* type);
/**
* Returns true if the type passed has a Python wrapper for it.
@@ -391,7 +375,6 @@ public:
QString cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false);
QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType = false);
QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg, bool genericNumberType = false);
- QString guessCPythonIsConvertible(const QString& type);
QString cpythonToCppConversionFunction(const AbstractMetaClass* metaClass);
QString cpythonToCppConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0);
@@ -425,15 +408,11 @@ public:
/// Returns the special cast function name, the function used to proper cast class with multiple inheritance.
QString cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass);
- QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
QString getFormatUnitString(const AbstractMetaFunction* func, bool incRef = false) const;
/// Returns the file name for the module global header. If no module name is provided the current will be used.
QString getModuleHeaderFileName(const QString& moduleName = QString()) const;
- QString extendedIsConvertibleFunctionName(const TypeEntry* targetType) const;
- QString extendedToCppFunctionName(const TypeEntry* targetType) const;
-
OptionDescriptions options() const override;
/// Returns true if the user enabled the so called "parent constructor heuristic".
@@ -479,12 +458,6 @@ public:
void writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor = QString());
/**
- * Helper function to return the flags to be used by a meta type when
- * it needs to write some converter code.
- */
- static Options getConverterOptions(const AbstractMetaType* metaType);
-
- /**
* Helper function to find for argument default value
*/
static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg);
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 0e2712ec8..ae6b2a68a 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -545,7 +545,7 @@ void init()
PyEval_InitThreads();
//Init private data
- Pep_Init();
+ Pep384_Init();
Shiboken::ObjectType::initPrivateData(SbkObject_TypeF());
@@ -828,7 +828,14 @@ Py_hash_t hash(PyObject* pyObj)
static void setSequenceOwnership(PyObject* pyObj, bool owner)
{
- if (PySequence_Check(pyObj)) {
+
+ bool has_length = true;
+ if (PySequence_Size(pyObj) < 0) {
+ PyErr_Clear();
+ has_length = false;
+ }
+
+ if (PySequence_Check(pyObj) && has_length) {
Py_ssize_t size = PySequence_Size(pyObj);
if (size > 0) {
std::list<SbkObject*> objs = splitPyObject(pyObj);
diff --git a/sources/shiboken2/libshiboken/pep384_issue33738.cpp b/sources/shiboken2/libshiboken/pep384_issue33738.cpp
new file mode 100644
index 000000000..ee085438e
--- /dev/null
+++ b/sources/shiboken2/libshiboken/pep384_issue33738.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// There is a bug in Python 3.6 that turned the Index_Check function
+// into a macro without taking care of the limited API.
+// This leads to the single problem that we don't have
+// access to PyLong_Type's nb_index field which is no heap type.
+// We cannot easily create this function by inheritance since it is
+// not inherited.
+//
+// Simple solution: Create the structure and write such a function.
+// Long term: Submit a patch to python.org .
+
+// Update: I did the long-term solution for python 3.7 in issue 33738.
+
+typedef struct {
+ /* Number implementations must check *both*
+ arguments for proper type and implement the necessary conversions
+ in the slot functions themselves. */
+
+ binaryfunc nb_add;
+ binaryfunc nb_subtract;
+ binaryfunc nb_multiply;
+ binaryfunc nb_remainder;
+ binaryfunc nb_divmod;
+ ternaryfunc nb_power;
+ unaryfunc nb_negative;
+ unaryfunc nb_positive;
+ unaryfunc nb_absolute;
+ inquiry nb_bool;
+ unaryfunc nb_invert;
+ binaryfunc nb_lshift;
+ binaryfunc nb_rshift;
+ binaryfunc nb_and;
+ binaryfunc nb_xor;
+ binaryfunc nb_or;
+ unaryfunc nb_int;
+ void *nb_reserved; /* the slot formerly known as nb_long */
+ unaryfunc nb_float;
+
+ binaryfunc nb_inplace_add;
+ binaryfunc nb_inplace_subtract;
+ binaryfunc nb_inplace_multiply;
+ binaryfunc nb_inplace_remainder;
+ ternaryfunc nb_inplace_power;
+ binaryfunc nb_inplace_lshift;
+ binaryfunc nb_inplace_rshift;
+ binaryfunc nb_inplace_and;
+ binaryfunc nb_inplace_xor;
+ binaryfunc nb_inplace_or;
+
+ binaryfunc nb_floor_divide;
+ binaryfunc nb_true_divide;
+ binaryfunc nb_inplace_floor_divide;
+ binaryfunc nb_inplace_true_divide;
+
+ unaryfunc nb_index;
+
+ binaryfunc nb_matrix_multiply;
+ binaryfunc nb_inplace_matrix_multiply;
+} PyNumberMethods;
+
+// temporary structure until we have a generator for the offsets
+typedef struct _oldtypeobject {
+ PyVarObject ob_base;
+ void *X01; // const char *tp_name;
+ void *X02; // Py_ssize_t tp_basicsize;
+ void *X03; // Py_ssize_t tp_itemsize;
+ void *X04; // destructor tp_dealloc;
+ void *X05; // printfunc tp_print;
+ void *X06; // getattrfunc tp_getattr;
+ void *X07; // setattrfunc tp_setattr;
+ void *X08; // PyAsyncMethods *tp_as_async;
+ void *X09; // reprfunc tp_repr;
+ PyNumberMethods *tp_as_number;
+
+} PyOldTypeObject;
+
+int PyIndex_Check(PyObject *obj)
+{
+ PyOldTypeObject *type = reinterpret_cast<PyOldTypeObject*>(Py_TYPE(obj));
+ return type->tp_as_number != NULL &&
+ type->tp_as_number->nb_index != NULL;
+}
+
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
index 2707d3716..dcd844ed6 100644
--- a/sources/shiboken2/libshiboken/pep384impl.cpp
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -449,94 +449,9 @@ check_PepTypeObject_valid(void)
#ifdef Py_LIMITED_API
-// This structure is only here because Python 3 has an error.
-// I will fix that.
-
-typedef struct {
- /* Number implementations must check *both*
- arguments for proper type and implement the necessary conversions
- in the slot functions themselves. */
-
- binaryfunc nb_add;
- binaryfunc nb_subtract;
- binaryfunc nb_multiply;
- binaryfunc nb_remainder;
- binaryfunc nb_divmod;
- ternaryfunc nb_power;
- unaryfunc nb_negative;
- unaryfunc nb_positive;
- unaryfunc nb_absolute;
- inquiry nb_bool;
- unaryfunc nb_invert;
- binaryfunc nb_lshift;
- binaryfunc nb_rshift;
- binaryfunc nb_and;
- binaryfunc nb_xor;
- binaryfunc nb_or;
- unaryfunc nb_int;
- void *nb_reserved; /* the slot formerly known as nb_long */
- unaryfunc nb_float;
-
- binaryfunc nb_inplace_add;
- binaryfunc nb_inplace_subtract;
- binaryfunc nb_inplace_multiply;
- binaryfunc nb_inplace_remainder;
- ternaryfunc nb_inplace_power;
- binaryfunc nb_inplace_lshift;
- binaryfunc nb_inplace_rshift;
- binaryfunc nb_inplace_and;
- binaryfunc nb_inplace_xor;
- binaryfunc nb_inplace_or;
-
- binaryfunc nb_floor_divide;
- binaryfunc nb_true_divide;
- binaryfunc nb_inplace_floor_divide;
- binaryfunc nb_inplace_true_divide;
-
- unaryfunc nb_index;
-
- binaryfunc nb_matrix_multiply;
- binaryfunc nb_inplace_matrix_multiply;
-} PyNumberMethods;
-
-// temporary structure until we have a generator for the offsets
-typedef struct _oldtypeobject {
- PyVarObject ob_base;
- void *X01; // const char *tp_name;
- void *X02; // Py_ssize_t tp_basicsize;
- void *X03; // Py_ssize_t tp_itemsize;
- void *X04; // destructor tp_dealloc;
- void *X05; // printfunc tp_print;
- void *X06; // getattrfunc tp_getattr;
- void *X07; // setattrfunc tp_setattr;
- void *X08; // PyAsyncMethods *tp_as_async;
- void *X09; // reprfunc tp_repr;
- PyNumberMethods *tp_as_number;
-
-} PyOldTypeObject;
-
-// There is a bug in Python 3.6 that turned the Index_Check function
-// into a macro without taking care of the limited API.
-// This leads to the single problem that we don't have
-// access to PyLong_Type's nb_index field which is no heap type.
-// We cannot easily create this function by inheritance since it is
-// not inherited.
-//
-// Simple solution: Create the structure and write such a function.
-// Long term: Submit a patch to python.org .
-
-unaryfunc
-PepType_nb_index(PyTypeObject *type)
-{
- return reinterpret_cast<PyOldTypeObject*>(type)->tp_as_number->nb_index;
-}
-
-int PyIndex_Check(PyObject *obj)
-{
- PyOldTypeObject *type = reinterpret_cast<PyOldTypeObject*>(Py_TYPE(obj));
- return type->tp_as_number != NULL &&
- type->tp_as_number->nb_index != NULL;
-}
+#if PY_VERSION_HEX < 0x03070000
+#include "pep384_issue33738.cpp"
+#endif
/*****************************************************************************
*
@@ -910,7 +825,7 @@ PepType_GetNameStr(PyTypeObject *type)
*/
void
-Pep_Init()
+Pep384_Init()
{
check_PepTypeObject_valid();
#ifdef Py_LIMITED_API
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
index fc0e3b40e..bfc603f69 100644
--- a/sources/shiboken2/libshiboken/pep384impl.h
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -133,11 +133,14 @@ typedef struct _peptypeobject {
} PepTypeObject;
-LIBSHIBOKEN_API unaryfunc PepType_nb_index(PyTypeObject *type);
-
+// This was a macro error in the limited API from the beginning.
+// It was fixed in Python 3.7 .
+// XXX The commit did go to master, but did not make it to 3.7, yet.
+//#if PY_VERSION_HEX < 0x03070000
+#if PY_VERSION_HEX < 0x03080000
#undef PyIndex_Check
-
LIBSHIBOKEN_API int PyIndex_Check(PyObject *obj);
+#endif
#undef PyObject_IS_GC
#define PyObject_IS_GC(o) (PyType_IS_GC(Py_TYPE(o)) && \
@@ -146,7 +149,6 @@ LIBSHIBOKEN_API int PyIndex_Check(PyObject *obj);
#else
#define PepTypeObject PyTypeObject
-#define PepType_nb_index(o) (PepType(o)->nb_index)
#endif // Py_LIMITED_API
struct SbkObjectTypePrivate;
@@ -309,7 +311,7 @@ typedef struct _methoddescr PyMethodDescrObject;
#ifdef Py_LIMITED_API
#define Py_TRASH_MIN_COMPATIBLE 0x03020400
-#define Py_TRASH_MAX_COMPATIBLE 0x030700A0
+#define Py_TRASH_MAX_COMPATIBLE 0x0307FFFF
#if PY_VERSION_HEX >= Py_TRASH_MIN_COMPATIBLE && \
PY_VERSION_HEX <= Py_TRASH_MAX_COMPATIBLE
@@ -383,7 +385,7 @@ LIBSHIBOKEN_API PyObject *PyRun_String(const char *, int, PyObject *, PyObject *
// But this is no problem as we check it's validity for every version.
#define PYTHON_BUFFER_VERSION_COMPATIBLE (PY_VERSION_HEX >= 0x03030000 && \
- PY_VERSION_HEX < 0X0306FFFF)
+ PY_VERSION_HEX < 0X0307FFFF)
#if !PYTHON_BUFFER_VERSION_COMPATIBLE
# error Please check the buffer compatibility for this python version!
#endif
@@ -564,7 +566,7 @@ extern LIBSHIBOKEN_API PyTypeObject *PepStaticMethod_TypePtr;
*
*/
-LIBSHIBOKEN_API void Pep_Init(void);
+LIBSHIBOKEN_API void Pep384_Init(void);
} // extern "C"
diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp
index d4d3ac899..f1be99a36 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.cpp
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -391,8 +391,11 @@ bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn)
{
assert(type);
assert(pyIn);
- if (!PySequence_Check(pyIn))
+ if (PySequence_Size(pyIn) < 0) {
+ // clear the error if < 0 which means no length at all
+ PyErr_Clear();
return false;
+ }
const Py_ssize_t size = PySequence_Size(pyIn);
for (Py_ssize_t i = 0; i < size; ++i) {
if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type))
diff --git a/sources/shiboken2/libshiboken/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h
index 5fe364a29..a26c318d1 100644
--- a/sources/shiboken2/libshiboken/sbkpython.h
+++ b/sources/shiboken2/libshiboken/sbkpython.h
@@ -76,7 +76,6 @@
#define SbkNumber_Check(X) \
(PyNumber_Check(X) && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__")))
#define SBK_NB_BOOL(x) (x).nb_nonzero
- #define SBK_STR_NAME "str"
#define SBK_PyMethod_New(X, Y) PyMethod_New(X, Y, reinterpret_cast<PyObject *>(Py_TYPE(Y)))
#define Py_hash_t long
diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp
index b92674383..6ca35f12e 100644
--- a/sources/shiboken2/libshiboken/sbkstring.cpp
+++ b/sources/shiboken2/libshiboken/sbkstring.cpp
@@ -99,18 +99,24 @@ const char* toCString(PyObject* str, Py_ssize_t* len)
{
if (str == Py_None)
return NULL;
-#ifdef IS_PY3K
if (PyUnicode_Check(str)) {
if (len) {
// We need to encode the unicode string into utf8 to know the size of returned char*.
Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str));
*len = PyBytes_GET_SIZE(uniStr.object());
}
+#ifdef IS_PY3K
// Return unicode from str instead of uniStr, because the lifetime of the returned pointer
// depends on the lifetime of str.
return _PepUnicode_AsString(str);
- }
+#else
+ str = PyUnicode_AsUTF8String(str);
+ if (str == NULL) {
+ return NULL;
+ }
+ return PyString_AsString(str);
#endif
+ }
if (PyBytes_Check(str)) {
if (len)
*len = PyBytes_GET_SIZE(str);
diff --git a/sources/shiboken2/libshiboken/sbkstring.h b/sources/shiboken2/libshiboken/sbkstring.h
index d437f1c77..a6b5fbeed 100644
--- a/sources/shiboken2/libshiboken/sbkstring.h
+++ b/sources/shiboken2/libshiboken/sbkstring.h
@@ -44,9 +44,9 @@
#include "shibokenmacros.h"
#if PY_MAJOR_VERSION >= 3
- #define SBK_STR_NAME "unicode"
+ #define SBK_BYTES_NAME "bytes"
#else
- #define SBK_STR_NAME "str"
+ #define SBK_BYTES_NAME "str"
#endif
namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp
index afb3f4040..94c667598 100644
--- a/sources/shiboken2/libshiboken/voidptr.cpp
+++ b/sources/shiboken2/libshiboken/voidptr.cpp
@@ -55,8 +55,13 @@ typedef struct {
PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- SbkVoidPtrObject *self =
- reinterpret_cast<SbkVoidPtrObject *>(PepType(type)->tp_alloc);
+ // PYSIDE-560: It is much safer to first call a function and then do a
+ // type cast than to do everything in one line. The bad construct looked
+ // like this, actual call forgotten:
+ // SbkVoidPtrObject *self =
+ // reinterpret_cast<SbkVoidPtrObject *>(PepType(type)->tp_alloc);
+ PyObject *ob = PepType(type)->tp_alloc(type, 0);
+ SbkVoidPtrObject *self = reinterpret_cast<SbkVoidPtrObject *>(ob);
if (self != 0) {
self->cptr = 0;
diff --git a/sources/shiboken2/tests/dumpcodemodel/main.cpp b/sources/shiboken2/tests/dumpcodemodel/main.cpp
index 997e13511..e132c97b3 100644
--- a/sources/shiboken2/tests/dumpcodemodel/main.cpp
+++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp
@@ -28,6 +28,7 @@
#include <abstractmetabuilder_p.h>
#include <parser/codemodel.h>
+#include <clangparser/compilersupport.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QCommandLineOption>
@@ -40,6 +41,13 @@
#include <algorithm>
#include <iterator>
+static inline QString languageLevelDescription()
+{
+ return QLatin1String("C++ Language level (c++11..c++17, default=")
+ + QLatin1String(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ + QLatin1Char(')');
+}
+
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
@@ -52,6 +60,10 @@ int main(int argc, char **argv)
QCommandLineOption verboseOption(QStringLiteral("d"),
QStringLiteral("Display verbose output about types"));
parser.addOption(verboseOption);
+ QCommandLineOption languageLevelOption(QStringLiteral("std"),
+ languageLevelDescription(),
+ QStringLiteral("level"));
+ parser.addOption(languageLevelOption);
parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("C++ source file"));
parser.process(app);
@@ -62,7 +74,19 @@ int main(int argc, char **argv)
QByteArrayList arguments;
std::transform(positionalArguments.cbegin(), positionalArguments.cend(),
std::back_inserter(arguments), QFile::encodeName);
- const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, 0);
+
+ LanguageLevel level = LanguageLevel::Default;
+ if (parser.isSet(languageLevelOption)) {
+ const QByteArray value = parser.value(languageLevelOption).toLatin1();
+ level = clang::languageLevelFromOption(value.constData());
+ if (level == LanguageLevel::Default) {
+ std::cerr << "Invalid value \"" << value.constData()
+ << "\" for language level option.\n";
+ return -2;
+ }
+ }
+
+ const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, level, 0);
if (dom.isNull()) {
QString message = QLatin1String("Unable to parse ") + positionalArguments.join(QLatin1Char(' '));
std::cerr << qPrintable(message) << '\n';