From 636b9a4bd5624d8ddb00da53b16add546e3944c4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 26 Oct 2020 14:16:11 +0100 Subject: shiboken2: Handle typedefs of template parameters within templates Typedefs of template parameters like template class QList { using reference = T&; are reported as "type-parameter-0-0" by clang. Resolve that to the proper name of the template parameter in the clang builder. Also, these typeinfo results must not be cached since the same CXType is used for parameters of unrelated templates. Rename the createTypeInfoHelper() function to createTypeInfoUncached() for clarity and introduce a cacheable parameter. Change-Id: I2b21a4dfdd8d86cf36497832837c21f37cb86518 Reviewed-by: Christian Tismer --- .../ApiExtractor/clangparser/clangbuilder.cpp | 58 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 11 deletions(-) (limited to 'sources') diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index 944445579..dd0aca407 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -176,7 +176,8 @@ public: FunctionModelItem createMemberFunction(const CXCursor &cursor, bool isTemplateCode = false); void qualifyConstructor(const CXCursor &cursor); - TypeInfo createTypeInfoHelper(const CXType &type) const; // uncashed + TypeInfo createTypeInfoUncached(const CXType &type, + bool *cacheable = nullptr) const; TypeInfo createTypeInfo(const CXType &type) const; TypeInfo createTypeInfo(const CXCursor &cursor) const { return createTypeInfo(clang_getCursorType(cursor)); } @@ -186,6 +187,7 @@ public: bool addTemplateInstantiationsRecursion(const CXType &type, TypeInfo *t) const; void addTypeDef(const CXCursor &cursor, const CXType &cxType); + ClassModelItem currentTemplateClass() const; void startTemplateTypeAlias(const CXCursor &cursor); void endTemplateTypeAlias(const CXCursor &typeAliasCursor); @@ -333,7 +335,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, name = fixTypeName(name); FunctionModelItem result(new _FunctionModelItem(m_model, name)); setFileName(cursor, result.data()); - result->setType(createTypeInfoHelper(clang_getCursorResultType(cursor))); + result->setType(createTypeInfo(clang_getCursorResultType(cursor))); result->setFunctionType(t); result->setScope(m_scope); result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); @@ -415,7 +417,7 @@ TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCurso TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const { TemplateParameterModelItem result = createTemplateParameter(cursor); - result->setType(createTypeInfoHelper(clang_getCursorType(cursor))); + result->setType(createTypeInfo(clang_getCursorType(cursor))); return result; } @@ -477,7 +479,7 @@ bool BuilderPrivate::addTemplateInstantiationsRecursion(const CXType &type, Type // of a non-type template (template ). if (argType.kind == CXType_Invalid) return false; - t->addInstantiation(createTypeInfoHelper(argType)); + t->addInstantiation(createTypeInfoUncached(argType)); } } break; @@ -513,16 +515,19 @@ void BuilderPrivate::addTemplateInstantiations(const CXType &type, typeName->remove(pos.first, pos.second - pos.first); } -TypeInfo BuilderPrivate::createTypeInfoHelper(const CXType &type) const +TypeInfo BuilderPrivate::createTypeInfoUncached(const CXType &type, + bool *cacheable) const { if (type.kind == CXType_Pointer) { // Check for function pointers, first. const CXType pointeeType = clang_getPointeeType(type); const int argCount = clang_getNumArgTypes(pointeeType); if (argCount >= 0) { - TypeInfo result = createTypeInfoHelper(clang_getResultType(pointeeType)); + TypeInfo result = createTypeInfoUncached(clang_getResultType(pointeeType), + cacheable); result.setFunctionPointer(true); for (int a = 0; a < argCount; ++a) - result.addArgument(createTypeInfoHelper(clang_getArgType(pointeeType, unsigned(a)))); + result.addArgument(createTypeInfoUncached(clang_getArgType(pointeeType, unsigned(a)), + cacheable)); return result; } } @@ -562,6 +567,23 @@ TypeInfo BuilderPrivate::createTypeInfoHelper(const CXType &type) const || TypeInfo::stripLeadingVolatile(&typeName)) { } + // For typedefs within templates or nested classes within templates (iterators): + // "template class QList { using Value=T; .." + // the typedef source is named "type-parameter-0-0". Convert it back to the + // template parameter name. The CXTypes are the same for all templates and + // must not be cached. + if (!m_currentClass.isNull() && typeName.startsWith(QLatin1String("type-parameter-0-"))) { + if (cacheable != nullptr) + *cacheable = false; + bool ok; + const int n = QStringView{typeName}.mid(17).toInt(&ok); + if (ok) { + auto currentTemplate = currentTemplateClass(); + if (!currentTemplate.isNull() && n < currentTemplate->templateParameters().size()) + typeName = currentTemplate->templateParameters().at(n)->name(); + } + } + // Obtain template instantiations if the name has '<' (thus excluding // typedefs like "std::string". if (typeName.contains(QLatin1Char('<'))) @@ -575,10 +597,14 @@ TypeInfo BuilderPrivate::createTypeInfoHelper(const CXType &type) const TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const { - TypeInfoHash::iterator it = m_typeInfoHash.find(type); - if (it == m_typeInfoHash.end()) - it = m_typeInfoHash.insert(type, createTypeInfoHelper(type)); - return it.value(); + const auto it = m_typeInfoHash.constFind(type); + if (it != m_typeInfoHash.constEnd()) + return it.value(); + bool cacheable = true; + TypeInfo result = createTypeInfoUncached(type, &cacheable); + if (cacheable) + m_typeInfoHash.insert(type, result); + return result; } void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType) @@ -592,6 +618,16 @@ void BuilderPrivate::addTypeDef(const CXCursor &cursor, const CXType &cxType) m_cursorTypedefHash.insert(cursor, item); } +ClassModelItem BuilderPrivate::currentTemplateClass() const +{ + for (int i = m_scopeStack.size() - 1; i >= 0; --i) { + auto klass = qSharedPointerDynamicCast<_ClassModelItem>(m_scopeStack.at(i)); + if (!klass.isNull() && klass->isTemplate()) + return klass; + } + return {}; +} + void BuilderPrivate::startTemplateTypeAlias(const CXCursor &cursor) { const QString target = getCursorSpelling(cursor); -- cgit v1.2.3