aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoberto Raggi <[email protected]>2009-10-05 11:38:54 +0200
committerRoberto Raggi <[email protected]>2009-10-05 11:39:55 +0200
commit1f1c899cc083c55daf7cc4591bf92f6103fac4ed (patch)
tree0028311bea9191f368a5780cf977bb2ef33a9302
parent5948e284bb576aa21b6adb3031a7a891861ffd06 (diff)
Improved template instantiation.
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp278
-rw-r--r--src/libs/cplusplus/ResolveExpression.h22
-rw-r--r--src/plugins/cpptools/cppcodecompletion.cpp20
3 files changed, 150 insertions, 170 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 31ff8a00865..23aa23a66d4 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -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 *>();
-}
-
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 71289ef3432..fb00f9e23f6 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -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;
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 988bba99665..cd0c8f705ed 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -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;