diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-12-14 18:06:32 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-12-21 16:19:43 +0100 |
| commit | dacd0e5f2c087478029b68d0b65ead7ba8a49e81 (patch) | |
| tree | 2e439ba1faffc3500d27e9a80e499242aeefdc17 /sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | |
| parent | 29dc723178da673139057389d78ff3f9bb17a08d (diff) | |
shiboken6: Rewite the graph sorter
Change the Graph used for dependency sorting from a graph
using integer node numbers to a template taking the Node value,
relying on operator==() (and its qDebug() operators).
The mapping of node to indexes can then be removed from the client code,
leading to a significant simplification.
As a side effect, this fixes undefined behavior of the overload
sorter in conjunction with reverse binary operators. It was not handling
overloads of the same decisor argument type correctly, leading to
graphs with duplicated node types for them.
Rewrite the toposort test to be data driven.
Change-Id: Idbe896dc81d7272099db6dab3d2673643fc17401
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 7626f04ac855a56d4b364eac7b8350bdd561fef0)
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp')
| -rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 97 |
1 files changed, 29 insertions, 68 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 5e914a989..ad354d901 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -2998,55 +2998,29 @@ void AbstractMetaBuilderPrivate::dumpLog() const writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_fields.log"), m_rejectedFields); } -using ClassIndexHash = QHash<const AbstractMetaClass *, int>; - -static ClassIndexHash::ConstIterator findByTypeEntry(const ClassIndexHash &map, - const TypeEntry *typeEntry) -{ - auto it = map.cbegin(); - for (auto end = map.cend(); it != end; ++it) { - if (it.key()->typeEntry() == typeEntry) - break; - } - return it; -} +using ClassGraph = Graph<AbstractMetaClass *>; // Add a dependency of the class associated with typeEntry on clazz -static void addClassDependency(const TypeEntry *typeEntry, - const AbstractMetaClass *clazz, - int classIndex, const ClassIndexHash &map, - Graph *graph) +static bool addClassDependency(const AbstractMetaClassList &classList, + const TypeEntry *typeEntry, + AbstractMetaClass *clazz, + ClassGraph *graph) { - if (typeEntry->isComplex() && typeEntry != clazz->typeEntry()) { - const auto it = findByTypeEntry(map, typeEntry); - if (it != map.cend() && it.key()->enclosingClass() != clazz) - graph->addEdge(it.value(), classIndex); - } + if (!typeEntry->isComplex() || typeEntry == clazz->typeEntry()) + return false; + const auto c = AbstractMetaClass::findClass(classList, typeEntry); + if (c == nullptr || c->enclosingClass() == clazz) + return false; + return graph->addEdge(c, clazz); } AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassList &classList, const Dependencies &additionalDependencies) const { - ClassIndexHash map; - QHash<int, AbstractMetaClass *> reverseMap; - - int i = 0; - for (AbstractMetaClass *clazz : classList) { - if (map.contains(clazz)) - continue; - map.insert(clazz, i); - reverseMap.insert(i, clazz); - i++; - } - - Graph graph(map.count()); + ClassGraph graph(classList.cbegin(), classList.cend()); for (const auto &dep : additionalDependencies) { - const int parentIndex = map.value(dep.parent, -1); - const int childIndex = map.value(dep.child, -1); - if (parentIndex >= 0 && childIndex >= 0) { - graph.addEdge(parentIndex, childIndex); - } else { + if (!graph.addEdge(dep.parent, dep.child)) { qCWarning(lcShiboken).noquote().nospace() << "AbstractMetaBuilder::classesTopologicalSorted(): Invalid additional dependency: " << dep.child->name() << " -> " << dep.parent->name() << '.'; @@ -3054,19 +3028,14 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } for (AbstractMetaClass *clazz : classList) { - const int classIndex = map.value(clazz); - if (auto enclosing = clazz->enclosingClass()) { - const auto enclosingIt = map.constFind(const_cast< AbstractMetaClass *>(enclosing)); - if (enclosingIt!= map.cend()) - graph.addEdge(enclosingIt.value(), classIndex); + if (auto enclosingC = clazz->enclosingClass()) { + auto enclosing = const_cast<AbstractMetaClass *>(enclosingC); + graph.addEdge(enclosing, clazz); } const AbstractMetaClassList &bases = getBaseClasses(clazz); - for (AbstractMetaClass *baseClass : bases) { - const auto baseIt = map.constFind(baseClass); - if (baseIt!= map.cend()) - graph.addEdge(baseIt.value(), classIndex); - } + for (AbstractMetaClass *baseClass : bases) + graph.addEdge(baseClass, clazz); for (const auto &func : clazz->functions()) { const AbstractMetaArgumentList &arguments = func->arguments(); @@ -3075,44 +3044,36 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const // ("QString s = QString()"), add a dependency. if (!arg.originalDefaultValueExpression().isEmpty() && arg.type().isValue()) { - addClassDependency(arg.type().typeEntry(), clazz, classIndex, - map, &graph); + addClassDependency(classList, arg.type().typeEntry(), + clazz, &graph); } } } // Member fields need to be initialized for (const AbstractMetaField &field : clazz->fields()) { - addClassDependency(field.type().typeEntry(), clazz, classIndex, - map, &graph); + addClassDependency(classList, field.type().typeEntry(), + clazz, &graph); } } - AbstractMetaClassList result; - const auto unmappedResult = graph.topologicalSort(); - if (!unmappedResult.isValid() && graph.nodeCount()) { + const auto result = graph.topologicalSort(); + if (!result.isValid() && graph.nodeCount()) { QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/cyclic_depXXXXXX.dot")); tempFile.setAutoRemove(false); tempFile.open(); - QHash<int, QString> hash; - for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) - hash.insert(it.value(), it.key()->qualifiedCppName()); - graph.dumpDot(hash, tempFile.fileName()); + graph.dumpDot(tempFile.fileName(), + [] (const AbstractMetaClass *c) { return c->name(); }); QString message; QTextStream str(&message); str << "Cyclic dependency of classes found:"; - for (int c : unmappedResult.cyclic) - str << ' ' << reverseMap.value(c)->name(); + for (auto c : result.cyclic) + str << ' ' << c->name(); str << ". Graph can be found at \"" << QDir::toNativeSeparators(tempFile.fileName()) << '"'; qCWarning(lcShiboken, "%s", qPrintable(message)); - } else { - for (int i : qAsConst(unmappedResult.result)) { - Q_ASSERT(reverseMap.contains(i)); - result << reverseMap[i]; - } } - return result; + return result.result; } void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item) |
