Commit c3f90741 authored by Erik Verbruggen's avatar Erik Verbruggen Committed by Erik Verbruggen

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

Task-number: QTCREATORBUG-8724

Change-Id: I00b0712cf5514bcec04b674052ad4b5b66cca506
Reviewed-by: default avatarPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent 413b153b
......@@ -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,
......
......@@ -45,12 +45,24 @@
namespace CPlusPlus {
namespace Internal {
struct FullyQualifiedName
{
QList<const Name *> fqn;
FullyQualifiedName(const QList<const Name *> &fqn)
: fqn(fqn)
{}
};
} // namespace Internal;
class CreateBindings;
class CPLUSPLUS_EXPORT ClassOrNamespace
{
public:
ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
~ClassOrNamespace();
const TemplateNameId *templateId() const;
ClassOrNamespace *instantiationOrigin() const;
......@@ -68,6 +80,8 @@ public:
ClassOrNamespace *lookupType(const Name *name);
ClassOrNamespace *findType(const Name *name);
Symbol *lookupInScope(const QList<const Name *> &fullName);
private:
typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable;
......@@ -115,6 +129,8 @@ private:
TemplateNameIdTable _specializations;
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
// it's an instantiation.
const TemplateNameId *_templateId;
ClassOrNamespace *_instantiationOrigin;
......@@ -308,7 +324,6 @@ private:
bool m_expandTemplates;
};
bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other);
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
const QList<const Name *> &other);
......
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