aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor
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 /sources/shiboken2/ApiExtractor
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>
Diffstat (limited to 'sources/shiboken2/ApiExtractor')
-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
4 files changed, 82 insertions, 75 deletions
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()