diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-02-12 11:39:36 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-03-01 16:28:48 +0100 |
| commit | 2107b9c16d7be1292c5439a47ed31871906e0b1f (patch) | |
| tree | 64447316e8885d4bcf3a45c6657eb7372c60c67c /sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp | |
| parent | c6f4d907190dbd66d09db7d4809c06f1b3e48ec2 (diff) | |
shiboken6: Add constructors of base classes imported via "using"
Parse "using" declarations in the clang builder using some code
from the base class determination algorithm.
Resolve them to struct UsingMember containing the base class
and the member name in the metabuilder and check whether any
base constructors are imported via "using". Add them
as functions like the default constructor.
Change-Id: I121a70f0591c6d1e6f9daedfb653206c49c07a3f
Reviewed-by: Christian Tismer <tismer@stackless.com>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp')
| -rw-r--r-- | sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp index 2970507ec..de0f2eb4f 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp @@ -196,6 +196,7 @@ public: void addField(const CXCursor &cursor); static QString cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor); + QString getBaseClassName(CXType type) const; void addBaseClass(const CXCursor &cursor); template <class Item> @@ -227,6 +228,8 @@ public: TemplateTypeAliasModelItem m_currentTemplateTypeAlias; QByteArrayList m_systemIncludes; // files, like "memory" QByteArrayList m_systemIncludePaths; // paths, like "/usr/include/Qt/" + QString m_usingTypeRef; // Base classes in "using Base::member;" + bool m_withinUsingDeclaration = false; int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; @@ -670,7 +673,7 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c qsizetype(snippet.size() - equalSign)).trimmed(); } -// Resolve declaration and type of a base class +// Resolve a type (loop over aliases/typedefs), for example for base classes struct TypeDeclaration { @@ -678,30 +681,28 @@ struct TypeDeclaration CXCursor declaration; }; -static TypeDeclaration resolveBaseSpecifier(const CXCursor &cursor) +static TypeDeclaration resolveType(CXType type) { - Q_ASSERT(clang_getCursorKind(cursor) == CXCursor_CXXBaseSpecifier); - CXType inheritedType = clang_getCursorType(cursor); - CXCursor decl = clang_getTypeDeclaration(inheritedType); - if (inheritedType.kind != CXType_Unexposed) { + CXCursor decl = clang_getTypeDeclaration(type); + if (type.kind != CXType_Unexposed) { while (true) { auto kind = clang_getCursorKind(decl); if (kind != CXCursor_TypeAliasDecl && kind != CXCursor_TypedefDecl) break; - inheritedType = clang_getTypedefDeclUnderlyingType(decl); - decl = clang_getTypeDeclaration(inheritedType); + type = clang_getTypedefDeclUnderlyingType(decl); + decl = clang_getTypeDeclaration(type); } } - return {inheritedType, decl}; + return {type, decl}; } -// Add a base class to the current class from CXCursor_CXXBaseSpecifier -void BuilderPrivate::addBaseClass(const CXCursor &cursor) +// Note: Return the baseclass for cursors like CXCursor_CXXBaseSpecifier, +// where the cursor spelling has "struct baseClass". +QString BuilderPrivate::getBaseClassName(CXType type) const { - Q_ASSERT(clang_getCursorKind(cursor) == CXCursor_CXXBaseSpecifier); + const auto decl = resolveType(type); // Note: spelling has "struct baseClass", use type QString baseClassName; - const auto decl = resolveBaseSpecifier(cursor); if (decl.type.kind == CXType_Unexposed) { // The type is unexposed when the base class is a template type alias: // "class QItemSelection : public QList<X>" where QList is aliased to QVector. @@ -716,13 +717,12 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) baseClassName = getTypeName(decl.type); auto it = m_cursorClassHash.constFind(decl.declaration); - const Access access = accessPolicy(clang_getCXXAccessSpecifier(cursor)); - if (it == m_cursorClassHash.constEnd()) { - // Set unqualified name. This happens in cases like "class X : public std::list<...>" - // "template<class T> class Foo : public T" and standard types like true_type, false_type. - m_currentClass->addBaseClass(baseClassName, access); - return; - } + // Not found: Set unqualified name. This happens in cases like + // "class X : public std::list<...>", "template<class T> class Foo : public T" + // and standard types like true_type, false_type. + if (it == m_cursorClassHash.constEnd()) + return baseClassName; + // Completely qualify the class name by looking it up and taking its scope // plus the actual baseClass stripped off any scopes. Consider: // namespace std { @@ -741,6 +741,15 @@ void BuilderPrivate::addBaseClass(const CXCursor &cursor) baseClassName.prepend(colonColon()); baseClassName.prepend(baseScope.join(colonColon())); } + return baseClassName; +} + +// Add a base class to the current class from CXCursor_CXXBaseSpecifier +void BuilderPrivate::addBaseClass(const CXCursor &cursor) +{ + Q_ASSERT(clang_getCursorKind(cursor) == CXCursor_CXXBaseSpecifier); + const auto access = accessPolicy(clang_getCXXAccessSpecifier(cursor)); + QString baseClassName = getBaseClassName(clang_getCursorType(cursor)); m_currentClass->addBaseClass(baseClassName, access); } @@ -1173,6 +1182,15 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) return Skip; } break; + // Using declarations look as follows: + // 1) Normal, non-template case ("using QObject::parent"): UsingDeclaration, TypeRef + // 2) Simple template case ("using QList::append()"): UsingDeclaration, TypeRef "QList<T>" + // 3) Template case with parameters ("using QList<T>::append()"): + // UsingDeclaration, TemplateRef "QList", TypeRef "T" + case CXCursor_TemplateRef: + if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) + d->m_usingTypeRef = getCursorSpelling(cursor); + break; case CXCursor_TypeRef: if (!d->m_currentFunction.isNull()) { if (d->m_currentArgument.isNull()) @@ -1181,6 +1199,8 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->qualifyTypeDef(cursor, d->m_currentArgument); } else if (!d->m_currentField.isNull()) { d->qualifyTypeDef(cursor, d->m_currentField); + } else if (d->m_withinUsingDeclaration && d->m_usingTypeRef.isEmpty()) { + d->m_usingTypeRef = d->getBaseClassName(clang_getCursorType(cursor)); } break; case CXCursor_CXXFinalAttr: @@ -1206,6 +1226,20 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) } } break; + // UsingDeclaration: consists of a TypeRef (base) and OverloadedDeclRef (member name) + case CXCursor_UsingDeclaration: + if (!d->m_currentClass.isNull()) + d->m_withinUsingDeclaration = true; + break; + case CXCursor_OverloadedDeclRef: + if (d->m_withinUsingDeclaration && !d->m_usingTypeRef.isEmpty()) { + QString member = getCursorSpelling(cursor); + if (member == d->m_currentClass->name()) + member = d->m_usingTypeRef; // Overloaded member is Constructor, use base + const auto ap = accessPolicy(clang_getCXXAccessSpecifier(cursor)); + d->m_currentClass->addUsingMember(d->m_usingTypeRef, member, ap); + } + break; default: break; } @@ -1273,6 +1307,10 @@ bool Builder::endToken(const CXCursor &cursor) case CXCursor_TypeAliasTemplateDecl: d->m_currentTemplateTypeAlias.reset(); break; + case CXCursor_UsingDeclaration: + d->m_withinUsingDeclaration = false; + d->m_usingTypeRef.clear(); + break; default: break; } |
