C++: cache fully qualified name lookupus in scopes.

Task-number: QTCREATORBUG-8724

Change-Id: I00b0712cf5514bcec04b674052ad4b5b66cca506
Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Erik Verbruggen
2013-03-01 18:02:50 +01:00
committed by Erik Verbruggen
parent 413b153b30
commit c3f907416f
2 changed files with 74 additions and 21 deletions

View File

@@ -92,7 +92,7 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names)
namespace CPlusPlus {
bool compareName(const Name *name, const Name *other)
static inline bool compareName(const Name *name, const Name *other)
{
if (name == other)
return true;
@@ -123,6 +123,30 @@ bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<cons
}
namespace CPlusPlus {
namespace Internal {
bool operator==(const FullyQualifiedName &left, const FullyQualifiedName &right)
{
return compareFullyQualifiedName(left.fqn, right.fqn);
}
uint qHash(const FullyQualifiedName &fullyQualifiedName)
{
uint h = 0;
for (int i = 0; i < fullyQualifiedName.fqn.size(); ++i) {
if (const Name *n = fullyQualifiedName.fqn.at(i)) {
if (const Identifier *id = n->identifier()) {
h <<= 1;
h += id->hashCode();
}
}
}
return h;
}
}
}
/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
@@ -393,13 +417,22 @@ ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
}
ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
: _factory(factory), _parent(parent), _templateId(0), _instantiationOrigin(0)
: _factory(factory)
, _parent(parent)
, _scopeLookupCache(0)
, _templateId(0)
, _instantiationOrigin(0)
#ifdef DEBUG_LOOKUP
, _name(0)
#endif // DEBUG_LOOKUP
{
}
ClassOrNamespace::~ClassOrNamespace()
{
delete _scopeLookupCache;
}
const TemplateNameId *ClassOrNamespace::templateId() const
{
return _templateId;
@@ -464,7 +497,7 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
if (name) {
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base())
if (! q->base()) // e.g. ::std::string
result = globalNamespace()->find(q->name());
else if (ClassOrNamespace *binding = lookupType(q->base())) {
@@ -477,23 +510,10 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
// a qualified name. For instance, a nested class which is forward declared
// in the class but defined outside it - we should capture both.
Symbol *match = 0;
ClassOrNamespace *parentBinding = binding->parent();
while (parentBinding && !match) {
for (int j = 0; j < parentBinding->symbols().size() && !match; ++j) {
if (Scope *scope = parentBinding->symbols().at(j)->asScope()) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *candidate = scope->memberAt(i);
if (compareFullyQualifiedName(
fullName,
LookupContext::fullyQualifiedName(candidate))) {
match = candidate;
break;
}
}
}
}
parentBinding = parentBinding->parent();
}
for (ClassOrNamespace *parentBinding = binding->parent();
parentBinding && !match;
parentBinding = parentBinding->parent())
match = parentBinding->lookupInScope(fullName);
if (match) {
LookupItem item;
@@ -634,6 +654,24 @@ ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this);
}
Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName)
{
if (!_scopeLookupCache) {
_scopeLookupCache = new QHash<Internal::FullyQualifiedName, Symbol *>;
for (int j = 0; j < symbols().size(); ++j) {
if (Scope *scope = symbols().at(j)->asScope()) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *s = scope->memberAt(i);
_scopeLookupCache->insert(LookupContext::fullyQualifiedName(s), s);
}
}
}
}
return _scopeLookupCache->value(fullName, 0);
}
ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope,