diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-10-23 10:55:35 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-10-28 13:38:34 +0000 |
| commit | 8d2aa4264ce2eef7b465c1917ca027eea294747e (patch) | |
| tree | 93e9b72309172a93b6483cd636f01a4c4c06480f /sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp | |
| parent | a26b04fae0f055d7590c9e7380afe7a5fb67c58e (diff) | |
shiboken2: Handle operators written as hidden friends
qtbase/f7f1a71ea41579c1ff86c08c16b82e4c84bc891f changed some operators
to be hidden friends, which causes them to become invisible.
Detecting them requires parsing friend declarations and turning on
parsing of function bodies for clang_isCursorDefinition() being able
to tell a definition.
Fixes a number of tests failing (qlinef_test, qsize_test, repr_test,
unaryoperator_test).
Change-Id: I4d3107181b942efebd785cfae7c3fd1b6f0963ac
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 | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp index dd0aca407..a90adca17 100644 --- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp @@ -230,6 +230,7 @@ public: int m_anonymousEnumCount = 0; CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; + bool m_withinFriendDecl = false; }; bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t) @@ -964,14 +965,14 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) case CXCursor_ClassDecl: case CXCursor_UnionDecl: case CXCursor_StructDecl: - if (clang_isCursorDefinition(cursor) == 0) + if (d->m_withinFriendDecl || clang_isCursorDefinition(cursor) == 0) return Skip; if (!d->addClass(cursor, codeModelClassTypeFromCursor(cursor.kind))) return Error; break; case CXCursor_ClassTemplate: case CXCursor_ClassTemplatePartialSpecialization: - if (clang_isCursorDefinition(cursor) == 0) + if (d->m_withinFriendDecl || clang_isCursorDefinition(cursor) == 0) return Skip; d->addClass(cursor, CodeModel::Class); d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); @@ -1028,16 +1029,18 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) case CXCursor_FieldDecl: d->addField(cursor); break; -#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 37 // Clang 4.0 case CXCursor_FriendDecl: + d->m_withinFriendDecl = true; + break; + case CXCursor_CompoundStmt: // Function bodies return Skip; -#endif case CXCursor_Constructor: case CXCursor_Destructor: // Note: Also use clang_CXXConstructor_is..Constructor? case CXCursor_CXXMethod: case CXCursor_ConversionFunction: + // Member functions of other classes can be declared to be friends. // Skip inline member functions outside class, only go by declarations inside class - if (!withinClassDeclaration(cursor)) + if (d->m_withinFriendDecl || !withinClassDeclaration(cursor)) return Skip; d->m_currentFunction = d->createMemberFunction(cursor, false); d->m_scopeStack.back()->addFunction(d->m_currentFunction); @@ -1059,8 +1062,19 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) d->m_scopeStack.back()->addFunction(d->m_currentFunction); break; case CXCursor_FunctionDecl: - d->m_currentFunction = d->createFunction(cursor, CodeModel::Normal, false); - d->m_scopeStack.back()->addFunction(d->m_currentFunction); + // Free functions or functions completely defined within "friend" (class + // operators). Note: CXTranslationUnit_SkipFunctionBodies must be off for + // clang_isCursorDefinition() to work here. + if (!d->m_withinFriendDecl || clang_isCursorDefinition(cursor) != 0) { + int scope = d->m_scopeStack.size() - 1; // enclosing class + if (d->m_withinFriendDecl) { + // Friend declaration: go back to namespace or file scope. + for (--scope; d->m_scopeStack.at(scope)->kind() == _CodeModelItem::Kind_Class; --scope) { + } + } + d->m_currentFunction = d->createFunction(cursor, CodeModel::Normal, false); + d->m_scopeStack.at(scope)->addFunction(d->m_currentFunction); + } break; case CXCursor_Namespace: { const auto type = namespaceType(cursor); @@ -1212,6 +1226,9 @@ bool Builder::endToken(const CXCursor &cursor) d->m_scopeStack.back()->addEnum(d->m_currentEnum); d->m_currentEnum.clear(); break; + case CXCursor_FriendDecl: + d->m_withinFriendDecl = false; + break; case CXCursor_VarDecl: case CXCursor_FieldDecl: d->m_currentField.clear(); |
