diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-07-04 13:01:46 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-07-11 19:01:53 +0000 |
commit | f2443b02fce5dd4182e80ed0e5343586cbd72a31 (patch) | |
tree | 31745405aa0f8f17b5339fe145134c31da150d4a /sources | |
parent | 0a8e37cd60863773940d9d7f21403a841d744720 (diff) |
shiboken: Improve const handling
- Use new enum in code.
- Rewrite the Clang type parsing to make use of it.
- Adapt some typesystem files.
This enables the distinction between "int *" and "int *const"
and fixes the signatures from "int const &" to the more common "const int&".
Task-number: PYSIDE-672
Change-Id: Ic1bff0015188c32f53d0e6f347b1523254cb7e4f
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources')
9 files changed, 102 insertions, 104 deletions
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/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index af7f96068..23ccf5d88 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -359,38 +359,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 +380,17 @@ 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; +} + TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const { if (type.kind == CXType_Pointer) { // Check for function pointers, first. @@ -427,50 +406,39 @@ 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); - // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *" - if (typeName.startsWith(QLatin1String("volatile "))) { - typeName.remove(0, 9); - typeInfo.setVolatile(true); - } + typeInfo.setConstant(clang_isConstQualifiedType(nestedType) != 0); + typeInfo.setVolatile(clang_isVolatileQualifiedType(nestedType) != 0); - typeName = typeName.trimmed(); + QString typeName = getTypeName(nestedType); + while (TypeInfo::stripLeadingConst(&typeName) + || TypeInfo::stripLeadingVolatile(&typeName)) { + } typeInfo.setQualifiedName(qualifiedName(typeName)); // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types? diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 4ad86bd15..d3ada9235 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -198,13 +198,13 @@ TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, Cod 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 "); + + tmp += m_qualifiedName.join(QLatin1String("::")); if (const int instantiationCount = m_instantiations.size()) { tmp += QLatin1Char('<'); @@ -276,7 +276,34 @@ bool TypeInfo::operator==(const TypeInfo &other) const QString TypeInfo::indirectionKeyword(Indirection i) { return i == Indirection::Pointer - ? QStringLiteral("*") : QStringLiteral("* const"); + ? 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 diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 1bc3e6e12..d0381c4e3 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -169,6 +169,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); @@ -203,6 +205,10 @@ public: static QString indirectionKeyword(Indirection i); + static bool stripLeadingConst(QString *s); + static bool stripLeadingVolatile(QString *s); + static bool stripLeadingQualifier(const QString &qualifier, QString *s); + private: static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope); diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp index 3f31f06e0..86bf64495 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp @@ -44,6 +44,12 @@ void TestAbstractMetaType::parsing_data() << 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() 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"> |