From d9527680a9fbbdb8f70c82143e77a52ef34d61aa Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Wed, 5 May 2010 12:06:38 +0200
Subject: [PATCH] Try to use the new LookupContext.

---
 src/libs/cplusplus/FindUsages.cpp          |   6 +-
 src/libs/cplusplus/GenTemplateInstance.cpp |  18 +-
 src/libs/cplusplus/GenTemplateInstance.h   |   4 +-
 src/libs/cplusplus/LookupContext.cpp       |  32 +-
 src/libs/cplusplus/LookupContext.h         |   3 +-
 src/libs/cplusplus/ResolveExpression.cpp   | 357 +++++++--------------
 src/libs/cplusplus/ResolveExpression.h     |  58 +---
 src/libs/cplusplus/TypeOfExpression.cpp    |  96 +++---
 src/libs/cplusplus/TypeOfExpression.h      |  38 ++-
 src/plugins/cppeditor/cppeditor.cpp        |  24 +-
 src/plugins/cppeditor/cpphoverhandler.cpp  |  13 +-
 src/plugins/cppeditor/cppquickfix.cpp      |  13 +-
 src/plugins/cpptools/cppcodecompletion.cpp |  93 +++---
 src/plugins/cpptools/cppcodecompletion.h   |  14 +-
 14 files changed, 324 insertions(+), 445 deletions(-)

diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index ca7d379f572..9c367d1ab7c 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -282,14 +282,14 @@ void FindUsages::checkExpression(unsigned startToken, unsigned endToken)
     // qDebug() << "*** check expression:" << expression;
 
     TypeOfExpression typeofExpression;
-    typeofExpression.setSnapshot(_snapshot);
+    typeofExpression.init(_doc, _snapshot);
 
     unsigned line, column;
     getTokenStartPosition(startToken, &line, &column);
     Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column);
 
-    const QList<LookupItem> results = typeofExpression(expression, _doc, lastVisibleSymbol,
-                                                   TypeOfExpression::Preprocess);
+    const QList<LookupItem> results = typeofExpression(expression, lastVisibleSymbol,
+                                                       TypeOfExpression::Preprocess);
 
     QList<Symbol *> candidates;
 
diff --git a/src/libs/cplusplus/GenTemplateInstance.cpp b/src/libs/cplusplus/GenTemplateInstance.cpp
index b430e458f6b..bb6afc6655e 100644
--- a/src/libs/cplusplus/GenTemplateInstance.cpp
+++ b/src/libs/cplusplus/GenTemplateInstance.cpp
@@ -47,10 +47,10 @@ namespace {
 class ApplySubstitution
 {
 public:
-    ApplySubstitution(const DeprecatedLookupContext &context, Symbol *symbol, const GenTemplateInstance::Substitution &substitution);
+    ApplySubstitution(Control *control, Symbol *symbol, const GenTemplateInstance::Substitution &substitution);
     ~ApplySubstitution();
 
-    Control *control() const { return context.control(); }
+    inline Control *control() const { return _control; }
 
     FullySpecifiedType apply(const Name *name);
     FullySpecifiedType apply(const FullySpecifiedType &type);
@@ -309,16 +309,16 @@ private:
     };
 
 public: // attributes
-    DeprecatedLookupContext context;
+    Control *_control;
     Symbol *symbol;
     GenTemplateInstance::Substitution substitution;
     ApplyToType applyToType;
     ApplyToName applyToName;
 };
 
-ApplySubstitution::ApplySubstitution(const DeprecatedLookupContext &context, Symbol *symbol,
+ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol,
                                      const GenTemplateInstance::Substitution &substitution)
-    : context(context), symbol(symbol),
+    : _control(control), symbol(symbol),
       substitution(substitution),
       applyToType(this), applyToName(this)
 { }
@@ -363,17 +363,17 @@ FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
 
 } // end of anonymous namespace
 
-GenTemplateInstance::GenTemplateInstance(const DeprecatedLookupContext &context, const Substitution &substitution)
+GenTemplateInstance::GenTemplateInstance(Control *control, const Substitution &substitution)
     : _symbol(0),
-      _context(context),
+      _control(control),
       _substitution(substitution)
 { }
 
 FullySpecifiedType GenTemplateInstance::operator()(Symbol *symbol)
 {
-    ApplySubstitution o(_context, symbol, _substitution);
+    ApplySubstitution o(_control, symbol, _substitution);
     return o.apply(symbol->type());
 }
 
 Control *GenTemplateInstance::control() const
-{ return _context.control(); }
+{ return _control; }
diff --git a/src/libs/cplusplus/GenTemplateInstance.h b/src/libs/cplusplus/GenTemplateInstance.h
index 6225c0bfb52..b667cc2ab41 100644
--- a/src/libs/cplusplus/GenTemplateInstance.h
+++ b/src/libs/cplusplus/GenTemplateInstance.h
@@ -47,7 +47,7 @@ public:
     typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
 
 public:
-    GenTemplateInstance(const DeprecatedLookupContext &context, const Substitution &substitution);
+    GenTemplateInstance(Control *control, const Substitution &substitution);
 
     FullySpecifiedType operator()(Symbol *symbol);
 
@@ -55,7 +55,7 @@ public:
 
 private:
     Symbol *_symbol;
-    DeprecatedLookupContext _context;
+    Control *_control;
     const Substitution _substitution;
 };
 
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 36fd3de8df6..27fdbb30f83 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -148,6 +148,16 @@ ClassOrNamespace *LookupContext::classOrNamespace(const Name *name, Symbol *last
     return classOrNamespace(name, lastVisibleSymbol);
 }
 
