summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/ResolveExpression.cpp
diff options
context:
space:
mode:
authorPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>2013-06-18 23:05:57 +0200
committerNikolai Kosjar <nikolai.kosjar@digia.com>2013-08-05 10:50:38 +0200
commitbfbf93e64f91630d7fad0bad1c4d38898ed5086b (patch)
tree6b5353d4e2bd383d839e5abf3af7587fa474472a /src/libs/cplusplus/ResolveExpression.cpp
parent62af8171754f8ec892a609ba7434928793026731 (diff)
downloadqt-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.cpp112
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,