diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 4562d41346fe5b58ffed35c4163c25c1932d6e0a..d747481dca9841922a8bf3f44a5a762033ec45a9 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -92,7 +92,7 @@ static void path_helper(Symbol *symbol, QList *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 &path, const QListidentifier()) { + 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 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 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 &fullName) +{ + if (!_scopeLookupCache) { + _scopeLookupCache = new QHash; + + 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 *processed, bool searchInEnclosingScope, diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 88506c1e8f953eb7e3bae86bf6850b3b5c5c600c..d7f3b54285a3473ef199edd2905bb0ad8306ab4a 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -45,12 +45,24 @@ namespace CPlusPlus { +namespace Internal { +struct FullyQualifiedName +{ + QList fqn; + + FullyQualifiedName(const QList &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 &fullName); + private: typedef std::map Table; typedef std::map TemplateNameIdTable; @@ -115,6 +129,8 @@ private: TemplateNameIdTable _specializations; QMap _instantiations; + QHash *_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 &path, const QList &other);