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