aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-12-14 18:06:32 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-12-21 16:19:43 +0100
commitdacd0e5f2c087478029b68d0b65ead7ba8a49e81 (patch)
tree2e439ba1faffc3500d27e9a80e499242aeefdc17 /sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
parent29dc723178da673139057389d78ff3f9bb17a08d (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.cpp97
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)