diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-07-05 12:54:25 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-07-11 19:01:58 +0000 |
commit | 612bfd01e1e7698cb3a06d619cc7d7c7acd3d273 (patch) | |
tree | dd9aa2aacd81e9045ba6708a4117e503cf3f9bca /sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp | |
parent | f2443b02fce5dd4182e80ed0e5343586cbd72a31 (diff) |
shiboken: Move detection of template arguments to ClangBuilder
Obtain the template arguments from Clang and fall back to parsing
the type name where this is not possible (which may be the case
inside a template declaration).
The string-based formatting and re-parsing of the type in
AbstractMetaBuilder::translateType() can then be removed, opening
the way to passing up more complex types from Clang into the
MetaBuilder.
Task-number: PYSIDE-672
Change-Id: I43ff285c5f3720319bf40c65b1c27302ef1b934e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index 23ccf5d88..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; @@ -391,6 +395,54 @@ 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. @@ -440,6 +492,11 @@ TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const || TypeInfo::stripLeadingVolatile(&typeName)) { } + // 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? return typeInfo; |