From cb459717785f2f2f114d665d6da725980f919a66 Mon Sep 17 00:00:00 2001 From: Leandro Melo <leandro.melo@nokia.com> Date: Thu, 17 Nov 2011 12:42:02 +0100 Subject: [PATCH] C++: Better resolution for typedef when resolving expr. Example: struct Bar { int m; }; typedef Bar *pBar; pBar b; b-> // completes correctly now Change-Id: I97cc67579b955fe47c68ab6c35be9a054b6d1be9 Done-by: ckamm Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com> --- src/libs/cplusplus/LookupContext.cpp | 2 -- src/libs/cplusplus/ResolveExpression.cpp | 44 ++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index ce62581f955..4908b1c65e3 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -485,8 +485,6 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, const TemplateNameId *templateId, ClassOrNamespace *binding) { - Q_UNUSED(templateId); - if (! name) { return; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index a9df47ad08b..14903210765 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -48,6 +48,7 @@ #include <QtCore/QList> #include <QtCore/QtDebug> +#include <QtCore/QSet> using namespace CPlusPlus; @@ -679,6 +680,38 @@ ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &origina return binding; } +static void resolveTypedefs(const LookupContext &context, + FullySpecifiedType *type, + Scope **scope) +{ + QSet<Symbol *> visited; + while (NamedType *namedTy = (*type)->asNamedType()) { + ClassOrNamespace *scopeCoN = context.lookupType(*scope); + if (!scopeCoN) + break; + + // check if namedTy->name() resolves to a typedef + QList<LookupItem> namedTypeItems = scopeCoN->lookup(namedTy->name()); + bool foundTypedef = false; + foreach (const LookupItem &it, namedTypeItems) { + if (it.declaration() && it.declaration()->isTypedef()) { + if (visited.contains(it.declaration())) + break; + visited.insert(it.declaration()); + + // continue working with the typedefed type and scope + *type = it.declaration()->type(); + *scope = it.scope(); + foundTypedef = true; + break; + } + } + + if (!foundTypedef) + break; + } +} + ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults, int accessOp, bool *replacedDotOperator) const @@ -687,6 +720,8 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas FullySpecifiedType ty = r.type().simplified(); Scope *scope = r.scope(); + resolveTypedefs(_context, &ty, &scope); + if (accessOp == T_ARROW) { if (PointerType *ptrTy = ty->asPointerType()) { if (ClassOrNamespace *binding = findClass(ptrTy->elementType(), scope)) @@ -700,6 +735,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas Symbol *overload = r.declaration(); if (! overload) continue; + Scope *functionScope = overload->enclosingScope(); if (overload->type()->isFunctionType()) { FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload); @@ -708,11 +744,13 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas FullySpecifiedType retTy = instantiatedFunction->returnType().simplified(); + resolveTypedefs(_context, &retTy, &functionScope); + if (PointerType *ptrTy = retTy->asPointerType()) { - if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), overload->enclosingScope())) + if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), functionScope)) return retBinding; - if (scope != overload->enclosingScope()) { + if (scope != functionScope) { if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope)) return retBinding; } @@ -720,7 +758,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas if (ClassOrNamespace *origin = binding->instantiationOrigin()) { foreach (Symbol *originSymbol, origin->symbols()) { Scope *originScope = originSymbol->asScope(); - if (originScope && originScope != scope && originScope != overload->enclosingScope()) { + if (originScope && originScope != scope && originScope != functionScope) { if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope)) return retBinding; } -- GitLab