aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-07-04 13:01:46 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-07-11 19:01:53 +0000
commitf2443b02fce5dd4182e80ed0e5343586cbd72a31 (patch)
tree31745405aa0f8f17b5339fe145134c31da150d4a
parent0a8e37cd60863773940d9d7f21403a841d744720 (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>
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml16
-rw-r--r--sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml27
-rw-r--r--sources/pyside2/PySide2/QtQml/typesystem_qml.xml2
-rw-r--r--sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml2
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp108
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp37
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h6
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp6
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml2
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 eee22b55..b679abc8 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 ea5c24cd..d04d2f67 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 4ca776e1..5103b921 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 f4e69087..2ac15080 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&amp;)const" remove="all" />
<modify-function signature="compareOrder(const QXmlNodeModelIndex &amp;)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 af7f9606..23ccf5d8 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 4ad86bd1..d3ada923 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 1bc3e6e1..d0381c4e 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 3f31f06e..86bf6449 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 5f0a9206..a55c4fe1 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">