forked from qt-creator/qt-creator
CppTypeHierarchy: Don't keep pointers to temp objects
When building type hierarchy the pointers to list elements were put into queue. Later, the list was modified and it was possible that list detaches causing stored pointers to be invalid. Simplify building type hierarchy by adding helper recursive methods. Fixes: QTCREATORBUG-28529 Change-Id: I240513fc097536d2175e2242766127b92aaa6a82 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -433,7 +433,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
|||||||
{
|
{
|
||||||
QList<LookupItem> candidates;
|
QList<LookupItem> candidates;
|
||||||
|
|
||||||
if (! name)
|
if (!name)
|
||||||
return candidates;
|
return candidates;
|
||||||
|
|
||||||
for (; scope; scope = scope->enclosingScope()) {
|
for (; scope; scope = scope->enclosingScope()) {
|
||||||
|
|||||||
@@ -142,32 +142,30 @@ CppClass *CppClass::toCppClass()
|
|||||||
void CppClass::lookupBases(QFutureInterfaceBase &futureInterface,
|
void CppClass::lookupBases(QFutureInterfaceBase &futureInterface,
|
||||||
Symbol *declaration, const LookupContext &context)
|
Symbol *declaration, const LookupContext &context)
|
||||||
{
|
{
|
||||||
using Data = QPair<ClassOrNamespace*, CppClass*>;
|
ClassOrNamespace *hierarchy = context.lookupType(declaration);
|
||||||
|
if (!hierarchy)
|
||||||
if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
|
return;
|
||||||
QSet<ClassOrNamespace *> visited;
|
QSet<ClassOrNamespace *> visited;
|
||||||
|
addBaseHierarchy(futureInterface, context, hierarchy, &visited);
|
||||||
|
}
|
||||||
|
|
||||||
QQueue<Data> q;
|
void CppClass::addBaseHierarchy(QFutureInterfaceBase &futureInterface, const LookupContext &context,
|
||||||
q.enqueue({clazz, this});
|
ClassOrNamespace *hierarchy, QSet<ClassOrNamespace *> *visited)
|
||||||
while (!q.isEmpty()) {
|
{
|
||||||
if (futureInterface.isCanceled())
|
if (futureInterface.isCanceled())
|
||||||
return;
|
return;
|
||||||
Data current = q.dequeue();
|
visited->insert(hierarchy);
|
||||||
clazz = current.first;
|
const QList<ClassOrNamespace *> &baseClasses = hierarchy->usings();
|
||||||
visited.insert(clazz);
|
for (ClassOrNamespace *baseClass : baseClasses) {
|
||||||
const QList<ClassOrNamespace *> &bases = clazz->usings();
|
|
||||||
for (ClassOrNamespace *baseClass : bases) {
|
|
||||||
const QList<Symbol *> &symbols = baseClass->symbols();
|
const QList<Symbol *> &symbols = baseClass->symbols();
|
||||||
for (Symbol *symbol : symbols) {
|
for (Symbol *symbol : symbols) {
|
||||||
if (symbol->asClass() && (
|
if (!symbol->asClass())
|
||||||
clazz = context.lookupType(symbol)) &&
|
continue;
|
||||||
!visited.contains(clazz)) {
|
ClassOrNamespace *baseHierarchy = context.lookupType(symbol);
|
||||||
CppClass baseCppClass(symbol);
|
if (baseHierarchy && !visited->contains(baseHierarchy)) {
|
||||||
CppClass *cppClass = current.second;
|
CppClass classSymbol(symbol);
|
||||||
cppClass->bases.append(baseCppClass);
|
classSymbol.addBaseHierarchy(futureInterface, context, baseHierarchy, visited);
|
||||||
q.enqueue({clazz, &cppClass->bases.last()});
|
bases.append(classSymbol);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,28 +174,20 @@ void CppClass::lookupBases(QFutureInterfaceBase &futureInterface,
|
|||||||
void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface,
|
void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface,
|
||||||
Symbol *declaration, const Snapshot &snapshot)
|
Symbol *declaration, const Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
using Data = QPair<CppClass*, TypeHierarchy>;
|
|
||||||
|
|
||||||
snapshot.updateDependencyTable(futureInterface);
|
snapshot.updateDependencyTable(futureInterface);
|
||||||
if (futureInterface.isCanceled())
|
if (futureInterface.isCanceled())
|
||||||
return;
|
return;
|
||||||
const TypeHierarchy &completeHierarchy
|
addDerivedHierarchy(TypeHierarchyBuilder::buildDerivedTypeHierarchy(
|
||||||
= TypeHierarchyBuilder::buildDerivedTypeHierarchy(futureInterface, declaration, snapshot);
|
futureInterface, declaration, snapshot));
|
||||||
|
}
|
||||||
|
|
||||||
QQueue<Data> q;
|
void CppClass::addDerivedHierarchy(const TypeHierarchy &hierarchy)
|
||||||
q.enqueue({this, completeHierarchy});
|
{
|
||||||
while (!q.isEmpty()) {
|
CppClass classSymbol(hierarchy.symbol());
|
||||||
if (futureInterface.isCanceled())
|
const QList<TypeHierarchy> derivedHierarchies = hierarchy.hierarchy();
|
||||||
return;
|
for (const TypeHierarchy &derivedHierarchy : derivedHierarchies)
|
||||||
const Data ¤t = q.dequeue();
|
classSymbol.addDerivedHierarchy(derivedHierarchy);
|
||||||
CppClass *clazz = current.first;
|
derived.append(classSymbol);
|
||||||
const TypeHierarchy &classHierarchy = current.second;
|
|
||||||
const QList<TypeHierarchy> hierarchy = classHierarchy.hierarchy();
|
|
||||||
for (const TypeHierarchy &derivedHierarchy : hierarchy) {
|
|
||||||
clazz->derived.append(CppClass(derivedHierarchy.symbol()));
|
|
||||||
q.enqueue({&clazz->derived.last(), derivedHierarchy});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CppFunction : public CppDeclarableElement
|
class CppFunction : public CppDeclarableElement
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "typehierarchybuilder.h"
|
||||||
|
|
||||||
#include <coreplugin/helpitem.h>
|
#include <coreplugin/helpitem.h>
|
||||||
|
#include <cplusplus/CppDocument.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <cplusplus/CppDocument.h>
|
|
||||||
|
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QIcon>
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace CPlusPlus {
|
namespace CPlusPlus {
|
||||||
|
class ClassOrNamespace;
|
||||||
class LookupItem;
|
class LookupItem;
|
||||||
class LookupContext;
|
class LookupContext;
|
||||||
}
|
}
|
||||||
@@ -96,9 +97,15 @@ public:
|
|||||||
void lookupDerived(QFutureInterfaceBase &futureInterface,
|
void lookupDerived(QFutureInterfaceBase &futureInterface,
|
||||||
CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot);
|
CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot);
|
||||||
|
|
||||||
public:
|
|
||||||
QList<CppClass> bases;
|
QList<CppClass> bases;
|
||||||
QList<CppClass> derived;
|
QList<CppClass> derived;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addBaseHierarchy(QFutureInterfaceBase &futureInterface,
|
||||||
|
const CPlusPlus::LookupContext &context,
|
||||||
|
CPlusPlus::ClassOrNamespace *hierarchy,
|
||||||
|
QSet<CPlusPlus::ClassOrNamespace *> *visited);
|
||||||
|
void addDerivedHierarchy(const TypeHierarchy &hierarchy);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user