Commit 1f1c899c authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Improved template instantiation.

parent 5948e284
......@@ -194,6 +194,22 @@ protected:
{ Q_ASSERT(false); }
};
template <typename _Tp>
static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
{
QList<_Tp> uniqueList;
QSet<_Tp> processed;
foreach (const _Tp &r, results) {
if (processed.contains(r))
continue;
processed.insert(r);
uniqueList.append(r);
}
return uniqueList;
}
} // end of anonymous namespace
/////////////////////////////////////////////////////////////////////
......@@ -212,7 +228,7 @@ QList<ResolveExpression::Result> ResolveExpression::operator()(ExpressionAST *as
{
const QList<Result> previousResults = switchResults(QList<Result>());
accept(ast);
return switchResults(previousResults);
return removeDuplicates(switchResults(previousResults));
}
QList<ResolveExpression::Result>
......@@ -482,7 +498,7 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
if (NamedType *namedTy = symbol->type()->asNamedType()) {
const Result r(namedTy, symbol);
const QList<Symbol *> resolvedClasses =
resolveClass(r, _context);
resolveClass(namedTy->name(), r, _context);
if (resolvedClasses.count()) {
foreach (Symbol *s, resolvedClasses) {
addResult(s->type(), s);
......@@ -591,7 +607,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
addResult(arrTy->elementType(), contextSymbol);
} else if (NamedType *namedTy = ty->asNamedType()) {
const QList<Symbol *> classObjectCandidates =
symbolsForDotAcccess(p, _context);
symbolsForDotAcccess(namedTy->name(), p, _context);
foreach (Symbol *classObject, classObjectCandidates) {
const QList<Result> overloads =
......@@ -630,30 +646,38 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
return false;
}
QList<Symbol *> ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const
QList<ResolveExpression::Result>
ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const
{
QList<Symbol *> classObjectCandidates;
QList<Result> results;
if (baseResults.isEmpty())
return classObjectCandidates;
return results;
Result result = baseResults.first();
FullySpecifiedType ty = result.first.simplified();
Symbol *lastVisibleSymbol = result.second;
if (accessOp == T_ARROW) {
FullySpecifiedType ty = result.first.simplified();
if (lastVisibleSymbol && ty->isClassType() && ! lastVisibleSymbol->isClass()) {
// ### remove ! lastVisibleSymbol->isClass() from the condition.
results.append(Result(ty, lastVisibleSymbol));
if (Class *classTy = ty->asClassType()) {
Symbol *symbol = result.second;
if (symbol && ! symbol->isClass())
classObjectCandidates.append(classTy);
} else if (NamedType *namedTy = ty->asNamedType()) {
// ### This code is pretty slow.
const QList<Symbol *> candidates = _context.resolve(namedTy->name());
foreach (Symbol *candidate, candidates) {
if (candidate->isTypedef()) {
ty = candidate->type();
const ResolveExpression::Result r(ty, candidate);
FullySpecifiedType declTy = candidate->type().simplified();
const ResolveExpression::Result r(declTy, candidate);
// update the result
result = r;
// refresh the cached ty and lastVisibileSymbol.
ty = result.first.simplified();
lastVisibleSymbol = result.second;
break;
}
}
......@@ -662,82 +686,49 @@ QList<Symbol *> ResolveExpression::resolveBaseExpression(const QList<Result> &ba
if (NamedType *namedTy = ty->asNamedType()) {
ResolveClass resolveClass;
const QList<Symbol *> candidates = resolveClass(result, _context);
const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, _context);
foreach (Symbol *classObject, candidates) {
const QList<Result> overloads = resolveArrowOperator(result, namedTy,
classObject->asClass());
foreach (Result r, overloads) {
FullySpecifiedType ty = r.first;
Function *funTy = ty->asFunctionType();
foreach (const Result &r, overloads) {
FullySpecifiedType typeOfOverloadFunction = r.first.simplified();
Symbol *lastVisibleSymbol = r.second;
Function *funTy = typeOfOverloadFunction->asFunctionType();
if (! funTy)
continue;
ty = funTy->returnType().simplified();
typeOfOverloadFunction = funTy->returnType().simplified();
if (PointerType *ptrTy = ty->asPointerType()) {
if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
const QList<Symbol *> classes =
resolveClass(namedTy, result, _context);
if (PointerType *ptrTy = typeOfOverloadFunction->asPointerType()) {
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
classObjectCandidates.append(c);
}
}
if (elementTy->isNamedType())
results.append(Result(elementTy, lastVisibleSymbol));
}
}
}
} else if (PointerType *ptrTy = ty->asPointerType()) {
if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
ResolveClass resolveClass;
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
const QList<Symbol *> classes = resolveClass(namedTy, result,
_context);
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
classObjectCandidates.append(c);
}
} else if (Class *classTy = ptrTy->elementType()->asClassType()) {
// typedef struct { int x } *Ptr;
// Ptr p;
// p->
classObjectCandidates.append(classTy);
}
if (elementTy->isNamedType() || elementTy->isClassType())
results.append(Result(elementTy, lastVisibleSymbol));
}
} else if (accessOp == T_DOT) {
FullySpecifiedType ty = result.first.simplified();
NamedType *namedTy = 0;
if (Class *classTy = ty->asClassType()) {
Symbol *symbol = result.second;
if (symbol && ! symbol->isClass())
classObjectCandidates.append(classTy);
} else {
namedTy = ty->asNamedType();
if (! namedTy) {
Function *fun = ty->asFunctionType();
if (fun && fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()))
namedTy = fun->returnType()->asNamedType();
}
}
if (ty->isClassType() || ty->isNamedType())
results.append(Result(ty, lastVisibleSymbol));
if (namedTy) {
ResolveClass resolveClass;
const QList<Symbol *> symbols = resolveClass(namedTy, result,
_context);
foreach (Symbol *symbol, symbols) {
if (classObjectCandidates.contains(symbol))
continue;
if (Class *klass = symbol->asClass())
classObjectCandidates.append(klass);
if (Function *fun = ty->asFunctionType()) {
Scope *funScope = fun->scope();
if (funScope && (funScope->isBlockScope() || funScope->isNamespaceScope())) {
FullySpecifiedType retTy = fun->returnType().simplified();
results.append(Result(retTy, lastVisibleSymbol));
}
}
}
return classObjectCandidates;
return removeDuplicates(results);
}
QList<ResolveExpression::Result>
......@@ -745,25 +736,42 @@ ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults,
unsigned accessOp,
Name *memberName) const
{
ResolveClass resolveClass;
QList<Result> results;
const QList<Symbol *> classObjectCandidates = resolveBaseExpression(baseResults, accessOp);
foreach (Symbol *candidate, classObjectCandidates) {
Class *klass = candidate->asClass();
if (! klass)
continue;
const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp);
foreach (const Result &r, classObjectResults) {
FullySpecifiedType ty = r.first;
if (Class *klass = ty->asClassType())
results += resolveMember(memberName, klass);
results += resolveMember(memberName, klass);
else if (NamedType *namedTy = ty->asNamedType()) {
Name *className = namedTy->name();
const QList<Symbol *> classes = resolveClass(className, r, _context);
foreach (Symbol *c, classes) {
if (Class *klass = c->asClass())
results += resolveMember(memberName, klass, className);
}
}
}
return results;
return removeDuplicates(results);
}
QList<ResolveExpression::Result>
ResolveExpression::resolveMember(Name *memberName, Class *klass) const
ResolveExpression::resolveMember(Name *memberName, Class *klass,
Name *className) const
{
QList<Result> results;
if (! className)
className = klass->name();
if (! className)
return results;
QList<Scope *> scopes;
_context.expand(klass->members(), _context.visibleScopes(), &scopes);
......@@ -771,35 +779,30 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass) const
foreach (Symbol *candidate, candidates) {
FullySpecifiedType ty = candidate->type();
if (Name *className = klass->name()) {
Name *unqualifiedNameId = className;
if (QualifiedNameId *q = className->asQualifiedNameId())
unqualifiedNameId = q->unqualifiedNameId();
if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) {
Substitution subst;
for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
if (i < klass->templateParameterCount())
subst.append(qMakePair(klass->templateParameterAt(i)->name(),
templArgTy));
}
Instantiation inst(control(), subst);
ty = inst(ty);
Name *unqualifiedNameId = className;
if (QualifiedNameId *q = className->asQualifiedNameId())
unqualifiedNameId = q->unqualifiedNameId();
if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) {
Substitution subst;
for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
if (i < klass->templateParameterCount())
subst.append(qMakePair(klass->templateParameterAt(i)->name(),
templArgTy));
}
Instantiation inst(control(), subst);
ty = inst(ty);
}
const Result result(ty, candidate);
if (! results.contains(result))
results.append(result);
results.append(Result(ty, candidate));
}
return results;
return removeDuplicates(results);
}
QList<ResolveExpression::Result>
......@@ -832,11 +835,10 @@ ResolveExpression::resolveArrowOperator(const Result &,
}
const Result result(ty, candidate);
if (! results.contains(result))
results.append(result);
results.append(result);
}
return results;
return removeDuplicates(results);
}
QList<ResolveExpression::Result>
......@@ -870,12 +872,10 @@ ResolveExpression::resolveArrayOperator(const Result &,
ty = inst(ty);
}
const Result result(ty, candidate);
if (! results.contains(result))
results.append(result);
results.append(Result(ty, candidate));
}
return results;
return removeDuplicates(results);
}
bool ResolveExpression::visit(PostIncrDecrAST *)
......@@ -894,27 +894,18 @@ bool ResolveClass::pointerAccess() const
void ResolveClass::setPointerAccess(bool pointerAccess)
{ _pointerAccess = pointerAccess; }
QList<Symbol *> ResolveClass::operator()(NamedType *namedTy,
ResolveExpression::Result p,
const LookupContext &context)
{
const QList<ResolveExpression::Result> previousBlackList = _blackList;
const QList<Symbol *> symbols = resolveClass(namedTy, p, context);
_blackList = previousBlackList;
return symbols;
}
QList<Symbol *> ResolveClass::operator()(ResolveExpression::Result p,
QList<Symbol *> ResolveClass::operator()(Name *name,
const ResolveExpression::Result &p,
const LookupContext &context)
{
const QList<ResolveExpression::Result> previousBlackList = _blackList;
const QList<Symbol *> symbols = resolveClass(p, context);
const QList<Symbol *> symbols = resolveClass(name, p, context);
_blackList = previousBlackList;
return symbols;
}
QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
ResolveExpression::Result p,
QList<Symbol *> ResolveClass::resolveClass(Name *name,
const ResolveExpression::Result &p,
const LookupContext &context)
{
QList<Symbol *> resolvedSymbols;
......@@ -925,7 +916,7 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
_blackList.append(p);
const QList<Symbol *> candidates =
context.resolve(namedTy->name(), context.visibleScopes(p));
context.resolve(name, context.visibleScopes(p));
foreach (Symbol *candidate, candidates) {
if (Class *klass = candidate->asClass()) {
......@@ -936,10 +927,13 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
if (Declaration *decl = candidate->asDeclaration()) {
if (_pointerAccess && decl->type()->isPointerType()) {
PointerType *ptrTy = decl->type()->asPointerType();
_pointerAccess = false;
const ResolveExpression::Result r(ptrTy->elementType(), decl);
resolvedSymbols += resolveClass(r, context);
_pointerAccess = true;
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
if (NamedType *namedTy = elementTy->asNamedType()) {
_pointerAccess = false;
const ResolveExpression::Result r(elementTy, decl);
resolvedSymbols += resolveClass(namedTy->name(), r, context);
_pointerAccess = true;
}
} else if (Class *asClass = decl->type()->asClassType()) {
// typedef struct { } Point;
// Point pt;
......@@ -949,8 +943,11 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
// typedef Point Boh;
// Boh b;
// b.
const ResolveExpression::Result r(decl->type(), decl);
resolvedSymbols += resolveClass(r, context);
FullySpecifiedType declType = decl->type().simplified();
if (NamedType *namedTy = declType->asNamedType()) {
const ResolveExpression::Result r(declType, decl);
resolvedSymbols += resolveClass(namedTy->name(), r, context);
}
}
}
} else if (Declaration *decl = candidate->asDeclaration()) {
......@@ -958,8 +955,11 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
// QString foo("ciao");
// foo.
if (funTy->scope() && (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope())) {
const ResolveExpression::Result r(funTy->returnType(), decl);
resolvedSymbols += resolveClass(r, context);
FullySpecifiedType retTy = funTy->returnType().simplified();
if (NamedType *namedTy = retTy->asNamedType()) {
const ResolveExpression::Result r(retTy, decl);
resolvedSymbols += resolveClass(namedTy->name(), r, context);
}
}
}
}
......@@ -967,19 +967,3 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
return resolvedSymbols;
}
QList<Symbol *> ResolveClass::resolveClass(ResolveExpression::Result p,
const LookupContext &context)
{
FullySpecifiedType ty = p.first;
if (NamedType *namedTy = ty->asNamedType()) {
return resolveClass(namedTy, p, context);
} else if (ReferenceType *refTy = ty->asReferenceType()) {
const ResolveExpression::Result e(refTy->elementType(), p.second);
return resolveClass(e, context);
}
return QList<Symbol *>();
}
......@@ -53,7 +53,7 @@ public:
unsigned accessOp,
Name *memberName) const;
QList<Result> resolveMember(Name *memberName, Class *klass) const;
QList<Result> resolveMember(Name *memberName, Class *klass, Name *className = 0) const;
QList<Result> resolveArrowOperator(const Result &result,
NamedType *namedTy,
......@@ -64,8 +64,8 @@ public:
Class *klass) const;
QList<Symbol *> resolveBaseExpression(const QList<Result> &baseResults,
int accessOp) const;
QList<Result> resolveBaseExpression(const QList<Result> &baseResults,
int accessOp) const;
protected:
QList<Result> switchResults(const QList<Result> &symbols);
......@@ -131,20 +131,14 @@ public:
bool pointerAccess() const;
void setPointerAccess(bool pointerAccess);
QList<Symbol *> operator()(NamedType *namedTy,
ResolveExpression::Result p,
const LookupContext &context);
QList<Symbol *> operator()(ResolveExpression::Result p,
QList<Symbol *> operator()(Name *name,
const ResolveExpression::Result &p,
const LookupContext &context);
private:
QList<Symbol *> resolveClass(NamedType *namedTy,
ResolveExpression::Result p,
const LookupContext &context);
QList<Symbol *> resolveClass(ResolveExpression::Result p,
const LookupContext &context);
QList<Symbol *> resolveClass(Name *name,
const ResolveExpression::Result &p,
const LookupContext &context);
private:
QList<ResolveExpression::Result> _blackList;
......
......@@ -1011,7 +1011,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
ResolveExpression resolveExpression(context);
ResolveClass resolveClass;
const QList<Symbol *> candidates = resolveClass(result, context);
const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, context);
foreach (Symbol *classObject, candidates) {
const QList<TypeOfExpression::Result> overloads =
resolveExpression.resolveArrowOperator(result, namedTy,
......@@ -1026,9 +1026,10 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
ty = funTy->returnType().simplified();
if (PointerType *ptrTy = ty->asPointerType()) {
if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
if (NamedType *namedTy = elementTy->asNamedType()) {
const QList<Symbol *> classes =
resolveClass(namedTy, result, context);
resolveClass(namedTy->name(), result, context);
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
......@@ -1039,17 +1040,18 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
}
}
} else if (PointerType *ptrTy = ty->asPointerType()) {
if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
if (NamedType *namedTy = elementTy->asNamedType()) {
ResolveClass resolveClass;
const QList<Symbol *> classes = resolveClass(namedTy, result,
const QList<Symbol *> classes = resolveClass(namedTy->name(), result,
context);
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
classObjectCandidates.append(c);
}
} else if (Class *classTy = ptrTy->elementType()->asClassType()) {
} else if (Class *classTy = elementTy->asClassType()) {
// typedef struct { int x } *Ptr;
// Ptr p;
// p->
......@@ -1099,7 +1101,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
if (namedTy) {
ResolveClass resolveClass;
const QList<Symbol *> symbols = resolveClass(namedTy, result,
const QList<Symbol *> symbols = resolveClass(namedTy->name(), result,
context);
foreach (Symbol *symbol, symbols) {
if (classObjectCandidates.contains(symbol))
......@@ -1330,7 +1332,7 @@ bool CppCodeCompletion::completeQtMethod(const QList<TypeOfExpression::Result> &
FullySpecifiedType ty = p.first.simplified();
if (PointerType *ptrTy = ty->asPointerType())
ty = ptrTy->elementType();
ty = ptrTy->elementType().simplified();
else
continue; // not a pointer or a reference to a pointer.
......@@ -1339,7 +1341,7 @@ bool CppCodeCompletion::completeQtMethod(const QList<TypeOfExpression::Result> &
continue;
const QList<Symbol *> classObjects =
resolveClass(namedTy, p, context);
resolveClass(namedTy->name(), p, context);
if (classObjects.isEmpty())
continue;
......
Supports Markdown
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