diff options
author | Przemyslaw Gorszkowski <pgorszkowski@gmail.com> | 2013-06-18 23:05:57 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2013-08-05 10:50:38 +0200 |
commit | bfbf93e64f91630d7fad0bad1c4d38898ed5086b (patch) | |
tree | 6b5353d4e2bd383d839e5abf3af7587fa474472a /src/libs/cplusplus/ResolveExpression.cpp | |
parent | 62af8171754f8ec892a609ba7434928793026731 (diff) | |
download | qt-creator-bfbf93e64f91630d7fad0bad1c4d38898ed5086b.tar.gz |
C++: fix auto completion for template parameters
Fix auto completion for the case when template parameter should be
found somewhere of scope of template instantiation declaration.
Example:
struct A
{
void foo();
struct B
{
int b;
};
};
template<typename T>
struct Template
{
T* get() { return 0; }
T t;
};
void A::foo()
{
Template<B> templ;
templ.get()->//no autocompletion
templ.t.//no autocompletion
}
Task-number: QTCREATORBUG-8852
Task-number: QTCREATORBUG-9169
Change-Id: I56b40776e66740f995ae6fc5d69e3c50139a3af2
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
Diffstat (limited to 'src/libs/cplusplus/ResolveExpression.cpp')
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 112 |
1 files changed, 81 insertions, 31 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 4b20466458..20a562562e 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -142,11 +142,13 @@ void ResolveExpression::addResults(const QList<LookupItem> &items) _results += items; } -void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope) +void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope, + ClassOrNamespace *binding) { LookupItem item; item.setType(ty); item.setScope(scope); + item.setBinding(binding); _results.append(item); } @@ -713,7 +715,7 @@ bool ResolveExpression::visit(CallAST *ast) } else if (Function *funTy = ty->asFunctionType()) { if (maybeValidPrototype(funTy, actualArgumentCount)) - addResult(funTy->returnType().simplified(), scope); + addResult(funTy->returnType().simplified(), scope, result.binding()); } else if (Class *classTy = ty->asClassType()) { // Constructor call @@ -1014,53 +1016,77 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas FullySpecifiedType type = ptrTy->elementType(); if (! ty->isPointerType()) type = ty; + + if (ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + type)) { + return binding; + } if (ClassOrNamespace *binding = findClass(type, scope)) return binding; } else if (PointerType *ptrTy = ty->asPointerType()) { FullySpecifiedType type = ptrTy->elementType(); + if (ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + type)) { + return binding; + } if (ClassOrNamespace *binding = findClass(type, scope)) return binding; - } else if (ClassOrNamespace *binding = findClass(ty, scope)) { - // lookup for overloads of operator-> + } else { + ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + ty); + if (! binding) + binding = findClass(ty, scope); - const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp); - foreach (const LookupItem &r, binding->find(arrowOp)) { - Symbol *overload = r.declaration(); - if (! overload) - continue; - Scope *functionScope = overload->enclosingScope(); + if (binding){ + // lookup for overloads of operator-> - if (overload->type()->isFunctionType()) { - FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload); - Function *instantiatedFunction = overloadTy->asFunctionType(); - Q_ASSERT(instantiatedFunction != 0); + const OperatorNameId *arrowOp + = control()->operatorNameId(OperatorNameId::ArrowOp); + foreach (const LookupItem &r, binding->find(arrowOp)) { + Symbol *overload = r.declaration(); + if (! overload) + continue; + Scope *functionScope = overload->enclosingScope(); - FullySpecifiedType retTy = instantiatedFunction->returnType().simplified(); + if (overload->type()->isFunctionType()) { + FullySpecifiedType overloadTy + = instantiate(binding->templateId(), overload); + Function *instantiatedFunction = overloadTy->asFunctionType(); + Q_ASSERT(instantiatedFunction != 0); - typedefsResolver.resolve(&retTy, &functionScope, r.binding()); + FullySpecifiedType retTy + = instantiatedFunction->returnType().simplified(); - if (! retTy->isPointerType() && ! retTy->isNamedType()) - continue; + typedefsResolver.resolve(&retTy, &functionScope, r.binding()); - if (PointerType *ptrTy = retTy->asPointerType()) - retTy = ptrTy->elementType(); + if (! retTy->isPointerType() && ! retTy->isNamedType()) + continue; - if (ClassOrNamespace *retBinding = findClass(retTy, functionScope)) - return retBinding; + if (PointerType *ptrTy = retTy->asPointerType()) + retTy = ptrTy->elementType(); - if (scope != functionScope) { - if (ClassOrNamespace *retBinding = findClass(retTy, scope)) + if (ClassOrNamespace *retBinding = findClass(retTy, functionScope)) return retBinding; - } - if (ClassOrNamespace *origin = binding->instantiationOrigin()) { - foreach (Symbol *originSymbol, origin->symbols()) { - Scope *originScope = originSymbol->asScope(); - if (originScope && originScope != scope && originScope != functionScope) { - if (ClassOrNamespace *retBinding = findClass(retTy, originScope)) - return retBinding; + if (scope != functionScope) { + if (ClassOrNamespace *retBinding = findClass(retTy, scope)) + return retBinding; + } + + if (ClassOrNamespace *origin = binding->instantiationOrigin()) { + foreach (Symbol *originSymbol, origin->symbols()) { + Scope *originScope = originSymbol->asScope(); + if (originScope && originScope != scope + && originScope != functionScope) { + if (ClassOrNamespace *retBinding + = findClass(retTy, originScope)) + return retBinding; + } } } } @@ -1078,6 +1104,12 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas } } + if (ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + ty)) { + return binding; + } + ClassOrNamespace *enclosingTemplateInstantiation = 0; if (ClassOrNamespace *binding = r.binding()) { if (binding->instantiationOrigin()) @@ -1092,6 +1124,24 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas return 0; } +ClassOrNamespace *ResolveExpression::findClassForTemplateParameterInExpressionScope( + ClassOrNamespace *resultBinding, + const FullySpecifiedType &ty) const +{ + if (resultBinding && resultBinding->instantiationOrigin()) { + if (ClassOrNamespace *origin = resultBinding->instantiationOrigin()) { + foreach (Symbol *originSymbol, origin->symbols()) { + if (Scope *originScope = originSymbol->asScope()) { + if (ClassOrNamespace *retBinding = findClass(ty, originScope)) + return retBinding; + } + } + } + } + + return 0; +} + FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const { return DeprecatedGenTemplateInstance::instantiate(className, candidate, |