forked from qt-creator/qt-creator
Refactor a bit the lookup, it should simplify template instantiation.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ public:
|
||||
typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
|
||||
|
||||
public:
|
||||
static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, Control *control);
|
||||
|
||||
private:
|
||||
GenTemplateInstance(Control *control, const Substitution &substitution);
|
||||
|
||||
FullySpecifiedType operator()(Symbol *symbol);
|
||||
|
||||
Control *control() const;
|
||||
FullySpecifiedType gen(Symbol *symbol);
|
||||
|
||||
private:
|
||||
Symbol *_symbol;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user