diff options
Diffstat (limited to 'sources')
27 files changed, 683 insertions, 396 deletions
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index cc63c0b7a..d23f90121 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -4395,8 +4395,8 @@ s1.addTransition(button.clicked, s1h)</code> <suppress-warning text="enum 'PM_CbaIconHeight' does not have a type entry or is not an enum" /> <!-- TODO: this need be removed --> - <suppress-warning text="skipping function '*', unmatched return type '*'"/> - <suppress-warning text="skipping function '*', unmatched type '*"/> + <suppress-warning text="^skipping function '.*', unmatched return type '.*$"/> + <suppress-warning text="^skipping function '.*', unmatched type '.*$"/> <suppress-warning text="enum 'q_static_assert_result39' does not have a type entry or is not an enum"/> <suppress-warning text="horribly broken type ''"/> diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml index eee22b55c..b679abc87 100644 --- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml +++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml @@ -97,21 +97,21 @@ <rejection class="*" function-name="d_func"/> <rejection class="*" field-name="d_ptr"/> <rejection class="*" field-name="d"/> - <rejection class="^QOpenGL.*$" argument-type="^GLboolean( const)?\*$"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?GLboolean ?\*$"/> <rejection class="^QOpenGL.*$" argument-type="^GLchar\*$"/> - <rejection class="^QOpenGL.*$" argument-type="GLchar *const const*"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?GLchar ?\*(const)?\*$"/> <rejection class="^QOpenGL.*$" argument-type="^char\*$"/> - <rejection class="^QOpenGL.*$" argument-type="^char( const)?\*\*$"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?char ?\*\*$"/> <rejection class="^QOpenGL.*$" argument-type="GLintptr"/> <rejection class="^QOpenGL.*$" argument-type="GLsizeiptr"/> <rejection class="^QOpenGL.*$" argument-type="GLsync"/> <rejection class="^QOpenGL.*$" argument-type="^GLubyte( const)?\*$"/> - <rejection class="^QOpenGL.*$" argument-type="^QMatrix.x.( const)?\*$"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?QMatrix.x. ?\*$"/> <rejection class="^QOpenGL.*$" argument-type="qopengl_GLintptr"/> <rejection class="^QOpenGL.*$" argument-type="qopengl_GLsizeiptr"/> <rejection class="^QOpenGL.*$" argument-type="QOpenGLTextureHelper*"/> - <rejection class="^QOpenGL.*$" argument-type="^QVector.D( const)?\*$"/> - <rejection class="^QOpenGL.*$" argument-type="^void( const)?\*\*$"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?QVector.D ?\*$"/> + <rejection class="^QOpenGL.*$" argument-type="^(const )?void ?\*\*$"/> <!-- Event classes have a lot of non-documented protected fields, those fields @@ -668,7 +668,7 @@ %0 = new %TYPE(QPixmap::fromImage(%1)); </inject-code> </add-function> - <modify-function signature="QPixmap(const char*[])"> + <modify-function signature="QPixmap(const char*const[])"> <modify-argument index="1"> <replace-type modified-type="PySequence" /> </modify-argument> @@ -897,7 +897,7 @@ <modify-function signature="QImage(const uchar*,int,int,QImage::Format,QImageCleanupFunction,void*)" remove="all" /> <!-- ### --> - <modify-function signature="QImage(const char*[])"> + <modify-function signature="QImage(const char*const[])"> <modify-argument index="1"> <replace-type modified-type="PySequence" /> </modify-argument> diff --git a/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml b/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml index ea5c24cd3..d04d2f674 100644 --- a/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml +++ b/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml @@ -59,16 +59,16 @@ <rejection class="QGLColormap::QGLColormapData"/> <rejection class="QGLContext" field-name="currentCtx"/> - <rejection class="^QGL.*$" argument-type="^GLboolean( const)?\*$"/> - <rejection class="^QGL.*$" argument-type="^GLchar( const)?\*$"/> - <rejection class="^QGL.*$" argument-type="GLchar *const const*"/> - <rejection class="^QGL.*$" argument-type="^GLenum( const)?\*$"/> - <rejection class="^QGL.*$" argument-type="^GLfloat( const)?\*$"/> - <rejection class="^QGL.*$" argument-type="^GLfloat( const)?\[.*$"/> - <rejection class="^QGL.*$" argument-type="^GLdouble( const)?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLboolean ?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLchar ?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLchar ?\*const"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLenum ?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLfloat ?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLfloat ?\[.*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLdouble ?\*$"/> <rejection class="^QGL.*$" argument-type="GLintptr"/> - <rejection class="^QGL.*$" argument-type="^GLint64( const)?\*$"/> - <rejection class="^QGL.*$" argument-type="^GLsizei( const)?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLint64 ?\*$"/> + <rejection class="^QGL.*$" argument-type="^(const )?GLsizei ?\*$"/> <namespace-type name="QGL"> <enum-type name="FormatOption" flags="FormatOptions" force-integer="yes"/> @@ -683,16 +683,7 @@ </inject-code> </modify-function> - <!-- ### TODO: must evaluate if anything other than removal should be done. --> - <modify-function signature="setAttributeArray(int,const GLfloat*,int,int)" remove="all" /> - <modify-function signature="setAttributeArray(const char*,const GLfloat*,int,int)" remove="all" /> - <modify-function signature="setUniformValueArray(int,const GLfloat*,int,int)" remove="all" /> - <modify-function signature="setUniformValueArray(const char*,const GLfloat*,int,int)" remove="all" /> - <!-- ### --> - <!-- ### Use QMatrixZxY overloads --> - <modify-function signature="setAttributeValue(int,const GLfloat*,int,int)" remove="all" /> - <modify-function signature="setAttributeValue(const char*,const GLfloat*,int,int)" remove="all" /> <modify-function signature="setAttributeArray(int,GLenum,const void*,int,int)" remove="all" since="4.7" /> <modify-function signature="setAttributeArray(const char*,GLenum,const void*,int,int)" remove="all" since="4.7" /> <!-- ### --> diff --git a/sources/pyside2/PySide2/QtQml/typesystem_qml.xml b/sources/pyside2/PySide2/QtQml/typesystem_qml.xml index 4ca776e11..5103b9218 100644 --- a/sources/pyside2/PySide2/QtQml/typesystem_qml.xml +++ b/sources/pyside2/PySide2/QtQml/typesystem_qml.xml @@ -158,7 +158,7 @@ <enum-type name="Status" /> </object-type> <object-type name="QQmlIncubationController"> - <modify-function signature="incubateWhile(bool volatile*,int)" allow-thread="yes"> + <modify-function signature="incubateWhile(volatile bool*,int)" allow-thread="yes"> <modify-argument index="1"> <!-- The replace type is needed to use the VolatileBool_Check macro instead of a template conversion function with "volatile bool" as argument. --> diff --git a/sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml b/sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml index f4e690874..2ac150807 100644 --- a/sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml +++ b/sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml @@ -101,7 +101,7 @@ <modify-function signature="kind()const" remove="all" /> <modify-function signature="isDeepEqual(const QXmlNodeModelIndex&)const" remove="all" /> <modify-function signature="compareOrder(const QXmlNodeModelIndex &)const" remove="all" /> - <modify-function signature="sendNamespaces(QAbstractXmlReceiver*)const" remove="all" /> + <modify-function signature="sendNamespaces(QAbstractXmlReceiver*const)const" remove="all" /> <modify-function signature="namespaceBindings()const" remove="all" /> <modify-function signature="namespaceForPrefix(QXmlName::PrefixCode)const" remove="all" /> <modify-function signature="stringValue()const" remove="all" /> diff --git a/sources/pyside2/pyside_version.py b/sources/pyside2/pyside_version.py index 789812464..a883bab96 100644 --- a/sources/pyside2/pyside_version.py +++ b/sources/pyside2/pyside_version.py @@ -38,16 +38,10 @@ ############################################################################# major_version = "5" -minor_version = "11" -patch_version = "1" - -# For example: "a", "b", "rc" -# (which means "alpha", "beta", "release candidate"). -# An empty string means the generated package will be an official release. -pre_release_version_type = "a" - -# For example: "1", "2" (which means "beta1", "beta2", if type is "b"). -pre_release_version = "1" +minor_version = "12" +patch_version = "0" +pre_release_version_type = "a" # e.g. "a", "b", "rc". +pre_release_version = "1" # e.g "1", "2", (which means "beta1", "beta2", if type is "b") if __name__ == '__main__': # Used by CMake. diff --git a/sources/pyside2/tests/CMakeLists.txt b/sources/pyside2/tests/CMakeLists.txt index 2386950e9..bed2d7cc1 100644 --- a/sources/pyside2/tests/CMakeLists.txt +++ b/sources/pyside2/tests/CMakeLists.txt @@ -46,7 +46,7 @@ else() set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT} WILL_FAIL ${EXPECT_TO_FAIL} - ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH};PYSIDE_DISABLE_INTERNAL_QT_CONF=1;QT_NO_GLIB=1") + ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH};PYSIDE_DISABLE_INTERNAL_QT_CONF=1;QT_NO_GLIB=1;QT_MAC_WANTS_LAYER=0") endmacro() if (NOT DISABLE_QtCore AND NOT DISABLE_QtGui AND NOT DISABLE_QtWidgets) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 84c116708..4105b4378 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -422,7 +422,7 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, TypeEntry* entry = types->findType(qualifiedName); if (entry) { if (isQObject(dom, qualifiedName) && entry->isComplex()) - ((ComplexTypeEntry*) entry)->setQObject(true); + static_cast<ComplexTypeEntry *>(entry)->setQObject(true); } } @@ -616,7 +616,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) } } } else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) { - const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier(); + const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier(); AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); bool enumFound = false; @@ -1014,7 +1014,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt AbstractMetaClass *metaClass = new AbstractMetaClass; metaClass->setTypeDef(true); metaClass->setTypeEntry(type); - metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon())); + metaClass->setBaseClassNames(QStringList(typeDef->type().toString())); *metaClass += AbstractMetaAttributes::Public; // Set the default include file name @@ -1803,7 +1803,8 @@ static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem return result; } -static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n) +static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n, + const QString &why) { QString result; QTextStream str(&result); @@ -1811,23 +1812,16 @@ static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, in << (n + 1); if (!arg->name().isEmpty()) str << " \"" << arg->name() << '"'; + str << ": " << why; return result; } -static inline QString msgUnmatchedReturnType(const FunctionModelItem &functionItem) +static inline QString msgUnmatchedReturnType(const FunctionModelItem &functionItem, + const QString &why) { return QLatin1String("unmatched return type '") - + functionItem->type().toString() + QLatin1Char('\''); -} - -static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n) -{ - QString result; - QTextStream str(&result); - str << "'void' encountered at parameter #" << (n + 1); - if (!arg->name().isEmpty()) - str << " \"" << arg->name() << '"'; - return result; + + functionItem->type().toString() + + QLatin1String("': ") + why; } static QString msgSkippingFunction(const FunctionModelItem &functionItem, @@ -1937,11 +1931,16 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) { m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); return 0; - } - else if (TypeDatabase::instance()->isFunctionRejected(className, - functionSignature(functionItem), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); - return 0; + } else { + const QString &signature = functionSignature(functionItem); + const bool rejected = + TypeDatabase::instance()->isFunctionRejected(className, signature, + &rejectReason); + qCDebug(lcShiboken).nospace().noquote() << __FUNCTION__ + << ": Checking rejection for signature \"" + << signature << "\" for " << className << ": " << rejected; + if (rejected) + return nullptr; } if (functionItem->isFriend()) @@ -1987,6 +1986,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel else *metaFunction += AbstractMetaAttributes::Protected; + QString errorMessage; switch (metaFunction->functionType()) { case AbstractMetaFunction::DestructorFunction: break; @@ -2005,9 +2005,9 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel AbstractMetaType *type = nullptr; if (!returnType.isVoid()) { - type = translateType(returnType); + type = translateType(returnType, true, &errorMessage); if (!type) { - const QString reason = msgUnmatchedReturnType(functionItem); + const QString reason = msgUnmatchedReturnType(functionItem, errorMessage); qCWarning(lcShiboken, "%s", qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); @@ -2041,7 +2041,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel return nullptr; } - AbstractMetaType *metaType = translateType(arg->type()); + AbstractMetaType *metaType = translateType(arg->type(), true, &errorMessage); if (!metaType) { // If an invalid argument has a default value, simply remove it if (arg->defaultValue()) { @@ -2058,18 +2058,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel break; } Q_ASSERT(metaType == 0); - const QString reason = msgUnmatchedParameterType(arg, i); - qCWarning(lcShiboken, "%s", - qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); - const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn - + QLatin1String(": ") + reason; - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); - delete metaFunction; - return nullptr; - } - - if (metaType == Q_NULLPTR) { - const QString reason = msgVoidParameterType(arg, i); + const QString reason = msgUnmatchedParameterType(arg, i, errorMessage); qCWarning(lcShiboken, "%s", qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason))); const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn @@ -2211,15 +2200,17 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const AddedFunction: QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName); - if (candidates.isEmpty()) - qFatal(qPrintable(QString(msg + QLatin1String("Declare it in the type system using the proper <*-type> tag."))), NULL); + if (candidates.isEmpty()) { + qFatal("%sDeclare it in the type system using the proper <*-type> tag.", + qPrintable(msg)); + } msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"); candidates.sort(); for (const QString& candidate : qAsConst(candidates)) { msg += QLatin1String(" ") + candidate + QLatin1Char('\n'); } - qFatal(qPrintable(msg), NULL); + qFatal("%s", qPrintable(msg)); } AbstractMetaType *metaType = new AbstractMetaType; @@ -2250,44 +2241,76 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC return type; } +static QString msgUnableToTranslateType(const QString &t, const QString &why) +{ + return QLatin1String("Unable to translate type \"") + + t + QLatin1String("\": ") + why; +} + +static inline QString msgUnableToTranslateType(const TypeInfo &typeInfo, + const QString &why) +{ + return msgUnableToTranslateType(typeInfo.toString(), why); +} + +static inline QString msgCannotFindTypeEntry(const QString &t) +{ + return QLatin1String("Cannot find type entry for \"") + t + QLatin1String("\"."); +} + +static inline QString msgCannotTranslateTemplateArgument(int i, + const TypeInfo &typeInfo, + const QString &why) +{ + QString result; + QTextStream(&result) << "Unable to translate template argument " + << (i + 1) << typeInfo.toString() << ": " << why; + return result; +} + AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - bool resolveType) + bool resolveType, + QString *errorMessage) +{ + return translateTypeStatic(_typei, m_currentClass, this, resolveType, errorMessage); +} + +AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, + AbstractMetaClass *currentClass, + AbstractMetaBuilderPrivate *d, + bool resolveType, + QString *errorMessageIn) { // 1. Test the type info without resolving typedefs in case this is present in the // type system - TypeInfo typei; if (resolveType) { - if (AbstractMetaType *resolved = translateType(_typei, false)) + if (AbstractMetaType *resolved = translateTypeStatic(_typei, currentClass, d, false, errorMessageIn)) return resolved; } - if (!resolveType) { - typei = _typei; - } else { + TypeInfo typeInfo = _typei; + if (resolveType) { // Go through all parts of the current scope (including global namespace) // to resolve typedefs. The parser does not properly resolve typedefs in // the global scope when they are referenced from inside a namespace. // This is a work around to fix this bug since fixing it in resolveType // seemed non-trivial - int i = m_scopes.size() - 1; + int i = d ? d->m_scopes.size() - 1 : -1; while (i >= 0) { - typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)); - if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon())) + typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--)); + if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon())) break; } } - if (typei.isFunctionPointer()) + if (typeInfo.isFunctionPointer()) { + if (errorMessageIn) + *errorMessageIn = msgUnableToTranslateType(_typei, QLatin1String("Unsupported function pointer.")); return nullptr; + } QString errorMessage; - TypeInfo typeInfo = TypeParser::parse(typei.toString(), &errorMessage); - if (typeInfo.qualifiedName().isEmpty()) { - qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString() - << "\": " << errorMessage; - return 0; - } // 2. Handle arrays. // 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with @@ -2312,16 +2335,22 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ if (!typeInfo.arrayElements().isEmpty() && !isConstCharStarCase) { TypeInfo newInfo; //newInfo.setArguments(typeInfo.arguments()); - newInfo.setIndirections(typeInfo.indirections()); + newInfo.setIndirectionsV(typeInfo.indirectionsV()); newInfo.setConstant(typeInfo.isConstant()); + newInfo.setVolatile(typeInfo.isVolatile()); newInfo.setFunctionPointer(typeInfo.isFunctionPointer()); newInfo.setQualifiedName(typeInfo.qualifiedName()); newInfo.setReferenceType(typeInfo.referenceType()); newInfo.setVolatile(typeInfo.isVolatile()); - AbstractMetaType *elementType = translateType(newInfo); - if (!elementType) + AbstractMetaType *elementType = translateTypeStatic(newInfo, currentClass, d, true, &errorMessage); + if (!elementType) { + if (errorMessageIn) { + errorMessage.prepend(QLatin1String("Unable to translate array element: ")); + *errorMessageIn = msgUnableToTranslateType(_typei, errorMessage); + } return nullptr; + } for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) { AbstractMetaType *arrayType = new AbstractMetaType; @@ -2329,7 +2358,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ const QString &arrayElement = typeInfo.arrayElements().at(i); if (!arrayElement.isEmpty()) { bool _ok; - const qint64 elems = findOutValueFromString(arrayElement, _ok); + const qint64 elems = d + ? d->findOutValueFromString(arrayElement, _ok) + : arrayElement.toLongLong(&_ok, 0); if (_ok) arrayType->setArrayElementCount(int(elems)); } @@ -2344,8 +2375,11 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ QStringList qualifierList = typeInfo.qualifiedName(); if (qualifierList.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("horribly broken type '%1'").arg(_typei.toString()); + errorMessage = msgUnableToTranslateType(_typei, QLatin1String("horribly broken type")); + if (errorMessageIn) + *errorMessageIn = errorMessage; + else + qCWarning(lcShiboken,"%s", qPrintable(errorMessage)); return nullptr; } @@ -2353,19 +2387,21 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ QString name = qualifierList.takeLast(); // 4. Special case QFlags (include instantiation in name) - if (qualifiedName == QLatin1String("QFlags")) + if (qualifiedName == QLatin1String("QFlags")) { qualifiedName = typeInfo.toString(); + typeInfo.clearInstantiations(); + } const TypeEntry *type = 0; // 5. Try to find the type // 5.1 - Try first using the current scope - if (m_currentClass) { - type = findTypeEntryUsingContext(m_currentClass, qualifiedName); + if (currentClass) { + type = findTypeEntryUsingContext(currentClass, qualifiedName); // 5.1.1 - Try using the class parents' scopes - if (!type && !m_currentClass->baseClassNames().isEmpty()) { - const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass); + if (!type && d && !currentClass->baseClassNames().isEmpty()) { + const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass); for (const AbstractMetaClass *cls : baseClasses) { type = findTypeEntryUsingContext(cls, qualifiedName); if (type) @@ -2388,36 +2424,44 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ // 8. No? Check if the current class is a template and this type is one // of the parameters. - if (!type && m_currentClass) { - const QVector<TypeEntry *> &template_args = m_currentClass->templateArguments(); + if (!type && currentClass) { + const QVector<TypeEntry *> &template_args = currentClass->templateArguments(); for (TypeEntry *te : template_args) { if (te->name() == qualifiedName) type = te; } } - if (!type) + if (!type) { + if (errorMessageIn) { + *errorMessageIn = + msgUnableToTranslateType(_typei, msgCannotFindTypeEntry(qualifiedName)); + } return nullptr; + } // Used to for diagnostics later... - m_usedTypes << type; + if (d) + d->m_usedTypes << type; // These are only implicit and should not appear in code... Q_ASSERT(!type->isInterface()); AbstractMetaType *metaType = new AbstractMetaType; metaType->setTypeEntry(type); - metaType->setIndirections(typeInfo.indirections()); + metaType->setIndirectionsV(typeInfo.indirectionsV()); metaType->setReferenceType(typeInfo.referenceType()); metaType->setConstant(typeInfo.isConstant()); + metaType->setVolatile(typeInfo.isVolatile()); metaType->setOriginalTypeDescription(_typei.toString()); - const auto &templateArguments = typeInfo.arguments(); + const auto &templateArguments = typeInfo.instantiations(); for (int t = 0, size = templateArguments.size(); t < size; ++t) { TypeInfo ti = templateArguments.at(t); - ti.setQualifiedName(ti.instantiationName()); - AbstractMetaType *targType = translateType(ti); + AbstractMetaType *targType = translateTypeStatic(ti, currentClass, d, true, &errorMessage); if (!targType) { + if (errorMessageIn) + *errorMessageIn = msgCannotTranslateTemplateArgument(t, ti, errorMessage); delete metaType; return nullptr; } @@ -2434,6 +2478,33 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ return metaType; } +AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, + AbstractMetaClass *currentClass, + bool resolveType, + QString *errorMessage) +{ + return AbstractMetaBuilderPrivate::translateTypeStatic(_typei, currentClass, + nullptr, resolveType, + errorMessage); +} + +AbstractMetaType *AbstractMetaBuilder::translateType(const QString &t, + AbstractMetaClass *currentClass, + bool resolveType, + QString *errorMessageIn) +{ + QString errorMessage; + TypeInfo typeInfo = TypeParser::parse(t, &errorMessage); + if (typeInfo.qualifiedName().isEmpty()) { + errorMessage = msgUnableToTranslateType(t, errorMessage); + if (errorMessageIn) + *errorMessageIn = errorMessage; + else + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + return nullptr; + } + return translateType(typeInfo, currentClass, resolveType, errorMessageIn); +} qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok) { @@ -2728,7 +2799,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, const TypeInfo &info) { - QVector<TypeInfo> targs = info.arguments(); + QVector<TypeInfo> targs = info.instantiations(); QVector<AbstractMetaType *> templateTypes; if (subclass->isTypeDef()) { @@ -2764,13 +2835,13 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, temporaryType->setTypeEntry(t); temporaryType->setConstant(i.isConstant()); temporaryType->setReferenceType(i.referenceType()); - temporaryType->setIndirections(i.indirections()); + temporaryType->setIndirectionsV(i.indirectionsV()); temporaryType->decideUsagePattern(); templateTypes << temporaryType; } else { qCWarning(lcShiboken).noquote().nospace() << "Ignoring template parameter " << templateParamName << " from " - << info.instantiationName() << ", because I don't know what it is."; + << info.toString() << ", because I don't know what it is."; } } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index a0ca71b94..bea2ac4c0 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -38,7 +38,9 @@ QT_FORWARD_DECLARE_CLASS(QIODevice) class AbstractMetaBuilderPrivate; class AbstractMetaClass; +class AbstractMetaType; class AbstractMetaEnumValue; +class TypeInfo; class AbstractMetaBuilder { @@ -83,6 +85,16 @@ public: */ void setGlobalHeader(const QString& globalHeader); + static AbstractMetaType *translateType(const TypeInfo &_typei, + AbstractMetaClass *currentClass = nullptr, + bool resolveType = true, + QString *errorMessage = nullptr); + static AbstractMetaType *translateType(const QString &t, + AbstractMetaClass *currentClass = nullptr, + bool resolveType = true, + QString *errorMessage = nullptr); + + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; #endif diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 59e3cfc94..7d4e280bd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -123,7 +123,14 @@ public: int argumentIndex); AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo); AbstractMetaType *translateType(const TypeInfo &type, - bool resolveType = true); + bool resolveType = true, + QString *errorMessage = nullptr); + static AbstractMetaType *translateTypeStatic(const TypeInfo &type, + AbstractMetaClass *current, + AbstractMetaBuilderPrivate *d = nullptr, + bool resolveType = true, + QString *errorMessageIn = nullptr); + qint64 findOutValueFromString(const QString &stringValue, bool &ok); AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 5be7050bf..634eae5a0 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -31,6 +31,8 @@ #include "typedatabase.h" #include "typesystem.h" +#include <parser/codemodel.h> + #ifndef QT_NO_DEBUG_STREAM # include <QtCore/QMetaEnum> # include <QtCore/QMetaObject> @@ -112,8 +114,8 @@ void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes & AbstractMetaType::AbstractMetaType() : m_constant(false), + m_volatile(false), m_cppInstantiation(true), - m_indirections(0), m_reserved(0) { } @@ -155,8 +157,9 @@ AbstractMetaType *AbstractMetaType::copy() const cpy->setTypeUsagePattern(typeUsagePattern()); cpy->setConstant(isConstant()); + cpy->setVolatile(isVolatile()); cpy->setReferenceType(referenceType()); - cpy->setIndirections(indirections()); + cpy->setIndirectionsV(indirectionsV()); cpy->setInstantiations(instantiations()); cpy->setArrayElementCount(arrayElementCount()); cpy->setOriginalTypeDescription(originalTypeDescription()); @@ -291,16 +294,32 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at) d << ", typeEntry=" << at->typeEntry() << ", signature=\"" << at->cppSignature() << "\", pattern=" << at->typeUsagePattern(); - if (at->indirections()) - d << ", indirections=" << at->indirections(); + const auto indirections = at->indirectionsV(); + if (!indirections.isEmpty()) { + d << ", indirections="; + for (auto i : indirections) + d << ' ' << TypeInfo::indirectionKeyword(i); + } if (at->referenceType()) d << ", reftype=" << at->referenceType(); if (at->isConstant()) d << ", [const]"; + if (at->isVolatile()) + d << ", [volatile]"; if (at->isArray()) { d << ", array of \"" << at->arrayElementType()->cppSignature() << "\", arrayElementCount=" << at->arrayElementCount(); } + const auto &instantiations = at->instantiations(); + if (const int instantiationsSize = instantiations.size()) { + d << ", instantiations[" << instantiationsSize << "]=<"; + for (int i = 0; i < instantiationsSize; ++i) { + if (i) + d << ", "; + d << instantiations.at(i); + } + } + d << '>'; } } else { d << '0'; @@ -2222,6 +2241,8 @@ QString AbstractMetaType::formatSignature(bool minimal) const QString result; if (isConstant()) result += QLatin1String("const "); + if (isVolatile()) + result += QLatin1String("volatile "); if (isArray()) { // Build nested array dimensions a[2][3] in correct order result += m_arrayElementType->minimalSignature(); @@ -2245,10 +2266,10 @@ QString AbstractMetaType::formatSignature(bool minimal) const result += QLatin1String(" >"); } - if (!minimal && (m_indirections != 0 || m_referenceType != NoReference)) + if (!minimal && (!m_indirections.isEmpty() || m_referenceType != NoReference)) result += QLatin1Char(' '); - if (m_indirections) - result += QString(m_indirections, QLatin1Char('*')); + for (Indirection i : m_indirections) + result += TypeInfo::indirectionKeyword(i); switch (referenceType()) { case NoReference: break; @@ -2406,6 +2427,18 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) } d << ')'; } + const auto &templateArguments = ac->templateArguments(); + if (const int count = templateArguments.size()) { + d << ", templateArguments=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + d << templateArguments.at(i); + } + d << ')'; + } + + } else { d << '0'; } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index d1a0fbf88..7b4ad2b21 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -288,6 +288,7 @@ class AbstractMetaType { Q_GADGET public: + typedef QVector<Indirection> Indirections; enum TypeUsagePattern { InvalidPattern, @@ -436,6 +437,9 @@ public: m_constant = constant; } + bool isVolatile() const { return m_volatile; } + void setVolatile(bool v) { m_volatile = v; } + bool isConstRef() const; ReferenceType referenceType() const { return m_referenceType; } @@ -443,16 +447,21 @@ public: int actualIndirections() const { - return m_indirections + (m_referenceType == LValueReference ? 1 : 0); - } - int indirections() const - { - return m_indirections; + return m_indirections.size() + (m_referenceType == LValueReference ? 1 : 0); } + + Indirections indirectionsV() const { return m_indirections; } + void setIndirectionsV(const Indirections &i) { m_indirections = i; } + void clearIndirections() { m_indirections.clear(); } + + // "Legacy"? + int indirections() const { return m_indirections.size(); } void setIndirections(int indirections) { - m_indirections = indirections; + m_indirections = Indirections(indirections, Indirection::Pointer); } + void addIndirection(Indirection i = Indirection::Pointer) + { m_indirections.append(i); } void setArrayElementCount(int n) { @@ -541,12 +550,14 @@ private: int m_arrayElementCount = -1; const AbstractMetaType *m_arrayElementType = nullptr; const AbstractMetaType *m_originalTemplateType = nullptr; + Indirections m_indirections; TypeUsagePattern m_pattern = InvalidPattern; uint m_constant : 1; + uint m_volatile : 1; uint m_cppInstantiation : 1; - int m_indirections : 4; - uint m_reserved : 26; // unused + uint m_reserved : 29; // unused + ReferenceType m_referenceType = NoReference; AbstractMetaTypeList m_children; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index af7f96068..9d0d69c27 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -183,6 +183,10 @@ public: TypeInfo createTypeInfo(const CXType &type) const; TypeInfo createTypeInfo(const CXCursor &cursor) const { return createTypeInfo(clang_getCursorType(cursor)); } + void addTemplateInstantiations(const CXType &type, + QString *typeName, + TypeInfo *t) const; + bool addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const; TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const; TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const; @@ -359,38 +363,6 @@ struct ArrayDimensionResult int position; }; -static ArrayDimensionResult arrayDimensions(const QString &typeName) -{ - ArrayDimensionResult result; - result.position = typeName.indexOf(QLatin1Char('[')); - for (int openingPos = result.position; openingPos != -1; ) { - const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1); - if (closingPos == -1) - break; - result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1)); - openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1); - } - return result; -} - -// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none -static QStringList parseArrayArgs(const CXType &type, QString *typeName) -{ - const ArrayDimensionResult dimensions = arrayDimensions(*typeName); - Q_ASSERT(!dimensions.dimensions.isEmpty()); - - QStringList result; - // get first dimension from clang, preferably. - // "a[]" is seen as pointer by Clang, set special indicator "" - const long long size = clang_getArraySize(type); - result.append(size >= 0 ? QString::number(size) : QString()); - // Parse out remaining dimensions - for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i) - result.append(dimensions.dimensions.at(i).toString()); - typeName->truncate(dimensions.position); - return result; -} - // Create qualified name "std::list<std::string>" -> ("std", "list<std::string>") static QStringList qualifiedName(const QString &t) { @@ -412,6 +384,65 @@ static QStringList qualifiedName(const QString &t) return result; } +static bool isArrayType(CXTypeKind k) +{ + return k == CXType_ConstantArray || k == CXType_IncompleteArray + || k == CXType_VariableArray || k == CXType_DependentSizedArray; +} + +static bool isPointerType(CXTypeKind k) +{ + return k == CXType_Pointer || k == CXType_LValueReference || k == CXType_RValueReference; +} + +bool BuilderPrivate::addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const +{ + // Template arguments + switch (type.kind) { + case CXType_Elaborated: + case CXType_Record: + case CXType_Unexposed: + if (const int numTemplateArguments = qMax(0, clang_Type_getNumTemplateArguments(type))) { + for (unsigned tpl = 0; tpl < unsigned(numTemplateArguments); ++tpl) { + const CXType argType = clang_Type_getTemplateArgumentAsType(type, tpl); + // CXType_Invalid is returned when hitting on a specialization + // of a non-type template (template <int v>). + if (argType.kind == CXType_Invalid) + return false; + t->addInstantiation(createTypeInfo(argType)); + } + } + break; + default: + break; + } + return true; +} + +static void dummyTemplateArgumentHandler(int, const QStringRef &) {} + +void BuilderPrivate::addTemplateInstantiations(const CXType &type, + QString *typeName, + TypeInfo *t) const +{ + // In most cases, for templates like "Vector<A>", Clang will give us the + // arguments by recursing down the type. However this will fail for example + // within template classes (for functions like the copy constructor): + // template <class T> + // class Vector { + // Vector(const Vector&); + // }; + // In that case, have TypeInfo parse the list from the spelling. + // Finally, remove the list "<>" from the type name. + const bool parsed = addTemplateInstantiationsRecursion(type, t) + && !t->instantiations().isEmpty(); + const QPair<int, int> pos = parsed + ? parseTemplateArgumentList(*typeName, dummyTemplateArgumentHandler) + : t->parseTemplateArgumentList(*typeName); + if (pos.first != -1 && pos.second != -1 && pos.second > pos.first) + typeName->remove(pos.first, pos.second - pos.first); +} + TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const { if (type.kind == CXType_Pointer) { // Check for function pointers, first. @@ -427,50 +458,44 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const } TypeInfo typeInfo; - QString typeName = fixTypeName(getTypeName(type)); - - int indirections = 0; - // "int **" - for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections) - typeName.chop(1); - typeInfo.setIndirections(indirections); - // "int &&" - if (typeName.endsWith(QLatin1String("&&"))) { - typeName.chop(2); - typeInfo.setReferenceType(RValueReference); - } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &" - typeName.chop(1); - typeInfo.setReferenceType(LValueReference); - } - // "int [3], int[]" - if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray - || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) { - typeInfo.setArrayElements(parseArrayArgs(type, &typeName)); + CXType nestedType = type; + for (; isArrayType(nestedType.kind); nestedType = clang_getArrayElementType(nestedType)) { + const long long size = clang_getArraySize(nestedType); + typeInfo.addArrayElement(size >= 0 ? QString::number(size) : QString()); } - bool isConstant = clang_isConstQualifiedType(type) != 0; - // A "char *const" parameter, is considered to be const-qualified by Clang, but - // not in the TypeInfo sense (corresponds to "char *" and not "const char *"). - if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) { - typeName.chop(5); - typeName = typeName.trimmed(); - isConstant = false; - } - // Clang has been observed to return false for "const int .." - if (!isConstant && typeName.startsWith(QLatin1String("const "))) { - typeName.remove(0, 6); - isConstant = true; + TypeInfo::Indirections indirections; + for (; isPointerType(nestedType.kind); nestedType = clang_getPointeeType(nestedType)) { + switch (nestedType.kind) { + case CXType_Pointer: + indirections.prepend(clang_isConstQualifiedType(nestedType) != 0 + ? Indirection::ConstPointer : Indirection::Pointer); + break; + case CXType_LValueReference: + typeInfo.setReferenceType(LValueReference); + break; + case CXType_RValueReference: + typeInfo.setReferenceType(RValueReference); + break; + default: + break; + } } - typeInfo.setConstant(isConstant); + typeInfo.setIndirectionsV(indirections); + + typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0); + typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0); - // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *" - if (typeName.startsWith(QLatin1String("volatile "))) { - typeName.remove(0, 9); - typeInfo.setVolatile(true); + QString typeName = getTypeName(nestedType); + while (TypeInfo::stripLeadingConst(&typeName) + || TypeInfo::stripLeadingVolatile(&typeName)) { } - typeName = typeName.trimmed(); + // Obtain template instantiations if the name has '<' (thus excluding + // typedefs like "std::string". + if (typeName.contains(QLatin1Char('<'))) + addTemplateInstantiations(nestedType, &typeName, &typeInfo); typeInfo.setQualifiedName(qualifiedName(typeName)); // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types? diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp index 2ff18b23b..a68c5b5ee 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp @@ -160,6 +160,43 @@ QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu) return result; } +QPair<int, int> parseTemplateArgumentList(const QString &l, + const TemplateArgumentHandler &handler, + int from) +{ + const int ltPos = l.indexOf(QLatin1Char('<'), from); + if (ltPos == - 1) + return qMakePair(-1, -1); + int startPos = ltPos + 1; + int level = 1; + for (int p = startPos, end = l.size(); p < end; ) { + const char c = l.at(p).toLatin1(); + switch (c) { + case ',': + case '>': + handler(level, l.midRef(startPos, p - startPos).trimmed()); + ++p; + if (c == '>') { + if (--level == 0) + return qMakePair(ltPos, p); + // Skip over next ',': "a<b<c,d>,e>" + for (; p < end && (l.at(p).isSpace() || l.at(p) == QLatin1Char(',')); ++p) {} + } + startPos = p; + break; + case '<': + handler(level, l.midRef(startPos, p - startPos).trimmed()); + ++level; + startPos = ++p; + break; + default: + ++p; + break; + } + } + return qMakePair(-1, -1); +} + CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds) { CXDiagnosticSeverity result = CXDiagnostic_Ignored; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h index 98d0c9752..ab6f0ef91 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h @@ -34,6 +34,8 @@ #include <QtCore/QString> #include <QtCore/QVector> +#include <functional> + QT_FORWARD_DECLARE_CLASS(QDebug) bool operator==(const CXCursor &c1, const CXCursor &c2); @@ -92,6 +94,14 @@ struct Diagnostic { QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu); CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds); +// Parse a template argument list "a<b<c,d>,e>" and invoke a handler +// with each match (level and string). Return begin and end of the list. +typedef std::function<void(int /*level*/, const QStringRef &)> TemplateArgumentHandler; + +QPair<int, int> parseTemplateArgumentList(const QString &l, + const TemplateArgumentHandler &handler, + int from = 0); + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug, const SourceLocation &); QDebug operator<<(QDebug, const Diagnostic &); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index d862692dd..a560c0faf 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -29,11 +29,15 @@ #include "codemodel.h" + +#include <clangparser/clangutils.h> + #include <algorithm> #include <functional> #include <iostream> #include <QDebug> #include <QDir> +#include <QtCore/QStack> // Predicate to find an item by name in a list of QSharedPointer<Item> template <class T> class ModelItemNamePredicate : public std::unary_function<bool, QSharedPointer<T> > @@ -140,16 +144,18 @@ TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) __result.setVolatile(__result.isVolatile() || __rhs.isVolatile()); if (__rhs.referenceType() > __result.referenceType()) __result.setReferenceType(__rhs.referenceType()); - __result.setIndirections(__result.indirections() + __rhs.indirections()); + __result.m_indirections.append(__rhs.m_indirections); __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); + __result.m_instantiations.append(__rhs.m_instantiations); return __result; } bool TypeInfo::isVoid() const { - return m_indirections == 0 && m_referenceType == NoReference + return m_indirections.isEmpty() && m_referenceType == NoReference && m_arguments.isEmpty() && m_arrayElements.isEmpty() + && m_instantiations.isEmpty() && m_qualifiedName.size() == 1 && m_qualifiedName.constFirst() == QLatin1String("void"); } @@ -193,19 +199,76 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, Cod return otherType; } +// Handler for clang::parseTemplateArgumentList() that populates +// TypeInfo::m_instantiations +class TypeInfoTemplateArgumentHandler : + public std::binary_function<void, int, const QStringRef &> +{ +public: + explicit TypeInfoTemplateArgumentHandler(TypeInfo *t) + { + m_parseStack.append(t); + } + + void operator()(int level, const QStringRef &name) + { + if (level > m_parseStack.size()) { + Q_ASSERT(!top()->m_instantiations.isEmpty()); + m_parseStack.push(&top()->m_instantiations.back()); + } + while (level < m_parseStack.size()) + m_parseStack.pop(); + TypeInfo instantiation; + instantiation.setQualifiedName(qualifiedName(name)); + top()->addInstantiation(instantiation); + } + +private: + TypeInfo *top() const { return m_parseStack.back(); } + + static QStringList qualifiedName(const QStringRef &name) + { + QStringList result; + const QVector<QStringRef> nameParts = name.split(QLatin1String("::")); + result.reserve(nameParts.size()); + for (const QStringRef &p : nameParts) + result.append(p.toString()); + return result; + } + + QStack<TypeInfo *> m_parseStack; +}; + +QPair<int, int> TypeInfo::parseTemplateArgumentList(const QString &l, int from) +{ + return clang::parseTemplateArgumentList(l, clang::TemplateArgumentHandler(TypeInfoTemplateArgumentHandler(this)), from); +} + QString TypeInfo::toString() const { QString tmp; - - tmp += m_qualifiedName.join(QLatin1String("::")); if (isConstant()) - tmp += QLatin1String(" const"); + tmp += QLatin1String("const "); if (isVolatile()) - tmp += QLatin1String(" volatile"); + tmp += QLatin1String("volatile "); - if (indirections()) - tmp += QString(indirections(), QLatin1Char('*')); + tmp += m_qualifiedName.join(QLatin1String("::")); + + if (const int instantiationCount = m_instantiations.size()) { + tmp += QLatin1Char('<'); + for (int i = 0; i < instantiationCount; ++i) { + if (i) + tmp += QLatin1String(", "); + tmp += m_instantiations.at(i).toString(); + } + if (tmp.endsWith(QLatin1Char('>'))) + tmp += QLatin1Char(' '); + tmp += QLatin1Char('>'); + } + + for (Indirection i : m_indirections) + tmp.append(indirectionKeyword(i)); switch (referenceType()) { case NoReference: @@ -238,20 +301,6 @@ 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()) @@ -269,7 +318,41 @@ bool TypeInfo::operator==(const TypeInfo &other) const return flags == other.flags && m_qualifiedName == other.m_qualifiedName - && (!m_functionPointer || m_arguments == other.m_arguments); + && (!m_functionPointer || m_arguments == other.m_arguments) + && m_instantiations == other.m_instantiations; +} + +QString TypeInfo::indirectionKeyword(Indirection i) +{ + return i == Indirection::Pointer + ? QStringLiteral("*") : QStringLiteral("*const"); +} + +static inline QString constQualifier() { return QStringLiteral("const"); } +static inline QString volatileQualifier() { return QStringLiteral("volatile"); } + +bool TypeInfo::stripLeadingConst(QString *s) +{ + return stripLeadingQualifier(constQualifier(), s); +} + +bool TypeInfo::stripLeadingVolatile(QString *s) +{ + return stripLeadingQualifier(volatileQualifier(), s); +} + +bool TypeInfo::stripLeadingQualifier(const QString &qualifier, QString *s) +{ + // "const int x" + const int qualifierSize = qualifier.size(); + if (s->size() < qualifierSize + 1 || !s->startsWith(qualifier) + || !s->at(qualifierSize).isSpace()) { + return false; + } + s->remove(0, qualifierSize + 1); + while (!s->isEmpty() && s->at(0).isSpace()) + s->remove(0, 1); + return true; } #ifndef QT_NO_DEBUG_STREAM @@ -292,8 +375,11 @@ void TypeInfo::formatDebug(QDebug &d) const d << ", [const]"; if (m_volatile) d << ", [volatile]"; - if (m_indirections) - d << ", indirections=" << m_indirections; + if (!m_indirections.isEmpty()) { + d << ", indirections="; + for (auto i : m_indirections) + d << ' ' << TypeInfo::indirectionKeyword(i); + } switch (m_referenceType) { case NoReference: break; @@ -304,6 +390,11 @@ void TypeInfo::formatDebug(QDebug &d) const d << ", [rvalref]"; break; } + if (!m_instantiations.isEmpty()) { + d << ", template<"; + formatSequence(d, m_instantiations.begin(), m_instantiations.end()); + d << '>'; + } if (m_functionPointer) { d << ", function ptr("; formatSequence(d, m_arguments.begin(), m_arguments.end()); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index ac1fe26c1..c61f640e1 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -36,6 +36,7 @@ #include "enumvalue.h" #include <QtCore/QHash> +#include <QtCore/QPair> #include <QtCore/QSet> #include <QtCore/QString> #include <QtCore/QStringList> @@ -100,6 +101,8 @@ class TypeInfo { friend class TypeParser; public: + typedef QVector<Indirection> Indirections; + TypeInfo() : flags(0), m_referenceType(NoReference) {} QStringList qualifiedName() const @@ -137,14 +140,16 @@ public: ReferenceType referenceType() const { return m_referenceType; } void setReferenceType(ReferenceType r) { m_referenceType = r; } - int indirections() const - { - return m_indirections; - } + Indirections indirectionsV() const { return m_indirections; } + void setIndirectionsV(const Indirections &i) { m_indirections = i; } + void addIndirection(Indirection i) { m_indirections.append(i); } + + // "Legacy", rename? + int indirections() const { return m_indirections.size(); } void setIndirections(int indirections) { - m_indirections = indirections; + m_indirections = Indirections(indirections, Indirection::Pointer); } bool isFunctionPointer() const @@ -165,6 +170,8 @@ public: m_arrayElements = arrayElements; } + void addArrayElement(const QString &a) { m_arrayElements.append(a); } + QVector<TypeInfo> arguments() const { return m_arguments; } void setArguments(const QVector<TypeInfo> &arguments); @@ -174,6 +181,13 @@ public: m_arguments.append(arg); } + QVector<TypeInfo> instantiations() const { return m_instantiations; } + void setInstantiations(const QVector<TypeInfo> &i) { m_instantiations = i; } + void addInstantiation(const TypeInfo &i) { m_instantiations.append(i); } + void clearInstantiations() { m_instantiations.clear(); } + + QPair<int, int> parseTemplateArgumentList(const QString &l, int from = 0); + bool operator==(const TypeInfo &other) const; bool operator!=(const TypeInfo &other) const @@ -185,8 +199,6 @@ public: QString toString() const; - QStringList instantiationName() const; - static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs); static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope); @@ -194,12 +206,22 @@ public: void formatDebug(QDebug &d) const; #endif + static QString indirectionKeyword(Indirection i); + + static bool stripLeadingConst(QString *s); + static bool stripLeadingVolatile(QString *s); + static bool stripLeadingQualifier(const QString &qualifier, QString *s); + private: + friend class TypeInfoTemplateArgumentHandler; + static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope); QStringList m_qualifiedName; QStringList m_arrayElements; QVector<TypeInfo> m_arguments; + QVector<TypeInfo> m_instantiations; + Indirections m_indirections; union { uint flags; @@ -208,8 +230,7 @@ private: uint m_constant: 1; uint m_volatile: 1; uint m_functionPointer: 1; - uint m_indirections: 6; - uint m_padding: 23; + uint m_padding: 29; }; }; diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index b8a10ba93..9a3cc0e07 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -41,4 +41,10 @@ enum EnumKind { EnumClass // C++ 11 : enum class Foo { value1, value2 } }; +enum class Indirection +{ + Pointer, // int * + ConstPointer // int *const +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp index 7f1361a7d..86bf64495 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp @@ -31,6 +31,37 @@ #include "testutil.h" #include <abstractmetalang.h> #include <typesystem.h> +#include <parser/codemodel.h> +#include <typeparser.h> + +void TestAbstractMetaType::parsing_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("output"); + QTest::newRow("primitive") + << QString::fromLatin1("int") << QString::fromLatin1("int"); + QTest::newRow("ref") + << QString::fromLatin1("int &") << QString::fromLatin1("int&"); + QTest::newRow("pointer") + << QString::fromLatin1("int **") << QString::fromLatin1("int**"); + QTest::newRow("const ref") + << QString::fromLatin1("const int &") << QString::fromLatin1("const int&"); + QTest::newRow("const pointer") + << QString::fromLatin1("const int **") << QString::fromLatin1("const int**"); + QTest::newRow("const pointer const") + << QString::fromLatin1("const int *const*") << QString::fromLatin1("const int*const*"); +} + +void TestAbstractMetaType::parsing() +{ + QFETCH(QString, input); + QFETCH(QString, output); + QString errorMessage; + const TypeInfo ti = TypeParser::parse(input, &errorMessage); + QVERIFY2(errorMessage.isEmpty(), qPrintable(errorMessage)); + const QString actual = ti.toString(); + QCOMPARE(actual, output); +} void TestAbstractMetaType::testConstCharPtrType() { diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h index b2aa7544f..b39a27a54 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h @@ -35,6 +35,8 @@ class TestAbstractMetaType : public QObject { Q_OBJECT private slots: + void parsing_data(); + void parsing(); void testConstCharPtrType(); void testCharType(); void testTypedef(); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 9529de40a..e494ba174 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -518,7 +518,10 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) { QXmlStreamReader reader(device); Handler handler(this, generate); - return handler.parse(reader); + const bool result = handler.parse(reader); + if (!result) + qCWarning(lcShiboken, "%s", qPrintable(handler.errorString())); + return result; } PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp index 02c85421b..0a60159ae 100644 --- a/sources/shiboken2/ApiExtractor/typeparser.cpp +++ b/sources/shiboken2/ApiExtractor/typeparser.cpp @@ -49,6 +49,7 @@ public: GreaterThanToken, ConstToken, + VolatileToken, Identifier, NoToken, InvalidToken @@ -137,13 +138,30 @@ Scanner::Token Scanner::nextToken(QString *errorMessage) } } - if (tok == Identifier && m_pos - m_tokenStart == 5) { - if (m_chars[m_tokenStart] == QLatin1Char('c') - && m_chars[m_tokenStart + 1] == QLatin1Char('o') - && m_chars[m_tokenStart + 2] == QLatin1Char('n') - && m_chars[m_tokenStart + 3] == QLatin1Char('s') - && m_chars[m_tokenStart + 4] == QLatin1Char('t')) - tok = ConstToken; + if (tok == Identifier) { + switch (m_pos - m_tokenStart) { + case 5: + if (m_chars[m_tokenStart] == QLatin1Char('c') + && m_chars[m_tokenStart + 1] == QLatin1Char('o') + && m_chars[m_tokenStart + 2] == QLatin1Char('n') + && m_chars[m_tokenStart + 3] == QLatin1Char('s') + && m_chars[m_tokenStart + 4] == QLatin1Char('t')) { + tok = ConstToken; + } + break; + case 8: + if (m_chars[m_tokenStart] == QLatin1Char('v') + && m_chars[m_tokenStart + 1] == QLatin1Char('o') + && m_chars[m_tokenStart + 2] == QLatin1Char('l') + && m_chars[m_tokenStart + 3] == QLatin1Char('a') + && m_chars[m_tokenStart + 4] == QLatin1Char('t') + && m_chars[m_tokenStart + 5] == QLatin1Char('i') + && m_chars[m_tokenStart + 6] == QLatin1Char('l') + && m_chars[m_tokenStart + 7] == QLatin1Char('e')) { + tok = VolatileToken; + } + break; + } } return tok; @@ -167,6 +185,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) bool colon_prefix = false; bool in_array = false; QString array; + bool seenStar = false; Scanner::Token tok = scanner.nextToken(errorMessage); while (tok != Scanner::NoToken) { @@ -191,7 +210,8 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) switch (tok) { case Scanner::StarToken: - ++stack.top()->m_indirections; + seenStar = true; + stack.top()->addIndirection(Indirection::Pointer); break; case Scanner::AmpersandToken: @@ -212,14 +232,14 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) } break; case Scanner::LessThanToken: - stack.top()->m_arguments << TypeInfo(); - stack.push(&stack.top()->m_arguments.last()); + stack.top()->m_instantiations << TypeInfo(); + stack.push(&stack.top()->m_instantiations.last()); break; case Scanner::CommaToken: stack.pop(); - stack.top()->m_arguments << TypeInfo(); - stack.push(&stack.top()->m_arguments.last()); + stack.top()->m_instantiations << TypeInfo(); + stack.push(&stack.top()->m_instantiations.last()); break; case Scanner::GreaterThanToken: @@ -231,7 +251,16 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage) break; case Scanner::ConstToken: - stack.top()->m_constant = true; + if (seenStar) { // "int *const": Last indirection is const. + Q_ASSERT(!stack.top()->m_indirections.isEmpty()); + *stack.top()->m_indirections.rbegin() = Indirection::ConstPointer; + } else { + stack.top()->m_constant = true; + } + break; + + case Scanner::VolatileToken: + stack.top()->m_volatile = true; break; case Scanner::OpenParenToken: // function pointers not supported diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index baaec6d30..f316de80a 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -210,11 +210,6 @@ static QString msgReaderError(const QXmlStreamReader &reader, const QString &wha return message; } -static QString msgReaderError(const QXmlStreamReader &reader) -{ - return msgReaderError(reader, reader.errorString()); -} - static QString msgInvalidVersion(const QStringRef &version, const QString &package = QString()) { QString result; @@ -238,7 +233,7 @@ bool Handler::parse(QXmlStreamReader &reader) switch (reader.readNext()) { case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: - qCWarning(lcShiboken).noquote().nospace() << msgReaderError(reader); + m_error = msgReaderError(reader, reader.errorString()); return false; case QXmlStreamReader::StartElement: if (!startElement(reader.name(), reader.attributes())) { diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h index 882cf3fab..cbca7a557 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_p.h +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -140,6 +140,8 @@ public: bool parse(QXmlStreamReader &reader); + QString errorString() const { return m_error; } + private: bool startElement(const QStringRef& localName, const QXmlStreamAttributes& atts); bool handleSmartPointerEntry(StackElement *element, diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 80096cbf2..0965a373a 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -31,6 +31,7 @@ #include "overloaddata.h" #include <reporthandler.h> #include <typedatabase.h> +#include <abstractmetabuilder.h> #include <iostream> #include <QtCore/QDir> @@ -706,7 +707,8 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, || arg->type()->referenceType() == LValueReference) { result += QLatin1Char(objType); } else if (arg->type()->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); + const PrimitiveTypeEntry *ptype = + static_cast<const PrimitiveTypeEntry *>(arg->type()->typeEntry()); if (ptype->basicReferencedTypeEntry()) ptype = ptype->basicReferencedTypeEntry(); if (m_formatUnits.contains(ptype->name())) @@ -745,7 +747,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && type->referenceType() == NoReference) { baseName = QLatin1String("Sbk_") + type->name(); } else if (type->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *ptype = static_cast<const PrimitiveTypeEntry *>(type); while (ptype->basicReferencedTypeEntry()) ptype = ptype->basicReferencedTypeEntry(); if (ptype->targetLangApiName() == ptype->name()) @@ -753,11 +755,11 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) else baseName = ptype->targetLangApiName(); } else if (type->isEnum()) { - baseName = cpythonEnumName((const EnumTypeEntry*) type); + baseName = cpythonEnumName(static_cast<const EnumTypeEntry *>(type)); } else if (type->isFlags()) { - baseName = cpythonFlagsName((const FlagsTypeEntry*) type); + baseName = cpythonFlagsName(static_cast<const FlagsTypeEntry *>(type)); } else if (type->isContainer()) { - const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type; + const ContainerTypeEntry *ctype = static_cast<const ContainerTypeEntry *>(type); switch (ctype->type()) { case ContainerTypeEntry::ListContainer: case ContainerTypeEntry::StringListContainer: @@ -975,7 +977,7 @@ bool ShibokenGenerator::isNumber(const TypeEntry* type) { if (!type->isPrimitive()) return false; - return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type)); + return isNumber(pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type))); } bool ShibokenGenerator::isNumber(const AbstractMetaType* type) @@ -987,7 +989,8 @@ bool ShibokenGenerator::isPyInt(const TypeEntry* type) { if (!type->isPrimitive()) return false; - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == QLatin1String("PyInt"); + return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)) + == QLatin1String("PyInt"); } bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) @@ -998,7 +1001,7 @@ bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) bool ShibokenGenerator::isWrapperType(const TypeEntry* type) { if (type->isComplex()) - return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type); + return ShibokenGenerator::isWrapperType(static_cast<const ComplexTypeEntry *>(type)); return type->isObject() || type->isValue() || type->isSmartPointer(); } bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type) @@ -1052,7 +1055,7 @@ bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type) { if (!type->isPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); return trueType->isPrimitive() && !trueType->isCppPrimitive() @@ -1072,7 +1075,7 @@ bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type) return true; if (!type->isPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); return trueType->qualifiedCppName() == QLatin1String("std::string"); @@ -1127,7 +1130,8 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); } else if (metaType->typeEntry()->isContainer()) { QString typeCheck = QLatin1String("Shiboken::Conversions::"); - ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type(); + ContainerTypeEntry::Type type = + static_cast<const ContainerTypeEntry *>(metaType->typeEntry())->type(); if (type == ContainerTypeEntry::ListContainer || type == ContainerTypeEntry::StringListContainer || type == ContainerTypeEntry::LinkedListContainer @@ -1182,8 +1186,10 @@ QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool gene if (type->isEnum() || type->isFlags() || isWrapperType(type)) return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type)); - else if (isCppPrimitive(type)) - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type) + QLatin1String("_Check"); + else if (isCppPrimitive(type)) { + return pythonPrimitiveTypeName(static_cast<const PrimitiveTypeEntry *>(type)) + + QLatin1String("_Check"); + } QString typeCheck; if (type->targetLangApiName() == type->name()) typeCheck = cpythonIsConvertibleFunction(type); @@ -1619,8 +1625,9 @@ ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentRepl QString argValue; if (language == TypeSystem::TargetLangCode) { bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty(); - bool argRemoved = func->argumentRemoved(i+1); - removed = removed + (int) argRemoved; + const bool argRemoved = func->argumentRemoved(i+1); + if (argRemoved) + ++removed; if (argRemoved && hasConversionRule) argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex())) @@ -2002,8 +2009,8 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa QString varName = list.at(1).trimmed(); if (!varType.isEmpty()) { if (varType != conversionType->cppSignature()) { - qFatal(qPrintable(QString::fromLatin1("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.") - .arg(varType, conversionType->cppSignature())), NULL); + qFatal("Types of receiver variable ('%s') and %%CONVERTTOCPP type system variable ('%s') differ.", + qPrintable(varType), qPrintable(conversionType->cppSignature())); } c << getFullTypeName(conversionType) << ' ' << varName; writeMinimalConstructorExpression(c, conversionType); @@ -2032,18 +2039,21 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa c << '('; break; } + Q_FALLTHROUGH(); case TypeSystemIsConvertibleFunction: if (conversion.isEmpty()) conversion = cpythonIsConvertibleFunction(conversionType); + Q_FALLTHROUGH(); case TypeSystemToPythonFunction: if (conversion.isEmpty()) conversion = cpythonToPythonConversionFunction(conversionType); + Q_FALLTHROUGH(); default: { QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); conversionString += arg; if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) { - qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'") - .arg(code)), NULL); + qFatal("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%s'", + qPrintable(code)); } if (conversion.contains(QLatin1String("%in"))) { conversion.prepend(QLatin1Char('(')); @@ -2256,10 +2266,14 @@ bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) return false; else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) return metaClass->hasCloneOperator(); - else - return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet); - return false; + return metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet; +} + +static inline QString msgCannotBuildMetaType(const QString &s) +{ + return QLatin1String("Unable to build meta type for \"") + + s + QLatin1String("\": "); } AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature, @@ -2269,110 +2283,18 @@ AbstractMetaType *ShibokenGenerator::buildAbstractMetaTypeFromString(QString typ if (typeSignature.startsWith(QLatin1String("::"))) typeSignature.remove(0, 2); - if (m_metaTypeFromStringCache.contains(typeSignature)) - return m_metaTypeFromStringCache.value(typeSignature); - - QString typeString = typeSignature; - bool isConst = typeString.startsWith(QLatin1String("const ")); - if (isConst) - typeString.remove(0, sizeof("const ") / sizeof(char) - 1); - - ReferenceType refType = NoReference; - if (typeString.endsWith(QLatin1String("&&"))) { - refType = RValueReference; - typeString.chop(2); - typeString = typeString.trimmed(); - } else if (typeString.endsWith(QLatin1Char('&'))) { - refType = LValueReference; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - int indirections = 0; - while (typeString.endsWith(QLatin1Char('*'))) { - ++indirections; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - if (typeString.startsWith(QLatin1String("::"))) - typeString.remove(0, 2); - - QString adjustedTypeName = typeString; - AbstractMetaTypeList instantiations; - int lpos = typeString.indexOf(QLatin1Char('<')); - if (lpos > -1) { - QStringList instantiatedTypes; - int rpos = typeString.lastIndexOf(QLatin1Char('>')); - if ((lpos != -1) && (rpos != -1)) { - QString type = typeString.mid(lpos + 1, rpos - lpos - 1); - int depth = 0; - int start = 0; - for (int i = 0; i < type.count(); ++i) { - if (type.at(i) == QLatin1Char('<')) { - ++depth; - } else if (type.at(i) == QLatin1Char('>')) { - --depth; - } else if (type.at(i) == QLatin1Char(',') && depth == 0) { - instantiatedTypes << type.mid(start, i - start).trimmed(); - start = i + 1; - } - } - instantiatedTypes << type.mid(start).trimmed(); - adjustedTypeName.truncate(lpos); - } - for (const QString &instantiatedType : qAsConst(instantiatedTypes)) { - AbstractMetaType *tmplArgType = buildAbstractMetaTypeFromString(instantiatedType); - if (!tmplArgType) { - if (errorMessage) { - QTextStream(errorMessage) << "Cannot find template type \"" - << instantiatedType << "\" for \"" << typeSignature << "\"."; - } - return nullptr; - } - instantiations.append(tmplArgType); + auto it = m_metaTypeFromStringCache.find(typeSignature); + if (it == m_metaTypeFromStringCache.end()) { + AbstractMetaType *metaType = + AbstractMetaBuilder::translateType(typeSignature, nullptr, true, errorMessage); + if (Q_UNLIKELY(!metaType)) { + if (errorMessage) + errorMessage->prepend(msgCannotBuildMetaType(typeSignature)); + return nullptr; } + it = m_metaTypeFromStringCache.insert(typeSignature, metaType); } - - TypeEntry *typeEntry = nullptr; - AbstractMetaType::TypeUsagePattern pattern = AbstractMetaType::InvalidPattern; - - if (instantiations.size() == 1 - && instantiations.at(0)->typeUsagePattern() == AbstractMetaType::EnumPattern - && adjustedTypeName == QLatin1String("QFlags")) { - pattern = AbstractMetaType::FlagsPattern; - typeEntry = TypeDatabase::instance()->findType(typeSignature); - } else { - typeEntry = TypeDatabase::instance()->findType(adjustedTypeName); - } - - if (!typeEntry) { - if (errorMessage) { - QTextStream(errorMessage) << "Cannot find type \"" << adjustedTypeName - << "\" for \"" << typeSignature << "\"."; - } - return nullptr; - } - - AbstractMetaType *metaType = new AbstractMetaType(); - metaType->setTypeEntry(typeEntry); - metaType->setIndirections(indirections); - metaType->setReferenceType(refType); - metaType->setConstant(isConst); - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - switch (pattern) { - case AbstractMetaType::FlagsPattern: - metaType->setTypeUsagePattern(pattern); - break; - default: - metaType->setInstantiations(instantiations); - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - metaType->decideUsagePattern(); - break; - } - - m_metaTypeFromStringCache.insert(typeSignature, metaType); - return metaType; + return it.value(); } AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry) @@ -2384,7 +2306,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const Ty return m_metaTypeFromStringCache.value(typeName); AbstractMetaType* metaType = new AbstractMetaType; metaType->setTypeEntry(typeEntry); - metaType->setIndirections(0); + metaType->clearIndirections(); metaType->setReferenceType(NoReference); metaType->setConstant(false); metaType->decideUsagePattern(); @@ -2449,7 +2371,7 @@ AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const Abstract { AbstractMetaFunctionList results; AbstractMetaClass* basis; - if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) { + if (func->ownerClass() && (basis = func->ownerClass()->baseClass())) { for (; basis; basis = basis->baseClass()) { const AbstractMetaFunction* inFunc = basis->findFunction(func->name()); if (inFunc && !seen->contains(inFunc->minimalSignature())) { @@ -2657,7 +2579,7 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* met QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type) { if (type->isCppPrimitive()) { - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry*>(type); if (trueType->basicReferencedTypeEntry()) type = trueType->basicReferencedTypeEntry(); } @@ -2738,7 +2660,7 @@ bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type) { if (!type->isCppPrimitive()) return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + const PrimitiveTypeEntry *trueType = static_cast<const PrimitiveTypeEntry *>(type); if (trueType->basicReferencedTypeEntry()) trueType = trueType->basicReferencedTypeEntry(); QString typeName = trueType->qualifiedCppName(); diff --git a/sources/shiboken2/shiboken_version.py b/sources/shiboken2/shiboken_version.py index 789812464..a883bab96 100644 --- a/sources/shiboken2/shiboken_version.py +++ b/sources/shiboken2/shiboken_version.py @@ -38,16 +38,10 @@ ############################################################################# major_version = "5" -minor_version = "11" -patch_version = "1" - -# For example: "a", "b", "rc" -# (which means "alpha", "beta", "release candidate"). -# An empty string means the generated package will be an official release. -pre_release_version_type = "a" - -# For example: "1", "2" (which means "beta1", "beta2", if type is "b"). -pre_release_version = "1" +minor_version = "12" +patch_version = "0" +pre_release_version_type = "a" # e.g. "a", "b", "rc". +pre_release_version = "1" # e.g "1", "2", (which means "beta1", "beta2", if type is "b") if __name__ == '__main__': # Used by CMake. diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 5f0a9206b..a55c4fe1e 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -1964,7 +1964,7 @@ <define-ownership owner="c++"/> </modify-argument> </modify-function> - <modify-function signature="acceptSequence(const char*[])"> + <modify-function signature="acceptSequence(const char*const[])"> <modify-argument index="1"> <replace-type modified-type="PySequence" /> <conversion-rule class="native"> |