From 05984e71fc1d93dc65bc5aab42b5edea8f66601e Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Thu, 6 May 2010 14:01:38 +0200 Subject: [PATCH] Refactor a bit the lookup, it should simplify template instantiation. --- src/libs/cplusplus/GenTemplateInstance.cpp | 32 +++++++++- src/libs/cplusplus/GenTemplateInstance.h | 8 +-- src/libs/cplusplus/LookupContext.cpp | 69 ++++++++++++++++++---- src/libs/cplusplus/LookupContext.h | 20 +++++-- src/libs/cplusplus/ResolveExpression.cpp | 44 +------------- 5 files changed, 110 insertions(+), 63 deletions(-) diff --git a/src/libs/cplusplus/GenTemplateInstance.cpp b/src/libs/cplusplus/GenTemplateInstance.cpp index bb6afc6655e..a9191461e13 100644 --- a/src/libs/cplusplus/GenTemplateInstance.cpp +++ b/src/libs/cplusplus/GenTemplateInstance.cpp @@ -369,11 +369,37 @@ GenTemplateInstance::GenTemplateInstance(Control *control, const Substitution &s _substitution(substitution) { } -FullySpecifiedType GenTemplateInstance::operator()(Symbol *symbol) +FullySpecifiedType GenTemplateInstance::gen(Symbol *symbol) { ApplySubstitution o(_control, symbol, _substitution); return o.apply(symbol->type()); } -Control *GenTemplateInstance::control() const -{ return _control; } +FullySpecifiedType GenTemplateInstance::instantiate(const Name *className, Symbol *candidate, Control *control) +{ + if (className) { + if (const TemplateNameId *templId = className->asTemplateNameId()) { + if (Class *klass = candidate->enclosingSymbol()->asClass()) { + GenTemplateInstance::Substitution subst; + + for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { + FullySpecifiedType templArgTy = templId->templateArgumentAt(i); + + if (i < klass->templateParameterCount()) { + const Name *templArgName = klass->templateParameterAt(i)->name(); + + if (templArgName && templArgName->identifier()) { + const Identifier *templArgId = templArgName->identifier(); + subst.append(qMakePair(templArgId, templArgTy)); + } + } + } + + GenTemplateInstance inst(control, subst); + return inst.gen(candidate); + } + } + } + + return candidate->type(); +} diff --git a/src/libs/cplusplus/GenTemplateInstance.h b/src/libs/cplusplus/GenTemplateInstance.h index b667cc2ab41..8d186341dcb 100644 --- a/src/libs/cplusplus/GenTemplateInstance.h +++ b/src/libs/cplusplus/GenTemplateInstance.h @@ -47,11 +47,11 @@ public: typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution; public: - GenTemplateInstance(Control *control, const Substitution &substitution); - - FullySpecifiedType operator()(Symbol *symbol); + static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, Control *control); - Control *control() const; +private: + GenTemplateInstance(Control *control, const Substitution &substitution); + FullySpecifiedType gen(Symbol *symbol); private: Symbol *_symbol; diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 74612de3ba0..33cab4103b5 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -31,6 +31,7 @@ #include "ResolveExpression.h" #include "Overview.h" #include "CppBindings.h" +#include "GenTemplateInstance.h" #include <CoreTypes.h> #include <Symbols.h> @@ -40,6 +41,7 @@ #include <Control.h> #include <QtDebug> +#include <cxxabi.h> //#define CPLUSPLUS_NO_LAZY_LOOKUP @@ -197,7 +199,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const for (; scope; scope = scope->enclosingScope()) { if (id && scope->isBlockScope()) { - ClassOrNamespace::lookup_helper(name, scope, &candidates); + bindings()->lookup_helper(name, scope, &candidates, /*templateId = */ 0); if (! candidates.isEmpty()) break; // it's a local. @@ -221,7 +223,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const } else if (scope->isFunctionScope()) { Function *fun = scope->owner()->asFunction(); - ClassOrNamespace::lookup_helper(name, fun->arguments(), &candidates); + bindings()->lookup_helper(name, fun->arguments(), &candidates, /*templateId = */ 0); if (! candidates.isEmpty()) break; // it's a formal argument. @@ -244,7 +246,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const } else if (scope->isObjCMethodScope()) { ObjCMethod *method = scope->owner()->asObjCMethod(); - ClassOrNamespace::lookup_helper(name, method->arguments(), &candidates); + bindings()->lookup_helper(name, method->arguments(), &candidates, /*templateId = */ 0); if (! candidates.isEmpty()) break; // it's a formal argument. @@ -261,7 +263,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const } ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent) - : _factory(factory), _parent(parent) + : _factory(factory), _parent(parent), _templateId(0) { } @@ -323,7 +325,7 @@ QList<Symbol *> ClassOrNamespace::lookup(const Name *name) QSet<ClassOrNamespace *> processed; ClassOrNamespace *binding = this; do { - lookup_helper(name, binding, &result, &processed); + lookup_helper(name, binding, &result, &processed, /*templateId = */ 0); binding = binding->_parent; } while (binding); @@ -332,7 +334,8 @@ QList<Symbol *> ClassOrNamespace::lookup(const Name *name) void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding, QList<Symbol *> *result, - QSet<ClassOrNamespace *> *processed) + QSet<ClassOrNamespace *> *processed, + const TemplateNameId *templateId) { if (! binding) return; @@ -340,21 +343,30 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding else if (! processed->contains(binding)) { processed->insert(binding); + //Overview oo; + //qDebug() << "search for:" << oo(name) << "template:" << oo(templateId) << "b:" << oo(binding->_templateId); + foreach (Symbol *s, binding->symbols()) { if (ScopedSymbol *scoped = s->asScopedSymbol()) - lookup_helper(name, scoped->members(), result); + _factory->lookup_helper(name, scoped->members(), result, templateId); } foreach (Enum *e, binding->enums()) - lookup_helper(name, e->members(), result); + _factory->lookup_helper(name, e->members(), result, templateId); foreach (ClassOrNamespace *u, binding->usings()) - lookup_helper(name, u, result, processed); + lookup_helper(name, u, result, processed, binding->_templateId); + + //qDebug() << "=======" << oo(name) << "template:" << oo(binding->_templateId); } } -void ClassOrNamespace::lookup_helper(const Name *name, Scope *scope, QList<Symbol *> *result) +void CreateBindings::lookup_helper(const Name *name, Scope *scope, + QList<Symbol *> *result, + const TemplateNameId *templateId) { + Q_UNUSED(templateId); + if (! name) { return; @@ -364,6 +376,7 @@ void ClassOrNamespace::lookup_helper(const Name *name, Scope *scope, QList<Symbo continue; else if (! s->name()->isEqualTo(op)) continue; + result->append(s); } @@ -382,6 +395,7 @@ void ClassOrNamespace::lookup_helper(const Name *name, Scope *scope, QList<Symbo #endif continue; } + result->append(s); } @@ -507,7 +521,28 @@ ClassOrNamespace *ClassOrNamespace::nestedClassOrNamespace(const Name *name) con if (it == _classOrNamespaces.end()) return 0; - return it->second; + ClassOrNamespace *c = it->second; + + if (const TemplateNameId *templId = name->asTemplateNameId()) { + Overview oo; + qDebug() << "search for:" << oo(templId); + + foreach (ClassOrNamespace *i, c->_instantiations) { + if (templId->isEqualTo(i->_templateId)) { + qDebug() << "*** got a match"; + return i; + } + } + + ClassOrNamespace *i = _factory->allocClassOrNamespace(c); + i->_templateId = templId; + i->_usings.append(c); + c->_instantiations.append(i); + qDebug() << "created a new instantiation" << i; + return i; + } + + return c; } void ClassOrNamespace::flush() @@ -566,6 +601,11 @@ ClassOrNamespace *ClassOrNamespace::findOrCreate(const Name *name) if (! e) { e = _factory->allocClassOrNamespace(this); + + if (const TemplateNameId *templId = name->asTemplateNameId()) { + Overview oo; + qDebug() << "find or create:" << oo(templId); + } _classOrNamespaces[name] = e; } @@ -578,6 +618,7 @@ ClassOrNamespace *ClassOrNamespace::findOrCreate(const Name *name) CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot) : _snapshot(snapshot) { + _control = new Control(); _globalNamespace = allocClassOrNamespace(/*parent = */ 0); _currentClassOrNamespace = _globalNamespace; @@ -587,6 +628,7 @@ CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snaps CreateBindings::~CreateBindings() { qDeleteAll(_entities); + delete _control; } ClassOrNamespace *CreateBindings::switchCurrentEntity(ClassOrNamespace *classOrNamespace) @@ -639,6 +681,11 @@ void CreateBindings::process(Symbol *symbol) #endif } +Control *CreateBindings::control() const +{ + return _control; +} + ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent) { ClassOrNamespace *e = new ClassOrNamespace(this, parent); diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 3d073aa6bbd..20188c6d21d 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -60,9 +60,6 @@ public: ClassOrNamespace *findClassOrNamespace(const Name *name); ClassOrNamespace *findClassOrNamespace(const QList<const Name *> &path); - /// \internal - static void lookup_helper(const Name *name, Scope *scope, QList<Symbol *> *result); - private: /// \internal void flush(); @@ -78,7 +75,8 @@ private: void lookup_helper(const Name *name, ClassOrNamespace *binding, QList<Symbol *> *result, - QSet<ClassOrNamespace *> *processed); + QSet<ClassOrNamespace *> *processed, + const TemplateNameId *templateId); ClassOrNamespace *lookupClassOrNamespace_helper(const Name *name, QSet<ClassOrNamespace *> *processed); ClassOrNamespace *findClassOrNamespace_helper(const Name *name, QSet<ClassOrNamespace *> *processed); @@ -99,6 +97,12 @@ private: QList<Enum *> _enums; QList<Symbol *> _todo; + // it's an instantiation. + const TemplateNameId *_templateId; + + // templates + QList<ClassOrNamespace *> _instantiations; + friend class CreateBindings; }; @@ -121,6 +125,13 @@ public: /// \internal ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent); + /// \internal + Control *control() const; + + /// \internal + void lookup_helper(const Name *name, Scope *scope, QList<Symbol *> *result, + const TemplateNameId *templateId); + protected: using SymbolVisitor::visit; @@ -150,6 +161,7 @@ protected: virtual bool visit(ObjCMethod *); private: + Control *_control; Snapshot _snapshot; QSet<Namespace *> _processed; QList<ClassOrNamespace *> _entities; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 3f1a72eced7..89c4b5ae271 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -679,29 +679,7 @@ ResolveExpression::resolveMemberExpression(const QList<LookupItem> &baseResults, FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const { - if (const TemplateNameId *templId = className->asTemplateNameId()) { - if (Class *klass = candidate->enclosingSymbol()->asClass()) { - GenTemplateInstance::Substitution subst; - - for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { - FullySpecifiedType templArgTy = templId->templateArgumentAt(i); - - if (i < klass->templateParameterCount()) { - const Name *templArgName = klass->templateParameterAt(i)->name(); - - if (templArgName && templArgName->identifier()) { - const Identifier *templArgId = templArgName->identifier(); - subst.append(qMakePair(templArgId, templArgTy)); - } - } - } - - GenTemplateInstance inst(_context.control(), subst); - return inst(candidate); - } - } - - return candidate->type(); + return GenTemplateInstance::instantiate(className, candidate, _context.control()); } QList<LookupItem> @@ -728,24 +706,8 @@ ResolveExpression::resolveMember(const Name *memberName, Class *klass, if (const QualifiedNameId *q = className->asQualifiedNameId()) unqualifiedNameId = q->unqualifiedNameId(); - if (const TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { - GenTemplateInstance::Substitution subst; - - for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { - FullySpecifiedType templArgTy = templId->templateArgumentAt(i); - - if (i < klass->templateParameterCount()) { - const Name *templArgName = klass->templateParameterAt(i)->name(); - if (templArgName && templArgName->identifier()) { - const Identifier *templArgId = templArgName->identifier(); - subst.append(qMakePair(templArgId, templArgTy)); - } - } - } - - GenTemplateInstance inst(_context.control(), subst); - ty = inst(candidate); - } + if (const TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) + ty = GenTemplateInstance::instantiate(templId, candidate, _context.control()); results.append(LookupItem(ty, candidate)); } -- GitLab