+QList<Symbol *> LookupContext::lookup(const Name *name, Symbol *lastVisibleSymbol) const
+{
+    Scope *scope = _thisDocument->globalSymbols();
+
+    if (lastVisibleSymbol && lastVisibleSymbol->scope())
+        scope = lastVisibleSymbol->scope();
+
+    return lookup(name, scope);
+}
+
 QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
 {
     QList<Symbol *> candidates;
@@ -168,19 +178,15 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
                 Symbol *member = scope->symbolAt(index);
 
                 if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
-                    Namespace *enclosingNamespace = u->enclosingNamespaceScope()->owner()->asNamespace();
-                    //qDebug() << "*** enclosing namespace:" << enclosingNamespace;
-                    Q_ASSERT(enclosingNamespace != 0);
-
-                    ClassOrNamespace *b = bindings()->findClassOrNamespace(enclosingNamespace);
-                    //qDebug() << "**** binding:" << b;
-                    Q_ASSERT(b != 0);
-
-                    if (ClassOrNamespace *uu = b->lookupClassOrNamespace(u->name())) {
-                        candidates = uu->lookup(name);
-
-                        if (! candidates.isEmpty())
-                            return candidates;
+                    if (Namespace *enclosingNamespace = u->enclosingNamespaceScope()->owner()->asNamespace()) {
+                        if (ClassOrNamespace *b = bindings()->findClassOrNamespace(enclosingNamespace)) {
+                            if (ClassOrNamespace *uu = b->lookupClassOrNamespace(u->name())) {
+                                candidates = uu->lookup(name);
+
+                                if (! candidates.isEmpty())
+                                    return candidates;
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index ad8f43f2682..0937e86a0b7 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -174,6 +174,7 @@ public:
     Document::Ptr document(const QString &fileName) const;
     Snapshot snapshot() const;
 
+    QList<Symbol *> lookup(const Name *name, Symbol *lastVisibleSymbol) const;
     QList<Symbol *> lookup(const Name *name, Scope *scope) const;
 
     ClassOrNamespace *globalNamespace() const;
@@ -188,7 +189,7 @@ public:
     /// \internal
     void setBindings(QSharedPointer<CreateBindings> bindings);
 
-    Q_DECL_DEPRECATED Control *control() const;
+    Control *control() const; // ### deprecate
 
 private:
     Control *_control;
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 9fc10b6d16e..1825de43811 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -28,7 +28,7 @@
 **************************************************************************/
 
 #include "ResolveExpression.h"
-#include "DeprecatedLookupContext.h"
+#include "LookupContext.h"
 #include "Overview.h"
 #include "GenTemplateInstance.h"
 
@@ -43,7 +43,6 @@
 #include <NameVisitor.h>
 
 #include <QtCore/QList>
-#include <QtCore/QVarLengthArray>
 #include <QtCore/QtDebug>
 
 using namespace CPlusPlus;
@@ -71,8 +70,21 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
 /////////////////////////////////////////////////////////////////////
 // ResolveExpression
 /////////////////////////////////////////////////////////////////////
-ResolveExpression::ResolveExpression(const DeprecatedLookupContext &context)
+ResolveExpression::ResolveExpression(Symbol *lastVisibleSymbol, const LookupContext &context)
     : ASTVisitor(context.expressionDocument()->translationUnit()),
+      _lastVisibleSymbol(lastVisibleSymbol),
+      _context(context),
+      sem(context.expressionDocument()->translationUnit())
+{
+    if (! lastVisibleSymbol)
+        lastVisibleSymbol = context.thisDocument()->globalNamespace();
+    _scope = lastVisibleSymbol->scope();
+}
+
+ResolveExpression::ResolveExpression(Scope *scope, const LookupContext &context)
+    : ASTVisitor(context.expressionDocument()->translationUnit()),
+      _lastVisibleSymbol(0),
+      _scope(scope),
       _context(context),
       sem(context.expressionDocument()->translationUnit())
 { }
@@ -102,21 +114,25 @@ void ResolveExpression::addResults(const QList<LookupItem> &results)
 }
 
 void ResolveExpression::addResult(const FullySpecifiedType &ty, Symbol *symbol)
-{ return addResult(LookupItem(ty, symbol)); }
-
-void ResolveExpression::addResult(const LookupItem &r)
 {
-    LookupItem p = r;
+    if (! symbol) {
+        if (_scope)
+            symbol = _scope->owner();
 
-    if (! p.lastVisibleSymbol())
-        p.setLastVisibleSymbol(_context.symbol());
+        else
+            symbol = _context.thisDocument()->globalNamespace();
+    }
 
-    if (! _results.contains(p))
-        _results.append(p);
+    return addResult(LookupItem(ty, symbol));
 }
 
-QList<Scope *> ResolveExpression::visibleScopes(const LookupItem &result) const
-{ return _context.visibleScopes(result); }
+void ResolveExpression::addResult(const LookupItem &r)
+{
+    Q_ASSERT(r.lastVisibleSymbol() != 0);
+
+    if (! _results.contains(r))
+        _results.append(r);
+}
 
 bool ResolveExpression::visit(BinaryExpressionAST *ast)
 {
@@ -289,10 +305,7 @@ bool ResolveExpression::visit(ThisExpressionAST *)
 
 void ResolveExpression::thisObject()
 {
-    if (! _context.symbol())
-        return;
-
-    Scope *scope = _context.symbol()->scope();
+    Scope *scope = _scope;
     for (; scope; scope = scope->enclosingScope()) {
         if (scope->isFunctionScope()) {
             Function *fun = scope->owner()->asFunction();
@@ -387,42 +400,28 @@ bool ResolveExpression::visit(CompoundLiteralAST *ast)
 
 bool ResolveExpression::visit(QualifiedNameAST *ast)
 {
-    ResolveClass resolveClass;
-    const Name *name = ast->name;
-
-    QList<Symbol *> symbols = _context.resolve(name);
-    foreach (Symbol *symbol, symbols) {
-        if (symbol->isTypedef()) {
-            if (NamedType *namedTy = symbol->type()->asNamedType()) {
-                const LookupItem r(namedTy, symbol);
-                const QList<Symbol *> resolvedClasses =
-                        resolveClass(namedTy->name(), r, _context);
-                if (resolvedClasses.count()) {
-                    foreach (Symbol *s, resolvedClasses) {
-                        addResult(s->type(), s);
-                    }
-                    continue;
-                }
-            }
-        }
-        addResult(symbol->type(), symbol);
+    if (const Name *name = ast->name) {
+        const QList<Symbol *> candidates = _context.lookup(name, _scope);
+
+        foreach (Symbol *candidate, candidates)
+            addResult(candidate->type(), candidate);
     }
-    return false;
-}
 
-bool ResolveExpression::visit(OperatorFunctionIdAST *)
-{
     return false;
 }
 
-bool ResolveExpression::visit(ConversionFunctionIdAST *)
+bool ResolveExpression::visit(SimpleNameAST *ast)
 {
+    QList<Symbol *> symbols = _context.lookup(ast->name, _scope);
+    foreach (Symbol *symbol, symbols)
+        addResult(symbol->type(), symbol);
+
     return false;
 }
 
-bool ResolveExpression::visit(SimpleNameAST *ast)
+bool ResolveExpression::visit(TemplateIdAST *ast)
 {
-    QList<Symbol *> symbols = _context.resolve(ast->name);
+    const QList<Symbol *> symbols = _context.lookup(ast->name, _scope);
     foreach (Symbol *symbol, symbols)
         addResult(symbol->type(), symbol);
 
@@ -436,12 +435,13 @@ bool ResolveExpression::visit(DestructorNameAST *)
     return false;
 }
 
-bool ResolveExpression::visit(TemplateIdAST *ast)
+bool ResolveExpression::visit(OperatorFunctionIdAST *)
 {
-    QList<Symbol *> symbols = _context.resolve(ast->name);
-    foreach (Symbol *symbol, symbols)
-        addResult(symbol->type(), symbol);
+    return false;
+}
 
+bool ResolveExpression::visit(ConversionFunctionIdAST *)
+{
     return false;
 }
 
@@ -470,8 +470,6 @@ bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgu
 
 bool ResolveExpression::visit(CallAST *ast)
 {
-    ResolveClass resolveClass;
-
     const QList<LookupItem> baseResults = _results;
     _results.clear();
 
@@ -491,17 +489,13 @@ bool ResolveExpression::visit(CallAST *ast)
         Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
 
         if (NamedType *namedTy = ty->asNamedType()) {
-            const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, _context);
-
-            foreach (Symbol *classObject, classObjectCandidates) {
-                const QList<LookupItem> overloads = resolveMember(functionCallOp, classObject->asClass(), namedTy->name());
-
-                foreach (const LookupItem &o, overloads) {
-                    FullySpecifiedType overloadTy = o.type().simplified();
-
-                    if (Function *funTy = overloadTy->asFunctionType()) {
-                        if (maybeValidPrototype(funTy, actualArgumentCount))
-                            addResult(funTy->returnType().simplified(), lastVisibleSymbol);
+            if (ClassOrNamespace *b = _context.classOrNamespace(namedTy->name(), lastVisibleSymbol->scope())) {
+                foreach (Symbol *overload, b->lookup(functionCallOp)) {
+                    if (Function *funTy = overload->type()->asFunctionType()) {
+                        if (maybeValidPrototype(funTy, actualArgumentCount)) {
+                            Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType();
+                            addResult(proto->returnType().simplified(), lastVisibleSymbol);
+                        }
                     }
                 }
             }
@@ -526,37 +520,29 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
     _results.clear();
 
     const QList<LookupItem> indexResults = operator()(ast->expression);
-    ResolveClass resolveClass;
 
     const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
 
     foreach (const LookupItem &result, baseResults) {
         FullySpecifiedType ty = result.type().simplified();
-        Symbol *contextSymbol = result.lastVisibleSymbol();
+        Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
 
         if (PointerType *ptrTy = ty->asPointerType()) {
-            addResult(ptrTy->elementType().simplified(), contextSymbol);
+            addResult(ptrTy->elementType().simplified(), lastVisibleSymbol);
 
         } else if (ArrayType *arrTy = ty->asArrayType()) {
-            addResult(arrTy->elementType().simplified(), contextSymbol);
+            addResult(arrTy->elementType().simplified(), lastVisibleSymbol);
 
         } else if (NamedType *namedTy = ty->asNamedType()) {
-            const QList<Symbol *> classObjectCandidates =
-                    resolveClass(namedTy->name(), result, _context);
-
-            foreach (Symbol *classObject, classObjectCandidates) {
-                Q_ASSERT(classObject->isClass());
-
-                const QList<LookupItem> overloads =
-                        resolveMember(arrayAccessOp, classObject->asClass(), namedTy->name());
-
-                foreach (LookupItem r, overloads) {
-                    FullySpecifiedType ty = r.type().simplified();
-                    if (Function *funTy = ty->asFunctionType()) {
-                        ty = funTy->returnType().simplified();
-                        addResult(ty, funTy);
+            if (ClassOrNamespace *b = _context.classOrNamespace(namedTy->name(), lastVisibleSymbol->scope())) {
+                foreach (Symbol *overload, b->lookup(arrayAccessOp)) {
+                    if (Function *funTy = overload->type()->asFunctionType()) {
+                        Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType();
+                        // ### TODO: check the actual arguments
+                        addResult(proto->returnType().simplified(), lastVisibleSymbol);
                     }
                 }
+
             }
         }
     }
@@ -567,7 +553,7 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
 {
     // The candidate types for the base expression are stored in
     // _results.
-    QList<LookupItem> baseResults = _results;
+    const QList<LookupItem> baseResults = _results;
 
     // Evaluate the expression-id that follows the access operator.
     const Name *memberName = 0;
@@ -601,56 +587,23 @@ ResolveExpression::resolveBaseExpression(const QList<LookupItem> &baseResults, i
     }
 
     if (accessOp == T_ARROW)  {
-        if (lastVisibleSymbol && ty->isClassType() && ! lastVisibleSymbol->isClass()) {
-            // ### remove ! lastVisibleSymbol->isClass() from the condition.
-            results.append(LookupItem(ty, lastVisibleSymbol));
-
-        } 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()) {
-                    FullySpecifiedType declTy = candidate->type().simplified();
-                    const LookupItem r(declTy, candidate);
-
-                    // update the result
-                    result = r;
-
-                    // refresh the cached ty and lastVisibileSymbol.
-                    ty = result.type().simplified();
-                    lastVisibleSymbol = result.lastVisibleSymbol();
-                    break;
-                }
-            }
-        }
-
         if (NamedType *namedTy = ty->asNamedType()) {
-            ResolveClass resolveClass;
             const Name *arrowAccessOp = control()->operatorNameId(OperatorNameId::ArrowOp);
-            const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, _context);
-
-            foreach (Symbol *classObject, candidates) {
-                const QList<LookupItem> overloads = resolveMember(arrowAccessOp, classObject->asClass(),
-                                                              namedTy->name());
-
-                foreach (const LookupItem &r, overloads) {
-                    FullySpecifiedType typeOfOverloadFunction = r.type().simplified();
-                    Symbol *lastVisibleSymbol = r.lastVisibleSymbol();
-                    Function *funTy = typeOfOverloadFunction->asFunctionType();
-                    if (! funTy)
-                        continue;
 
-                    typeOfOverloadFunction = funTy->returnType().simplified();
+            if (ClassOrNamespace *b = _context.classOrNamespace(namedTy->name(), result.lastVisibleSymbol()->scope())) {
+                foreach (Symbol *overload, b->lookup(arrowAccessOp)) {
+                    if (Function *funTy = overload->type()->asFunctionType()) {
+                        FullySpecifiedType f = instantiate(namedTy->name(), funTy);
+                        FullySpecifiedType retTy = f->asFunctionType()->returnType().simplified();
 
-                    if (PointerType *ptrTy = typeOfOverloadFunction->asPointerType()) {
-                        FullySpecifiedType elementTy = ptrTy->elementType().simplified();
-
-                        if (elementTy->isNamedType())
-                            results.append(LookupItem(elementTy, lastVisibleSymbol));
+                        if (PointerType *ptrTy = retTy->asPointerType()) {
+                            FullySpecifiedType elementTy = ptrTy->elementType().simplified();
+                            results.append(LookupItem(elementTy, overload));
+                        }
                     }
                 }
             }
+
         } else if (PointerType *ptrTy = ty->asPointerType()) {
             FullySpecifiedType elementTy = ptrTy->elementType().simplified();
 
@@ -669,8 +622,7 @@ ResolveExpression::resolveBaseExpression(const QList<LookupItem> &baseResults, i
         }
 
         if (NamedType *namedTy = ty->asNamedType()) {
-            const QList<Scope *> visibleScopes = _context.visibleScopes(result);
-            const QList<Symbol *> candidates = _context.resolve(namedTy->name(), visibleScopes);
+            const QList<Symbol *> candidates = _context.lookup(namedTy->name(), result.lastVisibleSymbol());
             foreach (Symbol *candidate, candidates) {
                 if (candidate->isTypedef() && candidate->type()->isNamedType()) {
                     ty = candidate->type();
@@ -704,10 +656,10 @@ ResolveExpression::resolveMemberExpression(const QList<LookupItem> &baseResults,
                                            const Name *memberName,
                                            bool *replacedDotOperator) const
 {
-    ResolveClass resolveClass;
     QList<LookupItem> results;
 
     const QList<LookupItem> classObjectResults = resolveBaseExpression(baseResults, accessOp, replacedDotOperator);
+
     foreach (const LookupItem &r, classObjectResults) {
         FullySpecifiedType ty = r.type();
 
@@ -715,12 +667,9 @@ ResolveExpression::resolveMemberExpression(const QList<LookupItem> &baseResults,
             results += resolveMember(memberName, klass);
 
         else if (NamedType *namedTy = ty->asNamedType()) {
-            const 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);
+            if (ClassOrNamespace *b = _context.classOrNamespace(namedTy->name(), r.lastVisibleSymbol()->scope())) {
+                foreach (Symbol *c, b->lookup(memberName))
+                    results.append(LookupItem(instantiate(namedTy->name(), c), c));
             }
         }
     }
@@ -728,22 +677,49 @@ ResolveExpression::resolveMemberExpression(const QList<LookupItem> &baseResults,
     return removeDuplicates(results);
 }
 
+FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const
+{
+    if (const TemplateNameId *templId = className->asTemplateNameId()) {
+        if (Class *klass = candidate->enclosingSymbol()->asClass()) {
+            GenTemplateInstance::Substitution subst;
+
+            for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
+                FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
+
+                if (i < klass->templateParameterCount()) {
+                    const Name *templArgName = klass->templateParameterAt(i)->name();
+
+                    if (templArgName && templArgName->identifier()) {
+                        const Identifier *templArgId = templArgName->identifier();
+                        subst.append(qMakePair(templArgId, templArgTy));
+                    }
+                }
+            }
+
+            GenTemplateInstance inst(_context.control(), subst);
+            return inst(candidate);
+        }
+    }
+
+    return candidate->type();
+}
+
 QList<LookupItem>
 ResolveExpression::resolveMember(const Name *memberName, Class *klass,
                                  const Name *className) const
 {
     QList<LookupItem> results;
 
+    if (! klass)
+        return results;
+
     if (! className)
         className = klass->name();
 
     if (! className)
         return results;
 
-    QList<Scope *> scopes;
-    _context.expand(klass->members(), _context.visibleScopes(), &scopes);
-
-    const QList<Symbol *> candidates = _context.resolve(memberName, scopes);
+    const QList<Symbol *> candidates = _context.lookup(memberName, klass->members());
 
     foreach (Symbol *candidate, candidates) {
         FullySpecifiedType ty = candidate->type();
@@ -767,7 +743,7 @@ ResolveExpression::resolveMember(const Name *memberName, Class *klass,
                 }
             }
 
-            GenTemplateInstance inst(_context, subst);
+            GenTemplateInstance inst(_context.control(), subst);
             ty = inst(candidate);
         }
 
@@ -782,14 +758,10 @@ QList<LookupItem>
 ResolveExpression::resolveMember(const Name *memberName, ObjCClass *klass) const
 {
     QList<LookupItem> results;
-
     if (!memberName || !klass)
         return results;
 
-    QList<Scope *> scopes;
-    _context.expand(klass->members(), _context.visibleScopes(), &scopes);
-
-    QList<Symbol *> candidates = _context.resolve(memberName, scopes);
+    const QList<Symbol *> candidates = _context.lookup(memberName, klass->members());
 
     foreach (Symbol *candidate, candidates) {
         FullySpecifiedType ty = candidate->type();
@@ -828,8 +800,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
         }
 
         if (klassName&&ast->selector && ast->selector->name) {
-            ResolveObjCClass resolveObjCClass;
-            QList<Symbol *> resolvedSymbols = resolveObjCClass(klassName, result, _context);
+            const QList<Symbol *> resolvedSymbols = _context.lookup(klassName, result.lastVisibleSymbol());
             foreach (Symbol *resolvedSymbol, resolvedSymbols)
                 if (ObjCClass *klass = resolvedSymbol->asObjCClass())
                     _results.append(resolveMember(ast->selector->name, klass));
@@ -839,103 +810,3 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
     return false;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-ResolveClass::ResolveClass()
-{ }
-
-QList<Symbol *> ResolveClass::operator()(const Name *name,
-                                         const LookupItem &p,
-                                         const DeprecatedLookupContext &context)
-{
-    const QList<LookupItem> previousBlackList = _blackList;
-    const QList<Symbol *> symbols = resolveClass(name, p, context);
-    _blackList = previousBlackList;
-    return symbols;
-}
-
-QList<Symbol *> ResolveClass::resolveClass(const Name *name,
-                                           const LookupItem &p,
-                                           const DeprecatedLookupContext &context)
-{
-    QList<Symbol *> resolvedSymbols;
-
-    if (_blackList.contains(p))
-        return resolvedSymbols;
-
-    _blackList.append(p);
-
-    const QList<Symbol *> candidates =
-            context.resolve(name, context.visibleScopes(p));
-
-    foreach (Symbol *candidate, candidates) {
-        if (Class *klass = candidate->asClass()) {
-            if (resolvedSymbols.contains(klass))
-                continue; // we already know about `klass'
-            resolvedSymbols.append(klass);
-        } else if (candidate->isTypedef()) {
-            if (Declaration *decl = candidate->asDeclaration()) {
-                if (Class *asClass = decl->type()->asClassType()) {
-                    // typedef struct { } Point;
-                    // Point pt;
-                    // pt.
-                    resolvedSymbols.append(asClass);
-                } else {
-                    // typedef Point Boh;
-                    // Boh b;
-                    // b.
-                    FullySpecifiedType declType = decl->type().simplified();
-                    if (NamedType *namedTy = declType->asNamedType()) {
-                        const LookupItem r(declType, decl);
-                        resolvedSymbols += resolveClass(namedTy->name(), r, context);
-                    }
-                }
-            }
-        } else if (Declaration *decl = candidate->asDeclaration()) {
-            if (Function *funTy = decl->type()->asFunctionType()) {
-                // QString foo("ciao");
-                // foo.
-                if (funTy->scope() && (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope())) {
-                    FullySpecifiedType retTy = funTy->returnType().simplified();
-                    if (NamedType *namedTy = retTy->asNamedType()) {
-                        const LookupItem r(retTy, decl);
-                        resolvedSymbols += resolveClass(namedTy->name(), r, context);
-                    }
-                }
-            }
-        }
-    }
-
-    return resolvedSymbols;
-}
-
-ResolveObjCClass::ResolveObjCClass()
-{}
-
-QList<Symbol *> ResolveObjCClass::operator ()(const Name *name,
-                                              const LookupItem &p,
-                                              const DeprecatedLookupContext &context)
-{
-    QList<Symbol *> resolvedSymbols;
-
-    const QList<Symbol *> candidates =
-            context.resolve(name, context.visibleScopes(p));
-
-    foreach (Symbol *candidate, candidates) {
-        if (ObjCClass *klass = candidate->asObjCClass()) {
-            if (resolvedSymbols.contains(klass))
-                continue; // we already know about `klass'
-            resolvedSymbols.append(klass);
-        } else if (candidate->isTypedef()) {
-            if (Declaration *decl = candidate->asDeclaration()) {
-                if (decl->type()->isObjCClassType()) {
-                    ObjCClass *klass = decl->type()->asObjCClassType();
-                    if (resolvedSymbols.contains(klass))
-                        continue;
-                    resolvedSymbols.append(klass);
-                }
-            }
-        }
-    }
-
-    return resolvedSymbols;
-}
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 8f7e6fb85af..d1fbc84e2fd 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -30,7 +30,7 @@
 #ifndef CPLUSPLUS_RESOLVEEXPRESSION_H
 #define CPLUSPLUS_RESOLVEEXPRESSION_H
 
-#include "DeprecatedLookupContext.h"
+#include "LookupContext.h"
 
 #include <ASTVisitor.h>
 #include <Semantic.h>
@@ -41,27 +41,30 @@ namespace CPlusPlus {
 class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor
 {
 public:
-    ResolveExpression(const DeprecatedLookupContext &context);
+    ResolveExpression(Symbol *lastVisibleSymbol, const LookupContext &context);
+    ResolveExpression(Scope *scope, const LookupContext &context);
+
     virtual ~ResolveExpression();
 
     QList<LookupItem> operator()(ExpressionAST *ast);
 
     QList<LookupItem> resolveMemberExpression(const QList<LookupItem> &baseResults,
-                                          unsigned accessOp,
-                                          const Name *memberName,
-                                          bool *replacedDotOperator = 0) const;
+                                              unsigned accessOp,
+                                              const Name *memberName,
+                                              bool *replacedDotOperator = 0) const;
 
     QList<LookupItem> resolveBaseExpression(const QList<LookupItem> &baseResults,
-                                        int accessOp,
-                                        bool *replacedDotOperator = 0) const;
+                                            int accessOp,
+                                            bool *replacedDotOperator = 0) const;
 
-    QList<LookupItem> resolveMember(const Name *memberName, Class *klass,
-                                    const Name *className = 0) const;
+    Q_DECL_DEPRECATED QList<LookupItem> resolveMember(const Name *memberName, Class *klass,
+                                                      const Name *className = 0) const;
 
-    QList<LookupItem> resolveMember(const Name *memberName, ObjCClass *klass) const;
+    Q_DECL_DEPRECATED QList<LookupItem> resolveMember(const Name *memberName, ObjCClass *klass) const;
 
 protected:
     QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
+    FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
 
     void thisObject();
     void addResult(const FullySpecifiedType &ty, Symbol *symbol = 0);
@@ -113,44 +116,15 @@ protected:
     // Objective-C expressions
     virtual bool visit(ObjCMessageExpressionAST *ast);
 
-    QList<Scope *> visibleScopes(const LookupItem &result) const;
-
 private:
-    DeprecatedLookupContext _context;
+    Symbol *_lastVisibleSymbol;
+    Scope *_scope;
+    LookupContext _context;
     Semantic sem;
     QList<LookupItem> _results;
     Symbol *_declSymbol;
 };
 
-class CPLUSPLUS_EXPORT ResolveClass
-{
-public:
-    ResolveClass();
-
-    QList<Symbol *> operator()(const Name *name,
-                               const LookupItem &p,
-                               const DeprecatedLookupContext &context);
-
-private:
-    QList<Symbol *> resolveClass(const Name *name,
-                                 const LookupItem &p,
-                                 const DeprecatedLookupContext &context);
-
-private:
-    QList<LookupItem> _blackList;
-};
-
-class CPLUSPLUS_EXPORT ResolveObjCClass
-{
-public:
-    ResolveObjCClass();
-
-    QList<Symbol *> operator()(const Name *name,
-                               const LookupItem &p,
-                               const DeprecatedLookupContext &context);
-};
-
-
 } // end of namespace CPlusPlus
 
 #endif // CPLUSPLUS_RESOLVEEXPRESSION_H
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index cfad0b737d8..cfe8ac74e99 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -29,7 +29,7 @@
 
 #include "TypeOfExpression.h"
 #include <TranslationUnit.h>
-#include "DeprecatedLookupContext.h"
+#include "LookupContext.h"
 #include "ResolveExpression.h"
 #include "pp.h"
 
@@ -39,44 +39,59 @@
 using namespace CPlusPlus;
 
 TypeOfExpression::TypeOfExpression():
-    m_ast(0)
+    m_ast(0),
+    m_lastVisibleSymbol(0)
 {
 }
 
-Snapshot TypeOfExpression::snapshot() const
+void TypeOfExpression::reset()
 {
-    return m_snapshot;
+    m_thisDocument.clear();
+    m_snapshot = Snapshot();
+    m_ast = 0;
+    m_lastVisibleSymbol = 0;
+    m_lookupContext = LookupContext();
+    m_bindings.clear();
+    m_environment.clear();
 }
 
-void TypeOfExpression::setSnapshot(const Snapshot &documents)
+void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
+                            QSharedPointer<CreateBindings> bindings)
 {
-    m_snapshot = documents;
-    m_lookupContext = DeprecatedLookupContext();
+    m_thisDocument = thisDocument;
+    m_snapshot = snapshot;
+    m_ast = 0;
+    m_lastVisibleSymbol = 0;
+    m_lookupContext = LookupContext();
+    m_bindings = bindings;
+    m_environment.clear();
 }
 
 QList<LookupItem> TypeOfExpression::operator()(const QString &expression,
-                                           Document::Ptr document,
-                                           Symbol *lastVisibleSymbol,
-                                           PreprocessMode mode)
+                                               Symbol *lastVisibleSymbol,
+                                               PreprocessMode mode)
 {
     QString code = expression;
+
     if (mode == Preprocess)
-        code = preprocessedExpression(expression, m_snapshot, document);
+        code = preprocessedExpression(expression);
+
     Document::Ptr expressionDoc = documentForExpression(code);
     expressionDoc->check();
     m_ast = extractExpressionAST(expressionDoc);
 
-    m_lookupContext = DeprecatedLookupContext(lastVisibleSymbol, expressionDoc,
-                                    document, m_snapshot);
+    m_lastVisibleSymbol = lastVisibleSymbol;
+
+    m_lookupContext = LookupContext(expressionDoc, m_thisDocument, m_snapshot);
+    m_lookupContext.setBindings(m_bindings);
 
-    ResolveExpression resolveExpression(m_lookupContext);
+    ResolveExpression resolveExpression(lastVisibleSymbol, m_lookupContext);
     return resolveExpression(m_ast);
 }
 
-QString TypeOfExpression::preprocess(const QString &expression,
-                                     Document::Ptr document) const
+QString TypeOfExpression::preprocess(const QString &expression) const
 {
-    return preprocessedExpression(expression, m_snapshot, document);
+    return preprocessedExpression(expression);
 }
 
 ExpressionAST *TypeOfExpression::ast() const
@@ -84,7 +99,12 @@ ExpressionAST *TypeOfExpression::ast() const
     return m_ast;
 }
 
-const DeprecatedLookupContext &TypeOfExpression::lookupContext() const
+Symbol *TypeOfExpression::lastVisibleSymbol() const
+{
+    return m_lastVisibleSymbol;
+}
+
+const LookupContext &TypeOfExpression::lookupContext() const
 {
     return m_lookupContext;
 }
@@ -112,37 +132,35 @@ Document::Ptr TypeOfExpression::documentForExpression(const QString &expression)
     return doc;
 }
 
-void TypeOfExpression::processEnvironment(Snapshot documents,
-                                          Document::Ptr doc, Environment *env,
+void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env,
                                           QSet<QString> *processed) const
 {
-    if (! doc)
-        return;
-    if (processed->contains(doc->fileName()))
-        return;
-    processed->insert(doc->fileName());
-    foreach (const Document::Include &incl, doc->includes()) {
-        processEnvironment(documents,
-                           documents.document(incl.fileName()),
-                           env, processed);
+    if (doc && ! processed->contains(doc->fileName())) {
+        processed->insert(doc->fileName());
+
+        foreach (const Document::Include &incl, doc->includes())
+            processEnvironment(m_snapshot.document(incl.fileName()), env, processed);
+
+        foreach (const Macro &macro, doc->definedMacros())
+            env->bind(macro);
     }
-    foreach (const Macro &macro, doc->definedMacros())
-        env->bind(macro);
 }
 
-QString TypeOfExpression::preprocessedExpression(const QString &expression,
-                                                 Snapshot documents,
-                                                 Document::Ptr thisDocument) const
+QString TypeOfExpression::preprocessedExpression(const QString &expression) const
 {
     if (expression.trimmed().isEmpty())
         return expression;
 
-    Environment env;
-    QSet<QString> processed;
-    processEnvironment(documents, thisDocument,
-                       &env, &processed);
+    if (! m_environment) {
+        Environment *env = new Environment(); // ### cache the environment.
+
+        QSet<QString> processed;
+        processEnvironment(m_thisDocument, env, &processed);
+        m_environment = QSharedPointer<Environment>(env);
+    }
+
     const QByteArray code = expression.toUtf8();
-    Preprocessor preproc(0, &env);
+    Preprocessor preproc(0, m_environment.data());
     const QByteArray preprocessedCode = preproc("<expression>", code);
     return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size());
 }
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index 24591158872..b2c181a419b 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -30,7 +30,8 @@
 #define CPLUSPLUS_TYPEOFEXPRESSION_H
 
 #include "CppDocument.h"
-#include "DeprecatedLookupContext.h"
+#include "LookupContext.h"
+#include "PreprocessorEnvironment.h"
 
 #include <ASTfwd.h>
 #include <QtCore/QMap>
@@ -44,11 +45,11 @@ class Macro;
 
 class CPLUSPLUS_EXPORT TypeOfExpression
 {
+    Q_DISABLE_COPY(TypeOfExpression)
+
 public:
     TypeOfExpression();
 
-    Snapshot snapshot() const;
-
     /**
      * Sets the documents used to evaluate expressions. Should be set before
      * calling this functor.
@@ -56,7 +57,10 @@ public:
      * Also clears the lookup context, so can be used to make sure references
      * to the documents previously used are removed.
      */
-    void setSnapshot(const Snapshot &documents);
+    void init(Document::Ptr thisDocument, const Snapshot &snapshot,
+              QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>());
+
+    void reset();
 
     enum PreprocessMode {
         NoPreprocess,
@@ -72,14 +76,13 @@ public:
      * has been made!
      *
      * @param expression        The expression to evaluate.
-     * @param document          The document the expression is part of.
      * @param lastVisibleSymbol The last visible symbol in the document.
      */
-    QList<LookupItem> operator()(const QString &expression, Document::Ptr document,
-                             Symbol *lastVisibleSymbol,
-                             PreprocessMode mode = NoPreprocess);
+    QList<LookupItem> operator()(const QString &expression,
+                                 Symbol *lastVisibleSymbol,
+                                 PreprocessMode mode = NoPreprocess);
 
-    QString preprocess(const QString &expression, Document::Ptr document) const;
+    QString preprocess(const QString &expression) const;
 
     /**
      * Returns the AST of the last evaluated expression.
@@ -89,7 +92,8 @@ public:
     /**
      * Returns the lookup context of the last evaluated expression.
      */
-    const DeprecatedLookupContext &lookupContext() const;
+    const LookupContext &lookupContext() const;
+    Symbol *lastVisibleSymbol() const;
 
     ExpressionAST *expressionAST() const;
 
@@ -97,17 +101,19 @@ private:
     ExpressionAST *extractExpressionAST(Document::Ptr doc) const;
     Document::Ptr documentForExpression(const QString &expression) const;
 
-    void processEnvironment(CPlusPlus::Snapshot documents,
-                            CPlusPlus::Document::Ptr doc, CPlusPlus::Environment *env,
+    void processEnvironment(Document::Ptr doc, Environment *env,
                             QSet<QString> *processed) const;
 
-    QString preprocessedExpression(const QString &expression,
-                                   CPlusPlus::Snapshot documents,
-                                   CPlusPlus::Document::Ptr thisDocument) const;
+    QString preprocessedExpression(const QString &expression) const;
 
+private:
+    Document::Ptr m_thisDocument;
     Snapshot m_snapshot;
+    QSharedPointer<CreateBindings> m_bindings;
     ExpressionAST *m_ast;
-    DeprecatedLookupContext m_lookupContext;
+    Symbol *m_lastVisibleSymbol;
+    LookupContext m_lookupContext;
+    mutable QSharedPointer<Environment> m_environment;
 };
 
 } // namespace CPlusPlus
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index dad2cb3c1c8..454f889e23d 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -560,7 +560,7 @@ protected:
 
 } // end of anonymous namespace
 
-static const QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const DeprecatedLookupContext &context)
+static const QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, Control *control)
 {
     const Name *symbolName = s->name();
     if (! symbolName)
@@ -591,7 +591,7 @@ static const QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const Deprecat
         names.append(symbolName);
     }
 
-    return context.control()->qualifiedNameId(names.constData(), names.size());
+    return control->qualifiedNameId(names.constData(), names.size());
 }
 
 CPPEditorEditable::CPPEditorEditable(CPPEditor *editor)
@@ -869,13 +869,12 @@ CPlusPlus::Symbol *CPPEditor::findCanonicalSymbol(const QTextCursor &cursor,
     // qDebug() << "code:" << code;
 
     TypeOfExpression typeOfExpression;
-    typeOfExpression.setSnapshot(snapshot);
+    typeOfExpression.init(doc, snapshot);
 
     Symbol *lastVisibleSymbol = doc->findSymbolAt(line, col);
 
-    const QList<LookupItem> results = typeOfExpression(code, doc,
-                                                   lastVisibleSymbol,
-                                                   TypeOfExpression::Preprocess);
+    const QList<LookupItem> results = typeOfExpression(code, lastVisibleSymbol,
+                                                       TypeOfExpression::Preprocess);
 
     NamespaceBindingPtr glo = bind(doc, snapshot);
     Symbol *canonicalSymbol = DeprecatedLookupContext::canonicalSymbol(results, glo.data());
@@ -1255,13 +1254,10 @@ void CPPEditor::switchDeclarationDefinition()
     }
 
     if (f) {
-        TypeOfExpression typeOfExpression;
-        typeOfExpression.setSnapshot(m_modelManager->snapshot());
-        QList<LookupItem> resolvedSymbols = typeOfExpression(QString(), doc, lastSymbol);
-        const DeprecatedLookupContext &context = typeOfExpression.lookupContext();
+        LookupContext context(doc, snapshot);
 
-        const QualifiedNameId *q = qualifiedNameIdForSymbol(f, context);
-        QList<Symbol *> symbols = context.resolve(q);
+        const QualifiedNameId *q = qualifiedNameIdForSymbol(f, context.control());
+        const QList<Symbol *> symbols = context.lookup(q, lastSymbol); // ### FIXME
 
         Symbol *declaration = 0;
         foreach (declaration, symbols) {
@@ -1438,9 +1434,9 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
     const QString expression = expressionUnderCursor(tc);
 
     TypeOfExpression typeOfExpression;
-    typeOfExpression.setSnapshot(snapshot);
+    typeOfExpression.init(doc, snapshot);
     QList<LookupItem> resolvedSymbols =
-            typeOfExpression(expression, doc, lastSymbol);
+            typeOfExpression(expression, lastSymbol);
 
     if (!resolvedSymbols.isEmpty()) {
         LookupItem result = skipForwardDeclarations(resolvedSymbols);
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 63be4f097fa..f38179e09ed 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -180,7 +180,8 @@ static QString buildHelpId(Symbol *symbol, const Name *name)
 
 // ### move me
 static FullySpecifiedType resolve(const FullySpecifiedType &ty,
-                                  const DeprecatedLookupContext &context,
+                                  const LookupContext &context,
+                                  Symbol *lastVisibleSymbol,
                                   Symbol **resolvedSymbol,
                                   const Name **resolvedName)
 {
@@ -188,22 +189,25 @@ static FullySpecifiedType resolve(const FullySpecifiedType &ty,
 
     if (const PointerType *ptrTy = ty->asPointerType()) {
         return control->pointerType(resolve(ptrTy->elementType(), context,
+                                            lastVisibleSymbol,
                                             resolvedSymbol, resolvedName));
 
     } else if (const ReferenceType *refTy = ty->asReferenceType()) {
         return control->referenceType(resolve(refTy->elementType(), context,
+                                              lastVisibleSymbol,
                                               resolvedSymbol, resolvedName));
 
     } else if (const PointerToMemberType *ptrToMemTy = ty->asPointerToMemberType()) {
         return control->pointerToMemberType(ptrToMemTy->memberName(),
                                             resolve(ptrToMemTy->elementType(), context,
+                                                    lastVisibleSymbol,
                                                     resolvedSymbol, resolvedName));
 
     } else if (const NamedType *namedTy = ty->asNamedType()) {
         if (resolvedName)
             *resolvedName = namedTy->name();
 
-        const QList<Symbol *> candidates = context.resolve(namedTy->name());
+        const QList<Symbol *> candidates = context.lookup(namedTy->name(), lastVisibleSymbol);
 
         foreach (Symbol *c, candidates) {
             if (c->isClass() || c->isEnum()) {
@@ -284,7 +288,7 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
     Symbol *lastSymbol = doc->findSymbolAt(line, column);
 
     TypeOfExpression typeOfExpression;
-    typeOfExpression.setSnapshot(documents);
+    typeOfExpression.init(doc, documents);
 
     // We only want to show F1 if the tooltip matches the help id
     bool showF1 = true;
@@ -332,7 +336,7 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
         ExpressionUnderCursor expressionUnderCursor;
         const QString expression = expressionUnderCursor(tc);
 
-        const QList<LookupItem> types = typeOfExpression(expression, doc, lastSymbol);
+        const QList<LookupItem> types = typeOfExpression(expression, lastSymbol);
 
         if (!types.isEmpty()) {
             const LookupItem result = types.first();
@@ -343,6 +347,7 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
             Symbol *resolvedSymbol = lookupSymbol;
             const Name *resolvedName = lookupSymbol ? lookupSymbol->name() : 0;
             firstType = resolve(firstType, typeOfExpression.lookupContext(),
+                                lastSymbol,
                                 &resolvedSymbol, &resolvedName);
 
             if (resolvedSymbol && resolvedSymbol->scope()
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index bf295dcd095..5a7b97e8725 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -1323,14 +1323,21 @@ void QuickFixOperation::apply()
  */
 const QList<LookupItem> QuickFixOperation::typeOf(CPlusPlus::ExpressionAST *ast)
 {
+#ifdef __GNUC__
+#  warning port me
+#endif
+
+    qWarning() << Q_FUNC_INFO << __LINE__;
+    return QList<LookupItem>();
+
+#if 0
     unsigned line, column;
     document()->translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
     Symbol *lastVisibleSymbol = document()->findSymbolAt(line, column);
 
-    _lookupContext = DeprecatedLookupContext(lastVisibleSymbol, document(), document(), snapshot());
-
-    ResolveExpression resolveExpression(_lookupContext);
+    ResolveExpression resolveExpression(lastVisibleSymbol, _lookupContext);
     return resolveExpression(ast);
+#endif
 }
 
 CPPQuickFixCollector::CPPQuickFixCollector()
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index a5f583254cd..b47ebf40393 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -90,7 +90,7 @@ class FunctionArgumentWidget : public QLabel
 public:
     FunctionArgumentWidget();
     void showFunctionHint(QList<Function *> functionSymbols,
-                          const DeprecatedLookupContext &context,
+                          const LookupContext &context,
                           int startPosition);
 
 protected:
@@ -118,7 +118,7 @@ private:
     QLabel *m_numberLabel;
     Utils::FakeToolTip *m_popupFrame;
     QList<Function *> m_items;
-    DeprecatedLookupContext m_context;
+    LookupContext m_context;
 };
 
 class ConvertToCompletionItem: protected NameVisitor
@@ -266,7 +266,7 @@ FunctionArgumentWidget::FunctionArgumentWidget():
 }
 
 void FunctionArgumentWidget::showFunctionHint(QList<Function *> functionSymbols,
-                                              const DeprecatedLookupContext &context,
+                                              const LookupContext &context,
                                               int startPosition)
 {
     Q_ASSERT(!functionSymbols.isEmpty());
@@ -784,7 +784,7 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit,
     if (! thisDocument)
         return -1;
 
-    typeOfExpression.setSnapshot(snapshot);
+    typeOfExpression.init(thisDocument, snapshot);
     Symbol *lastVisibleSymbol = thisDocument->findSymbolAt(line, column);
 
     if (expression.isEmpty()) {
@@ -798,14 +798,14 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit,
     }
 
 
-    QList<LookupItem> results = typeOfExpression(expression, thisDocument, lastVisibleSymbol, TypeOfExpression::Preprocess);
-    DeprecatedLookupContext context = typeOfExpression.lookupContext();
+    QList<LookupItem> results = typeOfExpression(expression, lastVisibleSymbol, TypeOfExpression::Preprocess);
+    LookupContext context = typeOfExpression.lookupContext();
 
     if (results.isEmpty()) {
         if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
             if (! (expression.isEmpty() || expression == QLatin1String("this"))) {
                 expression = QLatin1String("this");
-                results = typeOfExpression(expression, thisDocument, lastVisibleSymbol);
+                results = typeOfExpression(expression, lastVisibleSymbol);
             }
 
             if (results.isEmpty())
@@ -828,8 +828,7 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit,
 
             // Resolve the type of this expression
             const QList<LookupItem> results =
-                    typeOfExpression(baseExpression, thisDocument,
-                                     lastVisibleSymbol,
+                    typeOfExpression(baseExpression, lastVisibleSymbol,
                                      TypeOfExpression::Preprocess);
 
             // If it's a class, add completions for the constructors
@@ -908,7 +907,7 @@ int CppCodeCompletion::globalCompletion(Symbol *lastVisibleSymbol,
 }
 
 bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &results,
-                                                      const DeprecatedLookupContext &context,
+                                                      const LookupContext &context,
                                                       int endOfExpression, bool toolTipOnly)
 {
     QList<Function *> functions;
@@ -970,28 +969,19 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &r
     }
 
     if (functions.isEmpty()) {
-        ResolveExpression resolveExpression(context);
-        ResolveClass resolveClass;
         const Name *functionCallOp = context.control()->operatorNameId(OperatorNameId::FunctionCallOp);
 
         foreach (const LookupItem &result, results) {
             FullySpecifiedType ty = result.type().simplified();
+            Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
 
             if (NamedType *namedTy = ty->asNamedType()) {
-                const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, context);
+                if (ClassOrNamespace *b = context.classOrNamespace(namedTy->name(), lastVisibleSymbol)) {
+                    foreach (Symbol *overload, b->lookup(functionCallOp)) {
+                        FullySpecifiedType overloadTy = overload->type().simplified();
 
-                foreach (Symbol *classObjectCandidate, classObjectCandidates) {
-                    if (Class *klass = classObjectCandidate->asClass()) {
-                        const QList<LookupItem> overloads =
-                                resolveExpression.resolveMember(functionCallOp, klass,
-                                                                namedTy->name());
-
-                        foreach (const LookupItem &overloadResult, overloads) {
-                            FullySpecifiedType overloadTy = overloadResult.type().simplified();
-
-                            if (Function *funTy = overloadTy->asFunctionType())
-                                functions.append(funTy);
-                        }
+                        if (Function *funTy = overloadTy->asFunctionType())
+                            functions.append(funTy);
                     }
                 }
             }
@@ -1019,8 +1009,8 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &r
         // find a scope that encloses the current location, starting from the lastVisibileSymbol
         // and moving outwards
         Scope *sc = 0;
-        if (context.symbol())
-            sc = context.symbol()->scope();
+        if (typeOfExpression.lastVisibleSymbol())
+            sc = typeOfExpression.lastVisibleSymbol()->scope();
         else if (context.thisDocument())
             sc = context.thisDocument()->globalSymbols();
 
@@ -1102,13 +1092,12 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &r
 }
 
 bool CppCodeCompletion::completeMember(const QList<LookupItem> &baseResults,
-                                       const DeprecatedLookupContext &context)
+                                       const LookupContext &context)
 {
     if (baseResults.isEmpty())
         return false;
 
-    ResolveExpression resolveExpression(context);
-    ResolveClass resolveClass;
+    ResolveExpression resolveExpression(typeOfExpression.lastVisibleSymbol(), context);
 
     bool replacedDotOperator = false;
     const QList<LookupItem> classObjectResults =
@@ -1116,6 +1105,8 @@ bool CppCodeCompletion::completeMember(const QList<LookupItem> &baseResults,
                                                     m_completionOperator,
                                                     &replacedDotOperator);
 
+    ClassOrNamespace *classOrNamespace = 0;
+
     QList<Symbol *> classObjectCandidates;
     foreach (const LookupItem &r, classObjectResults) {
         FullySpecifiedType ty = r.type().simplified();
@@ -1124,17 +1115,19 @@ bool CppCodeCompletion::completeMember(const QList<LookupItem> &baseResults,
             classObjectCandidates.append(klass);
 
         else if (NamedType *namedTy = ty->asNamedType()) {
-            const Name *className = namedTy->name();
-            const QList<Symbol *> classes = resolveClass(className, r, context);
+            if (ClassOrNamespace *b = context.classOrNamespace(namedTy->name(), r.lastVisibleSymbol()->scope())) {
+                classOrNamespace = b;
+                break;
+
+            }  else {
+                Overview oo;
 
-            foreach (Symbol *c, classes) {
-                if (Class *klass = c->asClass())
-                    classObjectCandidates.append(klass);
+                qDebug() << "*** no class for" << oo(namedTy->name());
             }
         }
     }
 
-    if (replacedDotOperator && ! classObjectCandidates.isEmpty()) {
+    if (replacedDotOperator && classOrNamespace) {
         // Replace . with ->
         int length = m_editor->position() - m_startPosition + 1;
         m_editor->setCurPos(m_startPosition - 1);
@@ -1142,7 +1135,9 @@ bool CppCodeCompletion::completeMember(const QList<LookupItem> &baseResults,
         ++m_startPosition;
     }
 
-    completeClass(classObjectCandidates, context, /*static lookup = */ false);
+    if (classOrNamespace)
+        completeClass(classOrNamespace, context, /*static lookup = */ false);
+
     if (! m_completions.isEmpty())
         return true;
 
@@ -1150,17 +1145,11 @@ bool CppCodeCompletion::completeMember(const QList<LookupItem> &baseResults,
 }
 
 bool CppCodeCompletion::completeScope(const QList<LookupItem> &results,
-                                      const DeprecatedLookupContext &deprecatedContext)
+                                      const LookupContext &context)
 {
-    qDebug() << Q_FUNC_INFO;
-
     if (results.isEmpty())
         return false;
 
-    LookupContext context(deprecatedContext.expressionDocument(),
-                          deprecatedContext.thisDocument(),
-                          deprecatedContext.snapshot());
-
     foreach (const LookupItem &result, results) {
         FullySpecifiedType ty = result.type();
         Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
@@ -1434,13 +1423,16 @@ void CppCodeCompletion::completeClass(const QList<Symbol *> &candidates,
 }
 
 bool CppCodeCompletion::completeQtMethod(const QList<LookupItem> &results,
-                                         const DeprecatedLookupContext &context,
+                                         const LookupContext &newContext,
                                          bool wantSignals)
 {
     if (results.isEmpty())
         return false;
 
-    ResolveClass resolveClass;
+    DeprecatedLookupContext context(typeOfExpression.lastVisibleSymbol(),
+                                    newContext.expressionDocument(),
+                                    newContext.thisDocument(),
+                                    newContext.snapshot());
 
     ConvertToCompletionItem toCompletionItem(this);
     Overview o;
@@ -1461,8 +1453,11 @@ bool CppCodeCompletion::completeQtMethod(const QList<LookupItem> &results,
         if (! namedTy) // not a class name.
             continue;
 
-        const QList<Symbol *> classObjects =
-                resolveClass(namedTy->name(), p, context);
+        ClassOrNamespace *b = newContext.classOrNamespace(namedTy->name(), p.lastVisibleSymbol());
+        if (! b)
+            continue;
+
+        const QList<Symbol *> classObjects = b->symbols();
 
         if (classObjects.isEmpty())
             continue;
@@ -1710,7 +1705,7 @@ void CppCodeCompletion::cleanup()
 
     // Set empty map in order to avoid referencing old versions of the documents
     // until the next completion
-    typeOfExpression.setSnapshot(Snapshot());
+    typeOfExpression.reset();
 }
 
 int CppCodeCompletion::findStartOfName(int pos) const
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index 76090459c53..12f16687669 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -114,14 +114,14 @@ private:
                          const CPlusPlus::Snapshot &snapshot);
 
     bool completeConstructorOrFunction(const QList<CPlusPlus::LookupItem> &,
-                                       const CPlusPlus::DeprecatedLookupContext &,
+                                       const CPlusPlus::LookupContext &,
                                        int endOfExpression, bool toolTipOnly);
 
     bool completeMember(const QList<CPlusPlus::LookupItem> &,
-                        const CPlusPlus::DeprecatedLookupContext &context);
+                        const CPlusPlus::LookupContext &context);
 
     bool completeScope(const QList<CPlusPlus::LookupItem> &,
-                       const CPlusPlus::DeprecatedLookupContext &context);
+                       const CPlusPlus::LookupContext &context);
 
     void completeNamespace(CPlusPlus::ClassOrNamespace *binding,
                            const CPlusPlus::LookupContext &context);
@@ -139,16 +139,16 @@ private:
 
     bool completeConstructors(CPlusPlus::Class *klass);
 
-    bool completeQtMethod(const QList<CPlusPlus::LookupItem> &,
-                          const CPlusPlus::DeprecatedLookupContext &context,
+    bool completeQtMethod(const QList<CPlusPlus::LookupItem> &context,
+                          const CPlusPlus::LookupContext &context,
                           bool wantSignals);
 
     bool completeSignal(const QList<CPlusPlus::LookupItem> &results,
-                        const CPlusPlus::DeprecatedLookupContext &context)
+                        const CPlusPlus::LookupContext &context)
     { return completeQtMethod(results, context, true); }
 
     bool completeSlot(const QList<CPlusPlus::LookupItem> &results,
-                      const CPlusPlus::DeprecatedLookupContext &context)
+                      const CPlusPlus::LookupContext &context)
     { return completeQtMethod(results, context, false); }
 
     int findStartOfName(int pos = -1) const;
-- 
GitLab