diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccb36e9cbb9fe851a318c3dbd0263674d3fc91d3
--- /dev/null
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -0,0 +1,815 @@
+/**************************************************************************
+**
+** 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 "LookupContext.h"
+#include "ResolveExpression.h"
+#include "Overview.h"
+#include "CppBindings.h"
+
+#include <CoreTypes.h>
+#include <Symbols.h>
+#include <Literals.h>
+#include <Names.h>
+#include <Scope.h>
+#include <Control.h>
+
+#include <QtDebug>
+
+#define CPLUSPLUS_NO_LAZY_LOOKUP
+
+using namespace CPlusPlus;
+
+/////////////////////////////////////////////////////////////////////
+// LookupContext
+/////////////////////////////////////////////////////////////////////
+LookupContext::LookupContext()
+    : _control(0)
+{ }
+
+LookupContext::LookupContext(Document::Ptr thisDocument,
+                             const Snapshot &snapshot)
+    : _expressionDocument(Document::create("<LookupContext>")),
+      _thisDocument(thisDocument),
+      _snapshot(snapshot)
+{
+    _control = _expressionDocument->control();
+}
+
+LookupContext::LookupContext(Document::Ptr expressionDocument,
+                             Document::Ptr thisDocument,
+                             const Snapshot &snapshot)
+    : _expressionDocument(expressionDocument),
+      _thisDocument(thisDocument),
+      _snapshot(snapshot)
+{
+    _control = _expressionDocument->control();
+}
+
+LookupContext::LookupContext(const LookupContext &other)
+    : _control(other._control),
+      _expressionDocument(other._expressionDocument),
+      _thisDocument(other._thisDocument),
+      _snapshot(other._snapshot),
+      _bindings(other._bindings)
+{ }
+
+LookupContext &LookupContext::operator = (const LookupContext &other)
+{
+    _control = other._control;
+    _expressionDocument = other._expressionDocument;
+    _thisDocument = other._thisDocument;
+    _snapshot = other._snapshot;
+    _bindings = other._bindings;
+    return *this;
+}
+
+QSharedPointer<CreateBindings> LookupContext::bindings() const
+{
+    if (! _bindings)
+        _bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot));
+
+    return _bindings;
+}
+
+void LookupContext::setBindings(QSharedPointer<CreateBindings> bindings)
+{
+    _bindings = bindings;
+}
+
+bool LookupContext::isValid() const
+{ return _control != 0; }
+
+Control *LookupContext::control() const
+{ return _control; }
+
+Document::Ptr LookupContext::expressionDocument() const
+{ return _expressionDocument; }
+
+Document::Ptr LookupContext::thisDocument() const
+{ return _thisDocument; }
+
+Document::Ptr LookupContext::document(const QString &fileName) const
+{ return _snapshot.document(fileName); }
+
+Snapshot LookupContext::snapshot() const
+{ return _snapshot; }
+
+ClassOrNamespace *LookupContext::globalNamespace() const
+{
+    return bindings()->globalNamespace();
+}
+
+ClassOrNamespace *LookupContext::classOrNamespace(const Name *name, Scope *scope) const
+{
+    if (ClassOrNamespace *b = bindings()->findClassOrNamespace(scope->owner()))
+        return b->lookupClassOrNamespace(name);
+
+    return 0;
+}
+
+ClassOrNamespace *LookupContext::classOrNamespace(Symbol *symbol) const
+{
+    return bindings()->findClassOrNamespace(symbol);
+}
+
+QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
+{
+    QList<Symbol *> candidates;
+
+    if (! name)
+        return candidates;
+
+    const Identifier *id = name->identifier();
+
+    for (; scope; scope = scope->enclosingScope()) {
+        if (id && scope->isBlockScope()) {
+            ClassOrNamespace::lookup_helper(name, scope, &candidates);
+
+            if (! candidates.isEmpty())
+                break; // it's a local.
+
+            for (unsigned index = 0; index < scope->symbolCount(); ++index) {
+                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;
+                    }
+                }
+            }
+
+        } else if (scope->isFunctionScope()) {
+            Function *fun = scope->owner()->asFunction();
+            ClassOrNamespace::lookup_helper(name, fun->arguments(), &candidates);
+            if (! candidates.isEmpty())
+                break; // it's a formal argument.
+
+            if (fun->name() && fun->name()->isQualifiedNameId()) {
+                const QualifiedNameId *q = fun->name()->asQualifiedNameId();
+                QList<QByteArray> path;
+
+                for (unsigned index = 0; index < q->nameCount() - 1; ++index) {
+                    if (const Identifier *id = q->nameAt(index)->identifier())
+                        path.append(QByteArray::fromRawData(id->chars(), id->size()));
+                }
+
+                if (ClassOrNamespace *binding = bindings()->findClassOrNamespace(path))
+                    return binding->lookup(name);
+            }
+
+        } else if (scope->isObjCMethodScope()) {
+            ObjCMethod *method = scope->owner()->asObjCMethod();
+            ClassOrNamespace::lookup_helper(name, method->arguments(), &candidates);
+            if (! candidates.isEmpty())
+                break; // it's a formal argument.
+
+        } else if (scope->isClassScope() || scope->isNamespaceScope()
+                    || scope->isObjCClassScope() || scope->isObjCProtocolScope()) {
+            if (ClassOrNamespace *binding = bindings()->findClassOrNamespace(scope->owner()))
+                return binding->lookup(name);
+
+            break;
+        }
+    }
+
+    return candidates;
+}
+
+ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
+    : _factory(factory), _parent(parent), _flushing(false)
+{
+}
+
+QList<ClassOrNamespace *> ClassOrNamespace::usings() const
+{
+    const_cast<ClassOrNamespace *>(this)->flush();
+    return _usings;
+}
+
+QList<Enum *> ClassOrNamespace::enums() const
+{
+    const_cast<ClassOrNamespace *>(this)->flush();
+    return _enums;
+}
+
+QList<Symbol *> ClassOrNamespace::symbols() const
+{
+    const_cast<ClassOrNamespace *>(this)->flush();
+    return _symbols;
+}
+
+ClassOrNamespace *ClassOrNamespace::globalNamespace() const
+{
+    ClassOrNamespace *e = const_cast<ClassOrNamespace *>(this);
+
+    do {
+        if (! e->_parent)
+            break;
+
+        e = e->_parent;
+    } while (e);
+
+    return e;
+}
+
+QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
+{
+    QList<Symbol *> result;
+    if (! name)
+        return result;
+
+    if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+        ClassOrNamespace *binding = this;
+
+        if (q->isGlobal())
+            binding = globalNamespace();
+
+        binding = binding->lookupClassOrNamespace(q->nameAt(0));
+
+        for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
+            binding = binding->findClassOrNamespace(q->nameAt(index));
+
+        if (binding)
+            result = binding->lookup(q->unqualifiedNameId());
+
+        return result;
+    }
+
+    QSet<ClassOrNamespace *> processed;
+    ClassOrNamespace *binding = this;
+    do {
+        lookup_helper(name, binding, &result, &processed);
+        binding = binding->_parent;
+    } while (binding);
+
+    return result;
+}
+
+void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
+                                     QList<Symbol *> *result,
+                                     QSet<ClassOrNamespace *> *processed)
+{
+    if (! binding)
+        return;
+
+    else if (! processed->contains(binding)) {
+        processed->insert(binding);
+
+        foreach (Symbol *s, binding->symbols()) {
+            if (ScopedSymbol *scoped = s->asScopedSymbol())
+                lookup_helper(name, scoped->members(), result);
+        }
+
+        foreach (Enum *e, binding->enums())
+            lookup_helper(name, e->members(), result);
+
+        foreach (ClassOrNamespace *u, binding->usings())
+            lookup_helper(name, u, result, processed);
+    }
+}
+
+void ClassOrNamespace::lookup_helper(const Name *name, Scope *scope, QList<Symbol *> *result)
+{
+    if (! name) {
+        return;
+
+    } else if (const OperatorNameId *op = name->asOperatorNameId()) {
+        for (Symbol *s = scope->lookat(op->kind()); s; s = s->next()) {
+            if (! s->name())
+                continue;
+            else if (! s->name()->isEqualTo(op))
+                continue;
+            result->append(s);
+        }
+
+    } else if (const Identifier *id = name->identifier()) {
+        for (Symbol *s = scope->lookat(id); s; s = s->next()) {
+            if (! s->name())
+                continue;
+            else if (! id->isEqualTo(s->identifier()))
+                continue;
+            else if (s->name()->isQualifiedNameId()) {
+#if 0
+                Overview oo;
+                oo.setShowReturnTypes(true);
+                oo.setShowFunctionSignatures(true);
+                qDebug() << "SKIP:" << oo(s->type(), s->name()) << s->fileName() << s->line() << s->column();
+#endif
+                continue;
+            }
+            result->append(s);
+        }
+
+    }
+}
+
+ClassOrNamespace *ClassOrNamespace::lookupClassOrNamespace(const Name *name)
+{
+    if (! name)
+        return 0;
+
+    QSet<ClassOrNamespace *> processed;
+    return lookupClassOrNamespace_helper(name, &processed);
+}
+
+ClassOrNamespace *ClassOrNamespace::findClassOrNamespace(const Name *name)
+{
+    QSet<ClassOrNamespace *> processed;
+    return findClassOrNamespace_helper(name, &processed);
+}
+
+ClassOrNamespace *ClassOrNamespace::findClassOrNamespace(const QList<QByteArray> &path)
+{
+    if (path.isEmpty())
+        return globalNamespace();
+
+    ClassOrNamespace *e = this;
+
+    for (int i = 0; e && i < path.size(); ++i) {
+        QSet<ClassOrNamespace *> processed;
+        e = e->findClassOrNamespace_helper(path.at(i), &processed);
+    }
+
+    return e;
+}
+
+ClassOrNamespace *ClassOrNamespace::lookupClassOrNamespace_helper(const Name *name,
+                                                                  QSet<ClassOrNamespace *> *processed)
+{
+    Q_ASSERT(name != 0);
+
+    if (! processed->contains(this)) {
+        processed->insert(this);
+
+        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+            ClassOrNamespace *e = this;
+
+            if (q->isGlobal())
+                e = globalNamespace();
+
+            e = e->lookupClassOrNamespace(q->nameAt(0));
+
+            for (unsigned index = 1; e && index < q->nameCount(); ++index) {
+                QSet<ClassOrNamespace *> processed;
+                e = e->findClassOrNamespace_helper(q->nameAt(index), &processed);
+            }
+
+            return e;
+
+        } else if (const Identifier *id = name->identifier()) {
+            const QByteArray classOrNamespaceName = QByteArray::fromRawData(id->chars(), id->size());
+
+            if (ClassOrNamespace *e = nestedClassOrNamespace(classOrNamespaceName))
+                return e;
+
+            foreach (ClassOrNamespace *u, usings()) {
+                if (ClassOrNamespace *r = u->lookupClassOrNamespace_helper(name, processed))
+                    return r;
+            }
+        }
+
+        if (_parent)
+            return _parent->lookupClassOrNamespace_helper(name, processed);
+    }
+
+    return 0;
+}
+
+ClassOrNamespace *ClassOrNamespace::findClassOrNamespace_helper(const Name *name,
+                                                                QSet<ClassOrNamespace *> *processed)
+{
+    if (! name) {
+        return 0;
+
+    } else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+        ClassOrNamespace *e = this;
+
+        if (q->isGlobal())
+            e = globalNamespace();
+
+        for (unsigned i = 0; e && i < q->nameCount(); ++i) {
+            QSet<ClassOrNamespace *> processed;
+            e = e->findClassOrNamespace_helper(q->nameAt(i), &processed);
+        }
+
+        return e;
+
+    } else if (const Identifier *id = name->identifier()) {
+        const QByteArray classOrNamespaceName = QByteArray::fromRawData(id->chars(), id->size());
+        return findClassOrNamespace_helper(classOrNamespaceName, processed);
+
+    }
+
+    return 0;
+}
+
+ClassOrNamespace *ClassOrNamespace::findClassOrNamespace_helper(const QByteArray &name,
+                                                                QSet<ClassOrNamespace *> *processed)
+{
+    if (ClassOrNamespace *e = nestedClassOrNamespace(name))
+        return e;
+
+    else if (! processed->contains(this)) {
+        processed->insert(this);
+
+        foreach (ClassOrNamespace *u, usings()) {
+            if (ClassOrNamespace *e = u->findClassOrNamespace_helper(name, processed))
+                return e;
+        }
+    }
+
+    return 0;
+}
+
+ClassOrNamespace *ClassOrNamespace::nestedClassOrNamespace(const QByteArray &name) const
+{
+    const_cast<ClassOrNamespace *>(this)->flush();
+    return _classOrNamespaces.value(name);
+}
+
+void ClassOrNamespace::flush()
+{
+#ifndef CPLUSPLUS_NO_LAZY_LOOKUP
+    if (! _flushing) {
+        _flushing = true;
+
+        while (! _todo.isEmpty()) {
+            Symbol *member = _todo.takeFirst();
+            _factory->process(member, this);
+        }
+    }
+#endif
+}
+
+void ClassOrNamespace::addSymbol(Symbol *symbol)
+{
+    _symbols.append(symbol);
+}
+
+void ClassOrNamespace::addTodo(Symbol *symbol)
+{
+    _todo.append(symbol);
+}
+
+void ClassOrNamespace::addEnum(Enum *e)
+{
+    _enums.append(e);
+}
+
+void ClassOrNamespace::addUsing(ClassOrNamespace *u)
+{
+    _usings.append(u);
+}
+
+void ClassOrNamespace::addNestedClassOrNamespace(const QByteArray &alias, ClassOrNamespace *e)
+{
+    _classOrNamespaces.insert(alias, e);
+}
+
+ClassOrNamespace *ClassOrNamespace::findOrCreate(const Name *name)
+{
+    if (! name)
+        return this;
+
+    if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+        ClassOrNamespace *e = this;
+
+        for (unsigned i = 0; e && i < q->nameCount(); ++i)
+            e = e->findOrCreate(q->nameAt(i));
+
+        return e;
+
+    } else if (const Identifier *id = name->identifier()) {
+        const QByteArray name = QByteArray::fromRawData(id->chars(), id->size());
+        ClassOrNamespace *e = nestedClassOrNamespace(name);
+
+        if (! e) {
+            e = _factory->allocClassOrNamespace(this);
+            _classOrNamespaces.insert(name, e);
+        }
+
+        return e;
+    }
+
+    return 0;
+}
+
+CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
+    : _snapshot(snapshot)
+{
+    _globalNamespace = allocClassOrNamespace(/*parent = */ 0);
+    _currentClassOrNamespace = _globalNamespace;
+
+    process(thisDocument);
+}
+
+CreateBindings::~CreateBindings()
+{
+    qDeleteAll(_entities);
+}
+
+ClassOrNamespace *CreateBindings::switchCurrentEntity(ClassOrNamespace *classOrNamespace)
+{
+    ClassOrNamespace *previous = _currentClassOrNamespace;
+    _currentClassOrNamespace = classOrNamespace;
+    return previous;
+}
+
+ClassOrNamespace *CreateBindings::globalNamespace() const
+{
+    return _globalNamespace;
+}
+
+ClassOrNamespace *CreateBindings::findClassOrNamespace(Symbol *s)
+{
+    // jump to the enclosing class or namespace.
+    for (; s; s = s->enclosingSymbol()) {
+        if (s->isClass() || s->isNamespace())
+            break;
+    }
+
+    QList<QByteArray> path;
+    for (; s; s = s->enclosingSymbol()) {
+        if (const Identifier *id = s->identifier())
+            path.prepend(QByteArray::fromRawData(id->chars(), id->size()));
+    }
+
+    ClassOrNamespace *e = _globalNamespace->findClassOrNamespace(path);
+    return e;
+}
+
+ClassOrNamespace *CreateBindings::findClassOrNamespace(const QList<QByteArray> &path)
+{
+    ClassOrNamespace *e = _globalNamespace->findClassOrNamespace(path);
+    return e;
+}
+
+void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace)
+{
+    ClassOrNamespace *previous = switchCurrentEntity(classOrNamespace);
+    accept(s);
+    (void) switchCurrentEntity(previous);
+}
+
+void CreateBindings::process(Symbol *symbol)
+{
+#ifndef CPLUSPLUS_NO_LAZY_LOOKUP
+    _currentClassOrNamespace->addTodo(symbol);
+#else
+    accept(symbol);
+#endif
+}
+
+ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
+{
+    ClassOrNamespace *e = new ClassOrNamespace(this, parent);
+    _entities.append(e);
+    return e;
+}
+
+void CreateBindings::process(Document::Ptr doc)
+{
+    if (! doc)
+        return;
+
+    else if (Namespace *globalNamespace = doc->globalNamespace()) {
+        if (! _processed.contains(globalNamespace)) {
+            _processed.insert(globalNamespace);
+
+            foreach (const Document::Include &i, doc->includes()) {
+                if (Document::Ptr incl = _snapshot.document(i.fileName()))
+                    process(incl);
+            }
+
+            accept(globalNamespace);
+        }
+    }
+}
+
+ClassOrNamespace *CreateBindings::enterEntity(Symbol *symbol)
+{
+    ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreate(symbol->name());
+    entity->addSymbol(symbol);
+
+    return switchCurrentEntity(entity);
+}
+
+ClassOrNamespace *CreateBindings::enterGlobalEntity(Symbol *symbol)
+{
+    ClassOrNamespace *entity = _globalNamespace->findOrCreate(symbol->name());
+    entity->addSymbol(symbol);
+
+    return switchCurrentEntity(entity);
+}
+
+bool CreateBindings::visit(Namespace *ns)
+{
+    ClassOrNamespace *previous = enterEntity(ns);
+
+    for (unsigned i = 0; i < ns->memberCount(); ++i)
+        process(ns->memberAt(i));
+
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(Class *klass)
+{
+    ClassOrNamespace *previous = enterEntity(klass);
+
+    for (unsigned i = 0; i < klass->baseClassCount(); ++i)
+        process(klass->baseClassAt(i));
+
+    for (unsigned i = 0; i < klass->memberCount(); ++i)
+        process(klass->memberAt(i));
+
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(ForwardClassDeclaration *klass)
+{
+    ClassOrNamespace *previous = enterEntity(klass);
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(Enum *e)
+{
+    _currentClassOrNamespace->addEnum(e);
+    return false;
+}
+
+bool CreateBindings::visit(Declaration *decl)
+{
+    if (decl->isTypedef()) {
+        const FullySpecifiedType ty = decl->type();
+        const Identifier *typedefId = decl->identifier();
+
+        if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
+            if (const NamedType *namedTy = ty->asNamedType()) {
+                if (ClassOrNamespace *e = _currentClassOrNamespace->lookupClassOrNamespace(namedTy->name())) {
+                    const QByteArray alias = QByteArray::fromRawData(typedefId->chars(), typedefId->size());
+                    _currentClassOrNamespace->addNestedClassOrNamespace(alias, e);
+                } else if (false) {
+                    Overview oo;
+                    qDebug() << "found entity not found for" << oo(namedTy->name());
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+bool CreateBindings::visit(Function *)
+{
+    return false;
+}
+
+bool CreateBindings::visit(BaseClass *b)
+{
+    if (ClassOrNamespace *base = _currentClassOrNamespace->lookupClassOrNamespace(b->name())) {
+        _currentClassOrNamespace->addUsing(base);
+    } else if (false) {
+        Overview oo;
+        qDebug() << "no entity for:" << oo(b->name());
+    }
+    return false;
+}
+
+bool CreateBindings::visit(UsingNamespaceDirective *u)
+{
+    if (ClassOrNamespace *e = _currentClassOrNamespace->lookupClassOrNamespace(u->name())) {
+        _currentClassOrNamespace->addUsing(e);
+    } else if (false) {
+        Overview oo;
+        qDebug() << "no entity for namespace:" << oo(u->name());
+    }
+    return false;
+}
+
+bool CreateBindings::visit(NamespaceAlias *a)
+{
+    if (! a->identifier()) {
+        return false;
+
+    } else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupClassOrNamespace(a->namespaceName())) {
+        const QByteArray name = QByteArray::fromRawData(a->identifier()->chars(), a->identifier()->size());
+        _currentClassOrNamespace->addNestedClassOrNamespace(name, e);
+
+    } else if (false) {
+        Overview oo;
+        qDebug() << "no entity for namespace:" << oo(a->namespaceName());
+    }
+
+    return false;
+}
+
+bool CreateBindings::visit(ObjCClass *klass)
+{
+    ClassOrNamespace *previous = enterGlobalEntity(klass);
+
+    process(klass->baseClass());
+
+    for (unsigned i = 0; i < klass->protocolCount(); ++i)
+        process(klass->protocolAt(i));
+
+    for (unsigned i = 0; i < klass->memberCount(); ++i)
+        process(klass->memberAt(i));
+
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(ObjCBaseClass *b)
+{
+    if (ClassOrNamespace *base = _globalNamespace->lookupClassOrNamespace(b->name())) {
+        _currentClassOrNamespace->addUsing(base);
+    } else if (false) {
+        Overview oo;
+        qDebug() << "no entity for:" << oo(b->name());
+    }
+    return false;
+}
+
+bool CreateBindings::visit(ObjCForwardClassDeclaration *klass)
+{
+    ClassOrNamespace *previous = enterGlobalEntity(klass);
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(ObjCProtocol *proto)
+{
+    ClassOrNamespace *previous = enterGlobalEntity(proto);
+
+    for (unsigned i = 0; i < proto->protocolCount(); ++i)
+        process(proto->protocolAt(i));
+
+    for (unsigned i = 0; i < proto->memberCount(); ++i)
+        process(proto->memberAt(i));
+
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(ObjCBaseProtocol *b)
+{
+    if (ClassOrNamespace *base = _globalNamespace->lookupClassOrNamespace(b->name())) {
+        _currentClassOrNamespace->addUsing(base);
+    } else if (false) {
+        Overview oo;
+        qDebug() << "no entity for:" << oo(b->name());
+    }
+    return false;
+}
+
+bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto)
+{
+    ClassOrNamespace *previous = enterGlobalEntity(proto);
+    _currentClassOrNamespace = previous;
+    return false;
+}
+
+bool CreateBindings::visit(ObjCMethod *)
+{
+    return false;
+}
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
new file mode 100644
index 0000000000000000000000000000000000000000..a39e7bb7371f5762f892d4851d2d0a04230f7228
--- /dev/null
+++ b/src/libs/cplusplus/LookupContext.h
@@ -0,0 +1,210 @@
+/**************************************************************************
+**
+** 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_LOOKUPCONTEXT_H
+#define CPLUSPLUS_LOOKUPCONTEXT_H
+
+#include "CppDocument.h"
+#include "LookupItem.h"
+#include <FullySpecifiedType.h>
+#include <Type.h>
+#include <SymbolVisitor.h>
+#include <QtCore/QSet>
+
+namespace CPlusPlus {
+
+class CreateBindings;
+
+class CPLUSPLUS_EXPORT ClassOrNamespace
+{
+public:
+    ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
+
+    QList<ClassOrNamespace *> usings() const;
+    QList<Enum *> enums() const;
+    QList<Symbol *> symbols() const;
+
+    ClassOrNamespace *globalNamespace() const;
+
+    QList<Symbol *> lookup(const Name *name);
+
+    ClassOrNamespace *lookupClassOrNamespace(const Name *name);
+    ClassOrNamespace *findClassOrNamespace(const Name *name);
+    ClassOrNamespace *findClassOrNamespace(const QList<QByteArray> &path);
+
+    /// \internal
+    static void lookup_helper(const Name *name, Scope *scope, QList<Symbol *> *result);
+
+private:
+    /// \internal
+    void flush();
+
+    /// \internal
+    ClassOrNamespace *findOrCreate(const Name *name);
+
+    void addTodo(Symbol *symbol);
+    void addSymbol(Symbol *symbol);
+    void addEnum(Enum *e);
+    void addUsing(ClassOrNamespace *u);
+    void addNestedClassOrNamespace(const QByteArray &alias, ClassOrNamespace *e);
+
+    void lookup_helper(const Name *name, ClassOrNamespace *binding,
+                       QList<Symbol *> *result,
+                       QSet<ClassOrNamespace *> *processed);
+
+    ClassOrNamespace *lookupClassOrNamespace_helper(const Name *name, QSet<ClassOrNamespace *> *processed);
+    ClassOrNamespace *findClassOrNamespace_helper(const Name *name, QSet<ClassOrNamespace *> *processed);
+    ClassOrNamespace *findClassOrNamespace_helper(const QByteArray &name, QSet<ClassOrNamespace *> *processed);
+
+    ClassOrNamespace *nestedClassOrNamespace(const QByteArray &name) const;
+
+private:
+    CreateBindings *_factory;
+    ClassOrNamespace *_parent;
+    QList<Symbol *> _symbols;
+    QList<ClassOrNamespace *> _usings;
+    QHash<QByteArray, ClassOrNamespace *> _classOrNamespaces;
+    QList<Enum *> _enums;
+    QList<Symbol *> _todo;
+    bool _flushing;
+
+    friend class CreateBindings;
+};
+
+class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
+{
+    Q_DISABLE_COPY(CreateBindings)
+
+public:
+    CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
+    virtual ~CreateBindings();
+
+    ClassOrNamespace *globalNamespace() const;
+
+    ClassOrNamespace *findClassOrNamespace(Symbol *s); // ### rename
+    ClassOrNamespace *findClassOrNamespace(const QList<QByteArray> &path);
+
+    /// \internal
+    void process(Symbol *s, ClassOrNamespace *classOrNamespace);
+
+    /// \internal
+    ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent);
+
+protected:
+    using SymbolVisitor::visit;
+
+    ClassOrNamespace *switchCurrentEntity(ClassOrNamespace *classOrNamespace);
+    ClassOrNamespace *enterEntity(Symbol *symbol);
+    ClassOrNamespace *enterGlobalEntity(Symbol *symbol);
+
+    void process(Document::Ptr doc);
+    void process(Symbol *symbol);
+
+    virtual bool visit(Namespace *ns);
+    virtual bool visit(Class *klass);
+    virtual bool visit(ForwardClassDeclaration *klass);
+    virtual bool visit(Enum *e);
+    virtual bool visit(Declaration *decl);
+    virtual bool visit(Function *);
+    virtual bool visit(BaseClass *b);
+    virtual bool visit(UsingNamespaceDirective *u);
+    virtual bool visit(NamespaceAlias *a);
+
+    virtual bool visit(ObjCClass *klass);
+    virtual bool visit(ObjCBaseClass *b);
+    virtual bool visit(ObjCForwardClassDeclaration *klass);
+    virtual bool visit(ObjCProtocol *proto);
+    virtual bool visit(ObjCBaseProtocol *b);
+    virtual bool visit(ObjCForwardProtocolDeclaration *proto);
+    virtual bool visit(ObjCMethod *);
+
+private:
+    Snapshot _snapshot;
+    QSet<Namespace *> _processed;
+    QList<ClassOrNamespace *> _entities;
+    ClassOrNamespace *_globalNamespace;
+    ClassOrNamespace *_currentClassOrNamespace;
+};
+
+class CPLUSPLUS_EXPORT LookupContext
+{
+public:
+    LookupContext();
+
+    LookupContext(Document::Ptr thisDocument,
+                  const Snapshot &snapshot);
+
+    LookupContext(Document::Ptr expressionDocument,
+                  Document::Ptr thisDocument,
+                  const Snapshot &snapshot);
+
+    LookupContext(const LookupContext &other);
+    LookupContext &operator = (const LookupContext &other);
+
+    bool isValid() const;
+
+    Document::Ptr expressionDocument() const;
+    Document::Ptr thisDocument() const;
+    Document::Ptr document(const QString &fileName) const;
+    Snapshot snapshot() const;
+
+    QList<Symbol *> lookup(const Name *name, Scope *scope) const;
+
+    ClassOrNamespace *globalNamespace() const;
+
+    ClassOrNamespace *classOrNamespace(const Name *name, Scope *scope) const;
+    ClassOrNamespace *classOrNamespace(Symbol *symbol) const;
+
+    /// \internal
+    QSharedPointer<CreateBindings> bindings() const;
+
+    /// \internal
+    void setBindings(QSharedPointer<CreateBindings> bindings);
+
+    Q_DECL_DEPRECATED Control *control() const;
+
+private:
+    Control *_control;
+
+    // The current expression.
+    Document::Ptr _expressionDocument;
+
+    // The current document.
+    Document::Ptr _thisDocument;
+
+    // All documents.
+    Snapshot _snapshot;
+
+    // Bindings
+    mutable QSharedPointer<CreateBindings> _bindings;
+};
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_LOOKUPCONTEXT_H
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 3904b690ad3e489a784bd8e474e1d7f0a62ec960..cdd03b7b4f06bf85828520c794e1981d0b54e714 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -35,6 +35,7 @@ HEADERS += \
     $$PWD/TypePrettyPrinter.h \
     $$PWD/ResolveExpression.h \
     $$PWD/LookupItem.h \
+    $$PWD/LookupContext.h \
     $$PWD/DeprecatedLookupContext.h \
     $$PWD/CppBindings.h \
     $$PWD/ASTParent.h \
@@ -61,6 +62,7 @@ SOURCES += \
     $$PWD/TypePrettyPrinter.cpp \
     $$PWD/ResolveExpression.cpp \
     $$PWD/LookupItem.cpp \
+    $$PWD/LookupContext.cpp \
     $$PWD/DeprecatedLookupContext.cpp \
     $$PWD/CppBindings.cpp \
     $$PWD/ASTParent.cpp \