Commit b61dbac6 authored by Leandro Melo's avatar Leandro Melo
Browse files

Fix potential endless recursion in C++ hover handler.

To catch cases of invalid code like this:
struct A : B {};
struct B : A {};

Reviewed-by: Roberto Raggi
parent 6c009f19
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
#include <cplusplus/LookupItem.h> #include <cplusplus/LookupItem.h>
#include <QtCore/QSet>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QtAlgorithms> #include <QtCore/QtAlgorithms>
...@@ -82,24 +83,30 @@ namespace { ...@@ -82,24 +83,30 @@ namespace {
} }
} }
void buildClassHierarchyHelper(Symbol *symbol, void buildClassHierarchyHelper(ClassOrNamespace *classSymbol,
const LookupContext &context, const LookupContext &context,
const Overview &overview, const Overview &overview,
QList<QStringList> *hierarchy) { QList<QStringList> *hierarchy,
if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) { QSet<ClassOrNamespace *> *visited) {
const QList<ClassOrNamespace *> &bases = classSymbol->usings(); visited->insert(classSymbol);
foreach (ClassOrNamespace *baseClass, bases) { const QList<ClassOrNamespace *> &bases = classSymbol->usings();
const QList<Symbol *> &symbols = baseClass->symbols(); foreach (ClassOrNamespace *baseClass, bases) {
foreach (Symbol *baseSymbol, symbols) { const QList<Symbol *> &symbols = baseClass->symbols();
if (baseSymbol->isClass()) { foreach (Symbol *baseSymbol, symbols) {
const QString &qualifiedName = overview.prettyName( if (baseSymbol->isClass() && (
LookupContext::fullyQualifiedName(baseSymbol)); classSymbol = context.lookupType(baseSymbol)) &&
if (!qualifiedName.isEmpty()) { !visited->contains(classSymbol)) {
hierarchy->back().append(qualifiedName); const QString &qualifiedName = overview.prettyName(
buildClassHierarchyHelper(baseSymbol, context, overview, hierarchy); LookupContext::fullyQualifiedName(baseSymbol));
hierarchy->append(hierarchy->back()); if (!qualifiedName.isEmpty()) {
hierarchy->back().removeLast(); hierarchy->back().append(qualifiedName);
} buildClassHierarchyHelper(classSymbol,
context,
overview,
hierarchy,
visited);
hierarchy->append(hierarchy->back());
hierarchy->back().removeLast();
} }
} }
} }
...@@ -110,10 +117,12 @@ namespace { ...@@ -110,10 +117,12 @@ namespace {
const LookupContext &context, const LookupContext &context,
const Overview &overview, const Overview &overview,
QList<QStringList> *hierarchy) { QList<QStringList> *hierarchy) {
if (hierarchy->isEmpty()) if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) {
hierarchy->append(QStringList()); hierarchy->append(QStringList());
buildClassHierarchyHelper(symbol, context, overview, hierarchy); QSet<ClassOrNamespace *> visited;
hierarchy->removeLast(); buildClassHierarchyHelper(classSymbol, context, overview, hierarchy, &visited);
hierarchy->removeLast();
}
} }
struct ClassHierarchyComp struct ClassHierarchyComp
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment