diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 94832cc1420f8606d49e51b07bfe0e5b888acf2f..cb9598614b6f869489c9ec9b647ea8990847dd68 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -740,11 +740,12 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
                 continue; // nothing to do
 
             foreach (Function *fun, result) {
-                const QList<Symbol *> declarations = context.lookup(fun->name(), fun->scope());
+                const QList<LookupItem> declarations = context.lookup(fun->name(), fun->scope());
                 if (declarations.isEmpty())
                     continue;
 
-                else if (enclosingType == context.lookupType(declarations.first()))
+                const LookupItem best = declarations.first();
+                if (enclosingType == context.lookupType(best.declaration()))
                     viableFunctions.append(fun);
             }
 
diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2dcec18a419ce34ad9fa063b06b5f2897722e9e7
--- /dev/null
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -0,0 +1,364 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+#include "CppRewriter.h"
+#include <TypeVisitor.h>
+#include <NameVisitor.h>
+#include <CoreTypes.h>
+#include <Symbols.h>
+#include <Literals.h>
+#include <Names.h>
+#include <Scope.h>
+
+#include <QtCore/QVarLengthArray>
+#include <QtCore/QDebug>
+
+using namespace CPlusPlus;
+
+class CPlusPlus::Rewrite
+{
+public:
+    Rewrite(Control *control, const SubstitutionEnvironment &env)
+        : control(control), env(env), rewriteType(this), rewriteName(this) {}
+
+    class RewriteType: public TypeVisitor
+    {
+        Rewrite *rewrite;
+        QList<FullySpecifiedType> temps;
+
+        Control *control() const
+        { return rewrite->control; }
+
+        void accept(const FullySpecifiedType &ty)
+        {
+            TypeVisitor::accept(ty.type());
+            unsigned flags = ty.flags();
+            flags |= temps.back().flags();
+            temps.back().setFlags(flags);
+        }
+
+    public:
+        RewriteType(Rewrite *r): rewrite(r) {}
+
+        FullySpecifiedType operator()(const FullySpecifiedType &ty)
+        {
+            accept(ty);
+            return temps.takeLast();
+        }
+
+        virtual void visit(UndefinedType *)
+        {
+            temps.append(FullySpecifiedType());
+        }
+
+        virtual void visit(VoidType *)
+        {
+            temps.append(control()->voidType());
+        }
+
+        virtual void visit(IntegerType *type)
+        {
+            temps.append(control()->integerType(type->kind()));
+        }
+
+        virtual void visit(FloatType *type)
+        {
+            temps.append(control()->floatType(type->kind()));
+        }
+
+        virtual void visit(PointerToMemberType *type)
+        {
+            const Name *memberName = rewrite->rewriteName(type->memberName());
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->pointerToMemberType(memberName, elementType));
+        }
+
+        virtual void visit(PointerType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->pointerType(elementType));
+        }
+
+        virtual void visit(ReferenceType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->referenceType(elementType));
+        }
+
+        virtual void visit(ArrayType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->arrayType(elementType, type->size()));
+        }
+
+        virtual void visit(NamedType *type)
+        {
+            FullySpecifiedType ty = rewrite->env.apply(type->name(), rewrite);
+            if (! ty->isUndefinedType())
+                temps.append(rewrite->rewriteType(ty));
+            else {
+                const Name *name = rewrite->rewriteName(type->name());
+                temps.append(control()->namedType(name));
+            }
+        }
+
+        virtual void visit(Function *type)
+        {
+            Function *funTy = control()->newFunction(0, 0);
+            funTy->copy(type);
+
+            funTy->setName(rewrite->rewriteName(type->name()));
+
+            funTy->setReturnType(rewrite->rewriteType(type->returnType()));
+
+            for (unsigned i = 0; i < type->argumentCount(); ++i) {
+                Symbol *arg = type->argumentAt(i);
+
+                Argument *newArg = control()->newArgument(0, 0);
+                newArg->copy(arg);
+                newArg->setName(rewrite->rewriteName(arg->name()));
+                newArg->setType(rewrite->rewriteType(arg->type()));
+
+                funTy->arguments()->enterSymbol(newArg);
+            }
+
+            temps.append(funTy);
+        }
+
+        virtual void visit(Namespace *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(Class *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(Enum *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ForwardClassDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCClass *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCProtocol *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCMethod *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCForwardClassDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCForwardProtocolDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+    };
+
+    class RewriteName: public NameVisitor
+    {
+        Rewrite *rewrite;
+        QList<const Name *> temps;
+
+        Control *control() const
+        { return rewrite->control; }
+
+        const Identifier *identifier(const Identifier *other) const
+        {
+            if (! other)
+                return 0;
+
+            return control()->findOrInsertIdentifier(other->chars(), other->size());
+        }
+
+    public:
+        RewriteName(Rewrite *r): rewrite(r) {}
+
+        const Name *operator()(const Name *name)
+        {
+            if (! name)
+                return 0;
+
+            accept(name);
+            return temps.takeLast();
+        }
+
+        virtual void visit(const QualifiedNameId *name)
+        {
+            const Name *base = rewrite->rewriteName(name->base());
+            const Name *n = rewrite->rewriteName(name->name());
+            temps.append(control()->qualifiedNameId(base, n));
+        }
+
+        virtual void visit(const NameId *name)
+        {
+            temps.append(control()->nameId(identifier(name->identifier())));
+        }
+
+        virtual void visit(const TemplateNameId *name)
+        {
+            QVarLengthArray<FullySpecifiedType, 8> args(name->templateArgumentCount());
+            for (unsigned i = 0; i < name->templateArgumentCount(); ++i)
+                args[i] = rewrite->rewriteType(name->templateArgumentAt(i));
+            temps.append(control()->templateNameId(identifier(name->identifier()), args.data(), args.size()));
+        }
+
+        virtual void visit(const DestructorNameId *name)
+        {
+            temps.append(control()->destructorNameId(identifier(name->identifier())));
+        }
+
+        virtual void visit(const OperatorNameId *name)
+        {
+            temps.append(control()->operatorNameId(name->kind()));
+        }
+
+        virtual void visit(const ConversionNameId *name)
+        {
+            FullySpecifiedType ty = rewrite->rewriteType(name->type());
+            temps.append(control()->conversionNameId(ty));
+        }
+
+        virtual void visit(const SelectorNameId *name)
+        {
+            QVarLengthArray<const Name *, 8> names(name->nameCount());
+            for (unsigned i = 0; i < name->nameCount(); ++i)
+                names[i] = rewrite->rewriteName(name->nameAt(i));
+            temps.append(control()->selectorNameId(names.constData(), names.size(), name->hasArguments()));
+        }
+    };
+
+public: // attributes
+    Control *control;
+    SubstitutionEnvironment env;
+    RewriteType rewriteType;
+    RewriteName rewriteName;
+};
+
+ContextSubstitution::ContextSubstitution(const LookupContext &context, Scope *scope)
+    : _context(context), _scope(scope)
+{
+}
+
+ContextSubstitution::~ContextSubstitution()
+{
+}
+
+FullySpecifiedType ContextSubstitution::apply(const Name *name, Rewrite *rewrite) const
+{
+    const QList<LookupItem> candidates = _context.lookup(name, _scope);
+
+    foreach (const LookupItem &r, candidates) {
+        Symbol *s = r.declaration();
+        if (s->isDeclaration() && s->isTypedef()) {
+            qDebug() << "resolved typedef:" << s->fileName() << s->line() << s->column();
+
+            qDebug() << "scope is:" << r.scope()->owner()->fileName()
+                     << r.scope()->owner()->line()
+                     << r.scope()->owner()->column();
+
+            ContextSubstitution subst(_context, s->scope());
+            rewrite->env.enter(&subst);
+            FullySpecifiedType ty = rewrite->rewriteType(s->type());
+            rewrite->env.leave();
+
+            return ty;
+        }
+    }
+    return FullySpecifiedType();
+}
+
+
+SubstitutionMap::SubstitutionMap()
+{
+
+}
+
+SubstitutionMap::~SubstitutionMap()
+{
+
+}
+
+void SubstitutionMap::bind(const Name *name, const FullySpecifiedType &ty)
+{
+    _map.append(qMakePair(name, ty));
+}
+
+FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
+{
+    for (int n = _map.size() - 1; n != -1; --n) {
+        const QPair<const Name *, FullySpecifiedType> &p = _map.at(n);
+
+        if (name->isEqualTo(p.first))
+            return p.second;
+    }
+
+    return FullySpecifiedType();
+}
+
+FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type,
+                                          const SubstitutionEnvironment &env,
+                                          Control *control)
+{
+    Rewrite rewrite(control, env);
+    return rewrite.rewriteType(type);
+}
+
+const Name *CPlusPlus::rewriteName(const Name *name,
+                                   const SubstitutionEnvironment &env,
+                                   Control *control)
+{
+    Rewrite rewrite(control, env);
+    return rewrite.rewriteName(name);
+}
diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e6d14b3f5a03d7811796837b2fdfd9ab0ca696c
--- /dev/null
+++ b/src/libs/cplusplus/CppRewriter.h
@@ -0,0 +1,119 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPLUSPLUS_REWRITER_H
+#define CPLUSPLUS_REWRITER_H
+
+#include "CppDocument.h"
+#include "LookupContext.h"
+
+namespace CPlusPlus {
+
+class Rewrite;
+
+class CPLUSPLUS_EXPORT Substitution
+{
+    Q_DISABLE_COPY(Substitution)
+
+public:
+    Substitution() {}
+    virtual ~Substitution() {}
+
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const = 0;
+};
+
+class CPLUSPLUS_EXPORT SubstitutionEnvironment
+{
+    QList<Substitution *> substs;
+
+public:
+    FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const
+    {
+        if (name) {
+            for (int index = substs.size() - 1; index != -1; --index) {
+                const Substitution *subst = substs.at(index);
+
+                FullySpecifiedType ty = subst->apply(name, rewrite);
+                if (! ty->isUndefinedType())
+                    return ty;
+            }
+        }
+
+        return FullySpecifiedType();
+    }
+
+    void enter(Substitution *subst)
+    {
+        substs.append(subst);
+    }
+
+    void leave()
+    {
+        substs.removeLast();
+    }
+};
+
+class CPLUSPLUS_EXPORT ContextSubstitution: public Substitution
+{
+public:
+    ContextSubstitution(const LookupContext &context, Scope *scope);
+    virtual ~ContextSubstitution();
+
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
+
+private:
+    LookupContext _context;
+    Scope *_scope;
+};
+
+
+class CPLUSPLUS_EXPORT SubstitutionMap: public Substitution
+{
+public:
+    SubstitutionMap();
+    virtual ~SubstitutionMap();
+
+    void bind(const Name *name, const FullySpecifiedType &ty);
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
+
+private:
+    QList<QPair<const Name *, FullySpecifiedType> > _map;
+};
+
+CPLUSPLUS_EXPORT FullySpecifiedType rewriteType(const FullySpecifiedType &type,
+                                                const SubstitutionEnvironment &env,
+                                                Control *control);
+
+CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name,
+                                         const SubstitutionEnvironment &env,
+                                         Control *control);
+
+} // end of namespace CPlusPlus
+
+#endif
diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.h b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
index f40c951ba50e73e32c83bed06f70877e47d6b8ae..755fc341b59029f245df73eb1c8017358fba1e55 100644
--- a/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
+++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
@@ -46,7 +46,7 @@ public:
     typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
 
 public:
-    static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
+    Q_DECL_DEPRECATED static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
 
 private:
     DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index f8119fe456f68aaedde8881d81e3674a8c9c2f5c..e703f5fddb2b4badba7a229449f93ae0b827d7dc 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -124,7 +124,7 @@ Scope *FindUsages::scopeAt(unsigned tokenIndex) const
     return _doc->scopeAt(line, column);
 }
 
-void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates)
+void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates)
 {
     if (_processed.contains(tokenIndex))
         return;
@@ -160,11 +160,12 @@ void FindUsages::reportResult(unsigned tokenIndex)
     _references.append(tokenIndex);
 }
 
-bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const
+bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
 {
     if (ClassOrNamespace *c = _context.lookupType(_declSymbol)) {
         for (int i = candidates.size() - 1; i != -1; --i) {
-            Symbol *s = candidates.at(i);
+            const LookupItem &r = candidates.at(i);
+            Symbol *s = r.declaration();
             if (_context.lookupType(s) == c)
                 return true;
         }
@@ -186,7 +187,7 @@ bool FindUsages::visit(MemInitializerAST *ast)
 
         SimpleNameAST *simple = ast->name->asSimpleName();
         if (identifier(simple->identifier_token) == _id) {
-            const QList<Symbol *> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
+            const QList<LookupItem> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
             reportResult(simple->identifier_token, candidates);
         }
     }
@@ -223,14 +224,7 @@ void FindUsages::checkExpression(unsigned startToken, unsigned endToken)
     const QList<LookupItem> results = typeofExpression(expression, scope,
                                                        TypeOfExpression::Preprocess);
 
-    QList<Symbol *> candidates;
-
-    foreach (const LookupItem &r, results) {
-        Symbol *lastVisibleSymbol = r.declaration();
-        candidates.append(lastVisibleSymbol);
-    }
-
-    reportResult(endToken, candidates);
+    reportResult(endToken, results);
 }
 
 bool FindUsages::visit(QualifiedNameAST *ast)
@@ -297,7 +291,7 @@ bool FindUsages::visit(EnumeratorAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -310,7 +304,7 @@ bool FindUsages::visit(SimpleNameAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -321,7 +315,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -331,7 +325,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
 bool FindUsages::visit(TemplateIdAST *ast)
 {
     if (_id == identifier(ast->identifier_token)) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -406,7 +400,7 @@ bool FindUsages::visit(ObjCSelectorAST *ast)
     if (ast->name) {
         const Identifier *id = ast->name->identifier();
         if (id == _id) {
-            const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
+            const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
             reportResult(ast->firstToken(), candidates);
         }
     }
@@ -440,7 +434,7 @@ bool FindUsages::visit(TypenameTypeParameterAST *ast)
         const Identifier *id = name->name->identifier();
         if (id == _id) {
             unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
-            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
             reportResult(ast->name->firstToken(), candidates);
         }
     }
@@ -454,7 +448,7 @@ bool FindUsages::visit(TemplateTypeParameterAST *ast)
         const Identifier *id = name->name->identifier();
         if (id == _id) {
             unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
-            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
             reportResult(ast->name->firstToken(), candidates);
         }
     }
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index ff7a3b063bed07f54bf83fbdd810a48c12245aac..f274da04d6676000c74dbc008c7b22dc54eeeaf6 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -74,10 +74,10 @@ protected:
     QString matchingLine(const Token &tk) const;
     Scope *scopeAt(unsigned tokenIndex) const;
 
-    void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates);
+    void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
     void reportResult(unsigned tokenIndex);
 
-    bool checkCandidates(const QList<Symbol *> &candidates) const;
+    bool checkCandidates(const QList<LookupItem> &candidates) const;
     void checkExpression(unsigned startToken, unsigned endToken);
 
     void ensureNameIsValid(NameAST *ast);
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index ce832e2df60c7b5f911c70420489488fdfd1a0b5..5c935eb6a11babaaa9df83444c01264a570187ca 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -39,13 +39,17 @@
 #include <Scope.h>
 #include <Control.h>
 
-#include <QtDebug>
+#include <QtCore/QStack>
+#include <QtCore/QHash>
+#include <QtCore/QVarLengthArray>
+#include <QtCore/QtDebug>
+
+using namespace CPlusPlus;
 
 namespace {
-    const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
-}
+const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
+} // end of anonymous namespace
 
-using namespace CPlusPlus;
 
 static void addNames(const Name *name, QList<const Name *> *names, bool addAllNames = false)
 {
@@ -241,16 +245,16 @@ ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
     return bindings()->lookupType(symbol);
 }
 
-QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
+QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
 {
-    QList<Symbol *> candidates;
+    QList<LookupItem> candidates;
 
     if (! name)
         return candidates;
 
     for (; scope; scope = scope->enclosingScope()) {
         if ((name->isNameId() || name->isTemplateNameId()) && scope->isBlockScope()) {
-            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's a local.
@@ -274,10 +278,10 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
 
         } else if (scope->isFunctionScope()) {
             Function *fun = scope->owner()->asFunction();
-            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             for (TemplateParameters *it = fun->templateParameters(); it && candidates.isEmpty(); it = it->previous())
-                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
+                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's an argument or a template parameter.
@@ -295,7 +299,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
 
         } else if (scope->isObjCMethodScope()) {
             ObjCMethod *method = scope->owner()->asObjCMethod();
-            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's a formal argument.
@@ -304,7 +308,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
             Class *klass = scope->owner()->asClass();
 
             for (TemplateParameters *it = klass->templateParameters(); it && candidates.isEmpty(); it = it->previous())
-                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
+                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's an argument or a template parameter.
@@ -398,19 +402,19 @@ ClassOrNamespace *ClassOrNamespace::globalNamespace() const
     return e;
 }
 
-QList<Symbol *> ClassOrNamespace::find(const Name *name)
+QList<LookupItem> ClassOrNamespace::find(const Name *name)
 {
     return lookup_helper(name, false);
 }
 
-QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
+QList<LookupItem> ClassOrNamespace::lookup(const Name *name)
 {
     return lookup_helper(name, true);
 }
 
-QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
+QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
 {
-    QList<Symbol *> result;
+    QList<LookupItem> result;
 
     if (name) {
         if (const QualifiedNameId *q = name->asQualifiedNameId()) {
@@ -435,9 +439,9 @@ QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInE
 }
 
 void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
-                                     QList<Symbol *> *result,
-                                     QSet<ClassOrNamespace *> *processed,
-                                     const TemplateNameId *templateId)
+                                          QList<LookupItem> *result,
+                                          QSet<ClassOrNamespace *> *processed,
+                                          const TemplateNameId *templateId)
 {
     if (binding && ! processed->contains(binding)) {
         processed->insert(binding);
@@ -448,16 +452,20 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
             if (ScopedSymbol *scoped = s->asScopedSymbol()) {
                 if (Class *klass = scoped->asClass()) {
                     if (const Identifier *id = klass->identifier()) {
-                        if (nameId && nameId->isEqualTo(id))
-                            result->append(klass);
+                        if (nameId && nameId->isEqualTo(id)) {
+                            LookupItem item;
+                            item.setDeclaration(klass);
+                            item.setBinding(binding);
+                            result->append(item);
+                        }
                     }
                 }
-                _factory->lookupInScope(name, scoped->members(), result, templateId);
+                _factory->lookupInScope(name, scoped->members(), result, templateId, binding);
             }
         }
 
         foreach (Enum *e, binding->enums())
-            _factory->lookupInScope(name, e->members(), result, templateId);
+            _factory->lookupInScope(name, e->members(), result, templateId, binding);
 
         foreach (ClassOrNamespace *u, binding->usings())
             lookup_helper(name, u, result, processed, binding->_templateId);
@@ -465,8 +473,9 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
 }
 
 void CreateBindings::lookupInScope(const Name *name, Scope *scope,
-                                   QList<Symbol *> *result,
-                                   const TemplateNameId *templateId)
+                                   QList<LookupItem> *result,
+                                   const TemplateNameId *templateId,
+                                   ClassOrNamespace *binding)
 {
     Q_UNUSED(templateId);
 
@@ -480,7 +489,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
             else if (! s->name()->isEqualTo(op))
                 continue;
 
-            result->append(s);
+            LookupItem item;
+            item.setDeclaration(s);
+            item.setBinding(binding);
+            result->append(item);
         }
 
     } else if (const Identifier *id = name->identifier()) {
@@ -490,34 +502,17 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
             else if (s->name()->isQualifiedNameId())
                 continue; // skip qualified ids.
 
-            if (templateId && (s->isDeclaration() || s->isFunction())) {
+            LookupItem item;
+            item.setDeclaration(s);
+            item.setBinding(binding);
 
+            if (templateId && (s->isDeclaration() || s->isFunction())) {
                 FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, _control);
-
-                if (debug) {
-                    Overview oo;
-                    oo.setShowFunctionSignatures(true);
-                    oo.setShowReturnTypes(true);
-                    qDebug() << "instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId) << oo(ty);
-                }
-
-                if (Declaration *decl = s->asDeclaration()) {
-                    Declaration *d = _control->newDeclaration(0, 0);
-                    d->copy(decl);
-                    d->setType(ty);
-                    result->append(d);
-                    continue;
-                } else if (Function *fun = s->asFunction()) {
-                    Function *d = ty->asFunctionType();
-                    d->copy(fun);
-                    result->append(d);
-                    continue;
-                }
+                item.setType(ty); // override the type.
             }
 
-            result->append(s);
+            result->append(item);
         }
-
     }
 }
 
@@ -987,3 +982,4 @@ bool CreateBindings::visit(ObjCMethod *)
 {
     return false;
 }
+
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 3854b4cb7b7b5924d6f1556de3ffcc80972f6a96..db6163f8d06af7aed5553011fa444f5e739e45bb 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -36,6 +36,7 @@
 #include <Type.h>
 #include <SymbolVisitor.h>
 #include <Control.h>
+#include <Name.h>
 #include <QtCore/QSet>
 #include <map>
 #include <functional>
@@ -57,8 +58,8 @@ public:
 
     ClassOrNamespace *globalNamespace() const;
 
-    QList<Symbol *> lookup(const Name *name);
-    QList<Symbol *> find(const Name *name);
+    QList<LookupItem> lookup(const Name *name);
+    QList<LookupItem> find(const Name *name);
 
     ClassOrNamespace *lookupType(const Name *name);
     ClassOrNamespace *findType(const Name *name);
@@ -76,12 +77,12 @@ private:
     void addUsing(ClassOrNamespace *u);
     void addNestedType(const Name *alias, ClassOrNamespace *e);
 
-    QList<Symbol *> lookup_helper(const Name *name, bool searchInEnclosingScope);
+    QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
 
     void lookup_helper(const Name *name, ClassOrNamespace *binding,
-                       QList<Symbol *> *result,
-                       QSet<ClassOrNamespace *> *processed,
-                       const TemplateNameId *templateId);
+                            QList<LookupItem> *result,
+                            QSet<ClassOrNamespace *> *processed,
+                            const TemplateNameId *templateId);
 
     ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
                                         bool searchInEnclosingScope);
@@ -134,8 +135,8 @@ public:
     /// Searches in \a scope for symbols with the given \a name.
     /// Store the result in \a results.
     /// \internal
-    void lookupInScope(const Name *name, Scope *scope, QList<Symbol *> *result,
-                       const TemplateNameId *templateId);
+    void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result,
+                            const TemplateNameId *templateId, ClassOrNamespace *binding);
 
     /// Create bindings for the symbols reachable from \a rootSymbol.
     /// \internal
@@ -214,7 +215,7 @@ public:
 
     ClassOrNamespace *globalNamespace() const;
 
-    QList<Symbol *> lookup(const Name *name, Scope *scope) const;
+    QList<LookupItem> lookup(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(Symbol *symbol) const;
     ClassOrNamespace *lookupParent(Symbol *symbol) const;
diff --git a/src/libs/cplusplus/LookupItem.cpp b/src/libs/cplusplus/LookupItem.cpp
index 2502c02790b6f5617136d0314b2be6676d08fb21..1bc49303a3114705e6ae52fa8f186a16caa39e73 100644
--- a/src/libs/cplusplus/LookupItem.cpp
+++ b/src/libs/cplusplus/LookupItem.cpp
@@ -44,11 +44,16 @@ uint CPlusPlus::qHash(const CPlusPlus::LookupItem &key)
 }
 
 LookupItem::LookupItem()
-    : _scope(0), _declaration(0)
+    : _scope(0), _declaration(0), _binding(0)
 { }
 
 FullySpecifiedType LookupItem::type() const
-{ return _type; }
+{
+    if (! _type && _declaration)
+        return _declaration->type();
+
+    return _type;
+}
 
 void LookupItem::setType(const FullySpecifiedType &type)
 { _type = type; }
@@ -70,9 +75,16 @@ Scope *LookupItem::scope() const
 void LookupItem::setScope(Scope *scope)
 { _scope = scope; }
 
+ClassOrNamespace *LookupItem::binding() const
+{ return _binding; }
+
+void LookupItem::setBinding(ClassOrNamespace *binding)
+{ _binding = binding; }
+
 bool LookupItem::operator == (const LookupItem &other) const
 {
-    if (_type == other._type && _declaration == other._declaration && _scope == other._scope)
+    if (_type == other._type && _declaration == other._declaration && _scope == other._scope
+            && _binding == other._binding)
         return true;
 
     return false;
diff --git a/src/libs/cplusplus/LookupItem.h b/src/libs/cplusplus/LookupItem.h
index 14ba99c5734ff1cdeaac98e79f3f15edc4a5bed4..489fe31a09709bc10248afb2e497a1a75a0b1d43 100644
--- a/src/libs/cplusplus/LookupItem.h
+++ b/src/libs/cplusplus/LookupItem.h
@@ -35,6 +35,8 @@
 
 namespace CPlusPlus {
 
+class ClassOrNamespace;
+
 class CPLUSPLUS_EXPORT LookupItem
 {
 public:
@@ -59,6 +61,9 @@ public:
     /// Sets this item's scope.
     void setScope(Scope *scope);
 
+    ClassOrNamespace *binding() const;
+    void setBinding(ClassOrNamespace *binding);
+
     bool operator == (const LookupItem &other) const;
     bool operator != (const LookupItem &other) const;
 
@@ -66,6 +71,7 @@ private:
     FullySpecifiedType _type;
     Scope *_scope;
     Symbol *_declaration;
+    ClassOrNamespace *_binding;
 };
 
 uint qHash(const CPlusPlus::LookupItem &result);
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index b02b7ecf5d1dda510e5a499f587b56decbd329ce..3f2ae7ac82e12157d8e62e53544e2f481f1207ae 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -31,6 +31,7 @@
 #include "LookupContext.h"
 #include "Overview.h"
 #include "DeprecatedGenTemplateInstance.h"
+#include "CppRewriter.h"
 
 #include <Control.h>
 #include <AST.h>
@@ -121,6 +122,11 @@ void ResolveExpression::addResults(const QList<Symbol *> &symbols)
     }
 }
 
+void ResolveExpression::addResults(const QList<LookupItem> &items)
+{
+    _results += items;
+}
+
 void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope)
 {
     LookupItem item;
@@ -395,7 +401,7 @@ bool ResolveExpression::visit(CompoundLiteralAST *ast)
 bool ResolveExpression::visit(QualifiedNameAST *ast)
 {
     if (const Name *name = ast->name) {
-        const QList<Symbol *> candidates = _context.lookup(name, _scope);
+        const QList<LookupItem> candidates = _context.lookup(name, _scope);
         addResults(candidates);
     }
 
@@ -404,14 +410,14 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
 
 bool ResolveExpression::visit(SimpleNameAST *ast)
 {
-    const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
+    const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
     addResults(candidates);
     return false;
 }
 
 bool ResolveExpression::visit(TemplateIdAST *ast)
 {
-    const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
+    const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
     addResults(candidates);
     return false;
 }
@@ -477,7 +483,8 @@ bool ResolveExpression::visit(CallAST *ast)
 
         if (NamedType *namedTy = ty->asNamedType()) {
             if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
-                foreach (Symbol *overload, b->find(functionCallOp)) {
+                foreach (const LookupItem &r, b->find(functionCallOp)) {
+                    Symbol *overload = r.declaration();
                     if (Function *funTy = overload->type()->asFunctionType()) {
                         if (maybeValidPrototype(funTy, actualArgumentCount)) {
                             if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
@@ -520,7 +527,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
 
         } else if (NamedType *namedTy = ty->asNamedType()) {
             if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
-                foreach (Symbol *overload, b->find(arrayAccessOp)) {
+                foreach (const LookupItem &r, b->find(arrayAccessOp)) {
+                    Symbol *overload = r.declaration();
                     if (Function *funTy = overload->type()->asFunctionType()) {
                         if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
                             // ### TODO: check the actual arguments
@@ -534,6 +542,56 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
     return false;
 }
 
+QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
+{
+    QList<LookupItem> members;
+
+    const QList<LookupItem> originalMembers = binding->find(memberName);
+
+    foreach (const LookupItem &m, originalMembers) {
+        if (! m.binding() || ! m.binding()->templateId()) {
+            members.append(m);
+            continue;
+        }
+
+        Symbol *decl = m.declaration();
+
+        if (Class *klass = decl->enclosingSymbol()->asClass()) {
+            if (klass->templateParameters() != 0) {
+                SubstitutionMap map;
+
+                const TemplateNameId *templateId = m.binding()->templateId();
+                unsigned count = qMin(klass->templateParameterCount(), templateId->templateArgumentCount());
+
+                for (unsigned i = 0; i < count; ++i) {
+                    map.bind(klass->templateParameterAt(i)->name(), templateId->templateArgumentAt(i));
+                }
+
+                SubstitutionEnvironment env;
+                ContextSubstitution ctxSubst(_context, m.scope());
+
+                env.enter(&ctxSubst);
+                env.enter(&map);
+                FullySpecifiedType instantiatedTy = rewriteType(decl->type(), env, _context.control().data());
+
+                Overview oo;
+                oo.setShowReturnTypes(true);
+                oo.setShowFunctionSignatures(true);
+
+                qDebug() << "original:" << oo(decl->type(), decl->name()) << "inst:" << oo(instantiatedTy, decl->name());
+
+                LookupItem newItem;
+                newItem = m;
+                newItem.setType(instantiatedTy);
+                members.append(newItem);
+            }
+        }
+    }
+
+
+    return members;
+}
+
 bool ResolveExpression::visit(MemberAccessAST *ast)
 {
     // The candidate types for the base expression are stored in
@@ -586,9 +644,13 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
 
             } else if (ClassOrNamespace *binding = findClass(ty, scope)) {
                 // lookup for overloads of operator->
+
                 const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
+                foreach (const LookupItem &r, binding->find(arrowOp)) {
+                    Symbol *overload = r.declaration();
+                    if (! overload)
+                        continue;
 
-                foreach (Symbol *overload, binding->find(arrowOp)) {
                     if (overload->type()->isFunctionType()) {
                         FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
                         Function *instantiatedFunction = overloadTy->asFunctionType();
@@ -604,14 +666,10 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
                                 if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
                                     return retBinding;
                             }
-
-                            if (debug) {
-                                Overview oo;
-                                qDebug() << "no class for:" << oo(ptrTy->elementType());
-                            }
                         }
                     }
                 }
+
             }
         } else if (accessOp == T_DOT) {
             if (replacedDotOperator) {
@@ -663,9 +721,11 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
         }
 
         if (binding) {
-            foreach (Symbol *s, binding->lookup(ast->selector->name))
+            foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
+                Symbol *s = r.declaration();
                 if (ObjCMethod *m = s->asObjCMethod())
                     addResult(m->returnType(), result.scope());
+            }
         }
     }
 
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 8496631af4c2247cd95be0760560a4134f145ff8..19692a37def993f21b8d905a7d22b71305af901a 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -59,10 +59,13 @@ protected:
     QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
     FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
 
+    Q_DECL_DEPRECATED QList<LookupItem> getMembers(ClassOrNamespace *binding, const Name *memberName) const;
+
     void thisObject();
 
     void addResult(const FullySpecifiedType &ty, Scope *scope);
     void addResults(const QList<Symbol *> &symbols);
+    void addResults(const QList<LookupItem> &items);
 
     bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
 
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 24bb51cf5e2c9216b00754d32d2b5cf2d9a506a5..2a718d5712b359407a1a85ed9856d4b28bef2836 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -27,6 +27,7 @@ SOURCES += \
 HEADERS += \
     $$PWD/SimpleLexer.h \
     $$PWD/CppDocument.h \
+    $$PWD/CppRewriter.h \
     $$PWD/Overview.h \
     $$PWD/NamePrettyPrinter.h \
     $$PWD/TypeOfExpression.h \
@@ -52,6 +53,7 @@ HEADERS += \
 SOURCES += \
     $$PWD/SimpleLexer.cpp \
     $$PWD/CppDocument.cpp \
+    $$PWD/CppRewriter.cpp \
     $$PWD/Overview.cpp \
     $$PWD/NamePrettyPrinter.cpp \
     $$PWD/TypeOfExpression.cpp \
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index b38ba8e879284c3f8990ea19952a0e45cbc79bac..90261bb979b1ee8dd43b8ec2efa5acf0ebf0adf3 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -408,11 +408,11 @@ void CheckSymbols::checkName(NameAST *ast)
             const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
             if (_potentialTypes.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addTypeUsage(candidates, ast);
             } else if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             }
         }
@@ -426,11 +426,11 @@ void CheckSymbols::checkMemberName(NameAST *ast)
             const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
             if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             } else if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             }
         }
@@ -500,7 +500,7 @@ bool CheckSymbols::visit(TypenameTypeParameterAST *ast)
             const QByteArray id = QByteArray::fromRawData(templId->chars(), templId->size());
             if (_potentialTypes.contains(id)) {
                 Scope *scope = findScope(_templateDeclarationStack.back());
-                const QList<Symbol *> candidates = _context.lookup(ast->name->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name->name, scope);
                 addTypeUsage(candidates, ast->name);
             }
         }
@@ -582,7 +582,7 @@ void CheckSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
     //qDebug() << "added use" << oo(ast->name) << line << column << length;
 }
 
-void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
+void CheckSymbols::addTypeUsage(const QList<LookupItem> &candidates, NameAST *ast)
 {
     unsigned startToken = ast->firstToken();
     if (DestructorNameAST *dtor = ast->asDestructorName())
@@ -596,7 +596,8 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
     getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
 
-    foreach (Symbol *c, candidates) {
+    foreach (const LookupItem &r, candidates) {
+        Symbol *c = r.declaration();
         if (c->isUsingDeclaration()) // skip using declarations...
             continue;
         else if (c->isUsingNamespaceDirective()) // ... and using namespace directives.
@@ -612,7 +613,7 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
     }
 }
 
-void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast)
+void CheckSymbols::addMemberUsage(const QList<LookupItem> &candidates, NameAST *ast)
 {
     unsigned startToken = ast->firstToken();
     if (DestructorNameAST *dtor = ast->asDestructorName())
@@ -626,8 +627,11 @@ void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *as
     getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
 
-    foreach (Symbol *c, candidates) {
-        if (! c->isDeclaration())
+    foreach (const LookupItem &r, candidates) {
+        Symbol *c = r.declaration();
+        if (! c)
+            continue;
+        else if (! c->isDeclaration())
             continue;
         else if (c->isTypedef())
             continue;
diff --git a/src/plugins/cppeditor/cppchecksymbols.h b/src/plugins/cppeditor/cppchecksymbols.h
index bb996fb691d9cc2ee0f7e5347e3a215e865cac7a..8db7fda967d643b8bfbc4bdaef8bcde00979fce5 100644
--- a/src/plugins/cppeditor/cppchecksymbols.h
+++ b/src/plugins/cppeditor/cppchecksymbols.h
@@ -84,11 +84,11 @@ protected:
     void checkName(NameAST *ast);
     void checkNamespace(NameAST *name);
     void addTypeUsage(ClassOrNamespace *b, NameAST *ast);
-    void addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast);
+    void addTypeUsage(const QList<LookupItem> &candidates, NameAST *ast);
     void addTypeUsage(const Use &use);
 
     void checkMemberName(NameAST *ast);
-    void addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast);
+    void addMemberUsage(const QList<LookupItem> &candidates, NameAST *ast);
 
     virtual bool preVisit(AST *);
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 663bc73f6226fa8eabf6edd122bb5b6c10368b52..9dae26316d091fe29db29dfbd27a628d0f64cfdc 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -995,8 +995,9 @@ void CPPEditor::switchDeclarationDefinition()
             LookupContext context(thisDocument, snapshot);
 
             Function *functionDefinition = functionScope->owner()->asFunction();
-            const QList<Symbol *> declarations = context.lookup(functionDefinition->name(), functionDefinition->scope());
-            foreach (Symbol *decl, declarations) {
+            const QList<LookupItem> declarations = context.lookup(functionDefinition->name(), functionDefinition->scope());
+            foreach (const LookupItem &r, declarations) {
+                Symbol *decl = r.declaration();
                 // TODO: check decl.
                 openCppEditorAt(linkToSymbol(decl));
                 break;
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index b717d632541392c1cc55635d29e5702b6f5d7979..15c827bc89b4e5abc19fbff55870b03237498a50 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -920,7 +920,8 @@ public:
                 ClassOrNamespace *b = context.lookupType(function);
                 if (b) {
                     // Do we have a tr method?
-                    foreach(Symbol *s, b->find(trName)) {
+                    foreach(const LookupItem &r, b->find(trName)) {
+                        Symbol *s = r.declaration();
                         if (s->type()->isFunctionType()) {
                             m_option = useTr;
                             // no context required for tr
@@ -1302,9 +1303,10 @@ protected:
             if (Enum *e = result.declaration()->type()->asEnumType())
                 return e;
             if (NamedType *namedType = fst->asNamedType()) {
-                QList<Symbol *> candidates =
+                QList<LookupItem> candidates =
                         typeOfExpression.context().lookup(namedType->name(), scope);
-                foreach (Symbol *candidate, candidates) {
+                foreach (const LookupItem &r, candidates) {
+                    Symbol *candidate = r.declaration();
                     if (Enum *e = candidate->asEnum()) {
                         return e;
                     }
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 7b4303731e6e8fa6122acc4d28e2774d2915f0ca..44f8b861fac7507500271249d9d0346de503a545 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -1175,11 +1175,13 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &r
 
             if (NamedType *namedTy = ty->asNamedType()) {
                 if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
-                    foreach (Symbol *overload, b->lookup(functionCallOp)) {
+                    foreach (const LookupItem &r, b->lookup(functionCallOp)) {
+                        Symbol *overload = r.declaration();
                         FullySpecifiedType overloadTy = overload->type().simplified();
 
-                        if (Function *funTy = overloadTy->asFunctionType())
+                        if (Function *funTy = overloadTy->asFunctionType()) {
                             functions.append(funTy);
+                        }
                     }
                 }
             }
diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp
index da6c16a54a2de19c504bde4590c609c3424ead4a..764c56a1ccbfc6735eba8dce0ec96fe1c3c42cfb 100644
--- a/src/shared/cplusplus/FullySpecifiedType.cpp
+++ b/src/shared/cplusplus/FullySpecifiedType.cpp
@@ -235,6 +235,12 @@ FullySpecifiedType FullySpecifiedType::simplified() const
     return *this;
 }
 
+unsigned FullySpecifiedType::flags() const
+{ return _flags; }
+
+void FullySpecifiedType::setFlags(unsigned flags)
+{ _flags = flags; }
+
 void FullySpecifiedType::copySpecifiers(const FullySpecifiedType &type)
 {
     // class storage specifiers
diff --git a/src/shared/cplusplus/FullySpecifiedType.h b/src/shared/cplusplus/FullySpecifiedType.h
index 7905df162de6c95e3977ef0392ff8ca582a66e13..2d0824556a0d49d0a59771da63e14d1c3c5b30b4 100644
--- a/src/shared/cplusplus/FullySpecifiedType.h
+++ b/src/shared/cplusplus/FullySpecifiedType.h
@@ -134,6 +134,9 @@ public:
 
     void copySpecifiers(const FullySpecifiedType &type);
 
+    unsigned flags() const;
+    void setFlags(unsigned flags);
+
 private:
     Type *_type;
     struct Flags {
diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp
index fdf432704e39990f1806214682eb9bb2dac0acb6..6aae4b0b7926d8cf8aeace186a8ab7e85a144638 100644
--- a/tests/auto/cplusplus/lookup/tst_lookup.cpp
+++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp
@@ -64,6 +64,13 @@ private Q_SLOTS:
     void class_with_baseclass();
     void class_with_protocol_with_protocol();
     void iface_impl_scoping();
+
+    // template instantiation:
+    void templates_1();
+    void templates_2();
+    void templates_3();
+    void templates_4();
+    void templates_5();
 };
 
 void tst_Lookup::base_class_defined_1()
@@ -169,14 +176,14 @@ void tst_Lookup::simple_class_1()
     QVERIFY(klass->symbols().contains(impl));
 
     // check method resolving:
-    QList<Symbol *> results = context.lookup(allocMethodImpl->name(), impl->members());
+    QList<LookupItem> results = context.lookup(allocMethodImpl->name(), impl->members());
     QCOMPARE(results.size(), 2);
-    QCOMPARE(results.at(0), allocMethodIface);
-    QCOMPARE(results.at(1), allocMethodImpl);
+    QCOMPARE(results.at(0).declaration(), allocMethodIface);
+    QCOMPARE(results.at(1).declaration(), allocMethodImpl);
 
     results = context.lookup(deallocMethod->name(), impl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), deallocMethod);
+    QCOMPARE(results.at(0).declaration(), deallocMethod);
 }
 
 void tst_Lookup::class_with_baseclass()
@@ -230,13 +237,13 @@ void tst_Lookup::class_with_baseclass()
     QVERIFY(objClass != 0);
     QVERIFY(objClass->symbols().contains(baseZoo));
 
-    QList<Symbol *> results = context.lookup(baseDecl->name(), zooImpl->members());
+    QList<LookupItem> results = context.lookup(baseDecl->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), baseDecl);
+    QCOMPARE(results.at(0).declaration(), baseDecl);
 
     results = context.lookup(baseMethod->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), baseMethod);
+    QCOMPARE(results.at(0).declaration(), baseMethod);
 }
 
 void tst_Lookup::class_with_protocol_with_protocol()
@@ -279,20 +286,20 @@ void tst_Lookup::class_with_protocol_with_protocol()
     const LookupContext context(doc, snapshot);
 
     {
-        const QList<Symbol *> candidates = context.lookup(P1->name(), zooImpl->scope());
+        const QList<LookupItem> candidates = context.lookup(P1->name(), zooImpl->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.contains(P1));
+        QVERIFY(candidates.at(0).declaration() == P1);
     }
 
     {
-        const QList<Symbol *> candidates = context.lookup(P2->protocolAt(0)->name(), zooImpl->scope());
+        const QList<LookupItem> candidates = context.lookup(P2->protocolAt(0)->name(), zooImpl->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.contains(P1));
+        QVERIFY(candidates.first().declaration() == P1);
     }
 
-    QList<Symbol *> results = context.lookup(p1method->name(), zooImpl->members());
+    QList<LookupItem> results = context.lookup(p1method->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), p1method);
+    QCOMPARE(results.at(0).declaration(), p1method);
 }
 
 void tst_Lookup::iface_impl_scoping()
@@ -341,9 +348,9 @@ void tst_Lookup::iface_impl_scoping()
         QVERIFY(arg->name()->identifier());
         QCOMPARE(arg->name()->identifier()->chars(), "arg");
 
-        const QList<Symbol *> candidates = context.lookup(arg->name(), method1Body->scope());
+        const QList<LookupItem> candidates = context.lookup(arg->name(), method1Body->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.at(0)->type()->asIntegerType());
+        QVERIFY(candidates.at(0).declaration()->type()->asIntegerType());
     }
 
     Declaration *method2 = iface->memberAt(1)->asDeclaration();
@@ -351,11 +358,174 @@ void tst_Lookup::iface_impl_scoping()
     QCOMPARE(method2->identifier()->chars(), "method2");
 
     { // verify if we can resolve "method2" in the body
-        const QList<Symbol *> candidates = context.lookup(method2->name(), method1Body->scope());
+        const QList<LookupItem> candidates = context.lookup(method2->name(), method1Body->scope());
         QCOMPARE(candidates.size(), 1);
-        QCOMPARE(candidates.at(0), method2);
+        QCOMPARE(candidates.at(0).declaration(), method2);
     }
 }
 
+void tst_Lookup::templates_1()
+{
+    const QByteArray source = "\n"
+            "namespace std {\n"
+            "    template <typename T>\n"
+            "    struct _List_iterator {\n"
+            "        T data;\n"
+            "    };\n"
+            "\n"
+            "    template <typename T>\n"
+            "    struct list {\n"
+            "        typedef _List_iterator<T> iterator;\n"
+            "\n"
+            "        iterator begin();\n"
+            "        _List_iterator<T> end();\n"
+            "    };\n"
+            "}\n"
+            "\n"
+            "struct Point {\n"
+            "    int x, y;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    std::list<Point> l;\n"
+            "    l.begin();  // std::_List_iterator<Point> .. and not only _List_iterator<Point>\n"
+            "    l.end(); // std::_List_iterator<Point>\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_1");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_2()
+{
+    const QByteArray source = "\n"
+            "template <typename T1>\n"
+            "struct Node {\n"
+            "    T1 value;\n"
+            "    Node *next;\n"
+            "    Node<T1> *other_next;\n"
+            "};\n"
+            "\n"
+            "template <typename T2>\n"
+            "struct List {\n"
+            "    Node<T2> *elements;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    List<int> *e;\n"
+            "    e->elements; // Node<int> *\n"
+            "    e->elements->next; // Node<int> *\n"
+            "    e->elements->other_next; // Node<int> *\n"
+            "}\n"
+;
+    Document::Ptr doc = Document::create("templates_2");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_3()
+{
+    const QByteArray source = "\n"
+            "struct Point {\n"
+            "    int x, y;\n"
+            "};\n"
+            "\n"
+            "template <typename T = Point>\n"
+            "struct List {\n"
+            "    const T &at(int);\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    List<> l;\n"
+            "    l.at(0); // const Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_3");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_4()
+{
+    const QByteArray source = "\n"
+            "template <typename T>\n"
+            "struct Allocator {\n"
+            "    typedef T *pointer_type;\n"
+            "    typedef T &reference_type;\n"
+            "};\n"
+            "\n"
+            "template <typename T>\n"
+            "struct SharedPtr {\n"
+            "    typedef typename Allocator<T>::pointer_type pointer_type;\n"
+            "    typedef typename Allocator<T>::reference_type reference_type;\n"
+            "\n"
+            "    pointer_type operator->();\n"
+            "    reference_type operator*();\n"
+            "\n"
+            "    pointer_type data();\n"
+            "    reference_type get();\n"
+            "\n"
+            "};\n"
+            "\n"
+            "struct Point {\n"
+            "    int x,y;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    SharedPtr<Point> l;\n"
+            "\n"
+            "    l->x; // int\n"
+            "    (*l); // Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_4");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_5()
+{
+    const QByteArray source = "\n"
+            "struct Point {\n"
+            "    int x,y;\n"
+            "};\n"
+            "\n"
+            "template <typename _Tp>\n"
+            "struct Allocator {\n"
+            "    typedef const _Tp &const_reference;\n"
+            "\n"
+            "    const_reference get();\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    Allocator<Point>::const_reference r = pt;\n"
+            "    //r.; // const Point &\n"
+            "\n"
+            "    Allocator<Point> a;\n"
+            "    a.get(); // const Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_5");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
 QTEST_APPLESS_MAIN(tst_Lookup)
 #include "tst_lookup.moc"