diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 1f2ee33368a359b06676a314f517383127023e4c..cf4dd079401733660de30435c8e87c07a46d5ae0 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -29,6 +29,8 @@
 
 #include "CppDocument.h"
 #include "FastPreprocessor.h"
+#include "LookupContext.h"
+#include "Overview.h"
 
 #include <Control.h>
 #include <TranslationUnit.h>
@@ -36,8 +38,10 @@
 #include <Semantic.h>
 #include <Literals.h>
 #include <Symbols.h>
+#include <Names.h>
 #include <AST.h>
 #include <Scope.h>
+#include <SymbolVisitor.h>
 
 #include <QtCore/QByteArray>
 #include <QtCore/QBitArray>
@@ -570,3 +574,120 @@ void Snapshot::simplified_helper(Document::Ptr doc, Snapshot *snapshot) const
         }
     }
 }
+
+namespace {
+class FindMatchingDefinition: public SymbolVisitor
+{
+    Symbol *_declaration;
+    QList<Function *> _result;
+
+public:
+    FindMatchingDefinition(Symbol *declaration)
+        : _declaration(declaration) {}
+
+    QList<Function *> result() const { return _result; }
+
+    using SymbolVisitor::visit;
+
+    virtual bool visit(Function *fun)
+    {
+        if (_declaration->identifier()->isEqualTo(fun->identifier()))
+            _result.append(fun);
+
+        return false;
+    }
+
+    virtual bool visit(Block *)
+    {
+        return false;
+    }
+};
+} // end of anonymous namespace
+
+Symbol *Snapshot::findMatchingDefinition(Symbol *symbol) const
+{
+    if (! symbol->identifier())
+        return 0;
+
+    Document::Ptr thisDocument = document(QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()));
+    if (! thisDocument) {
+        qWarning() << "undefined document:" << symbol->fileName();
+        return 0;
+    }
+
+    LookupContext thisContext(thisDocument, *this);
+    const QList<Symbol *> declarationCandidates = thisContext.lookup(symbol->name(), symbol);
+    if (declarationCandidates.isEmpty()) {
+        qWarning() << "unresolved declaration:" << symbol->fileName() << symbol->line() << symbol->column();
+        return 0;
+    }
+
+    Symbol *declaration = declarationCandidates.first();
+    Function *declarationTy = declaration->type()->asFunctionType();
+    if (! declarationTy) {
+        qWarning() << "not a function:" << declaration->fileName() << declaration->line() << declaration->column();
+        return 0;
+    }
+
+    foreach (Document::Ptr doc, *this) {
+        if (! doc->control()->findIdentifier(declaration->identifier()->chars(),
+                                             declaration->identifier()->size()))
+            continue;
+
+        FindMatchingDefinition candidates(declaration);
+        candidates.accept(doc->globalNamespace());
+
+        const QList<Function *> result = candidates.result();
+        if (! result.isEmpty()) {
+            LookupContext context(doc, *this);
+
+            QList<Function *> viableFunctions;
+
+            foreach (Function *fun, result) {
+                const QList<Symbol *> declarations = context.lookup(fun->name(), fun);
+
+                if (declarations.contains(declaration))
+                    viableFunctions.append(fun);
+
+                else if (false)
+                    qDebug() << "does not contain" << declaration->fileName() << declaration->line() << declaration->column();
+            }
+
+            if (viableFunctions.isEmpty())
+                continue;
+
+            else if (viableFunctions.length() == 1)
+                return viableFunctions.first();
+
+            Function *best = 0;
+
+            foreach (Function *fun, viableFunctions) {
+                if (fun->identity()->isEqualTo(declaration->identity()))
+                    continue;
+
+                else if (fun->argumentCount() == declarationTy->argumentCount()) {
+                    if (! best)
+                        best = fun;
+
+                    unsigned argc = 0;
+                    for (; argc < declarationTy->argumentCount(); ++argc) {
+                        Symbol *arg = fun->argumentAt(argc);
+                        Symbol *otherArg = declarationTy->argumentAt(argc);
+                        if (! arg->type().isEqualTo(otherArg->type()))
+                            break;
+                    }
+
+                    if (argc == declarationTy->argumentCount())
+                        best = fun;
+                }
+            }
+
+            if (! best)
+                best = viableFunctions.first();
+
+            return best;
+        }
+    }
+
+    return 0;
+}
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index f2cb24856d257961a5f3b6c00465a71277bb6f85..854da42a0ce1dd811f9a152933dc0c20918e27c6 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -364,6 +364,8 @@ public:
     Document::Ptr documentFromSource(const QByteArray &preprocessedCode,
                                      const QString &fileName) const;
 
+    Symbol *findMatchingDefinition(Symbol *symbol) const;
+
 private:
     void simplified_helper(Document::Ptr doc, Snapshot *snapshot) const;
 
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 2cd4dea274f473840c2f201f6614f1e0758395ee..3951d624816ef8cdf8a6a7db8a341f51757f57db 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -46,12 +46,12 @@
 
 using namespace CPlusPlus;
 
-static void fullyQualifiedName(Symbol *symbol, QList<const Name *> *names)
+static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
 {
     if (! symbol)
         return;
 
-    fullyQualifiedName(symbol->enclosingSymbol(), names);
+    fullyQualifiedName_helper(symbol->enclosingSymbol(), names);
 
     if (symbol->name() && (symbol->isClass() || symbol->isNamespace())) {
         if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
@@ -119,6 +119,13 @@ LookupContext &LookupContext::operator = (const LookupContext &other)
     return *this;
 }
 
+QList<const Name *> LookupContext::fullyQualifiedName(Symbol *symbol)
+{
+    QList<const Name *> names;
+    fullyQualifiedName_helper(symbol, &names);
+    return names;
+}
+
 QSharedPointer<CreateBindings> LookupContext::bindings() const
 {
     if (! _bindings)
@@ -230,8 +237,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
             if (fun->name() && fun->name()->isQualifiedNameId()) {
                 const QualifiedNameId *q = fun->name()->asQualifiedNameId();
 
-                QList<const Name *> path;
-                fullyQualifiedName(scope->owner(), &path);
+                QList<const Name *> path = fullyQualifiedName(scope->owner());
 
                 for (unsigned index = 0; index < q->nameCount() - 1; ++index) { // ### TODO remove me.
                     const Name *name = q->nameAt(index);
@@ -681,8 +687,7 @@ ClassOrNamespace *CreateBindings::globalNamespace() const
 
 ClassOrNamespace *CreateBindings::findClassOrNamespace(Symbol *symbol)
 {
-    QList<const Name *> names;
-    fullyQualifiedName(symbol, &names);
+    const QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
 
     if (names.isEmpty())
         return _globalNamespace;
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 4dff4c4cd361d82cfbb967a5627c3b9830f92645..04a74440469a9f6a0e68b62e314398c46cfba314 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -231,6 +231,8 @@ public:
 
     Control *control() const; // ### deprecate
 
+    static QList<const Name *> fullyQualifiedName(Symbol *symbol);
+
 private:
     Control *_control;
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 454f889e23d904cd6cea8da7c9b0503bd0a15520..2d1a06d21d88993cac114becc88068b8df9fc2dd 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -1271,7 +1271,7 @@ void CPPEditor::switchDeclarationDefinition()
         if (declaration)
             openCppEditorAt(linkToSymbol(declaration));
     } else if (lastSymbol->type()->isFunctionType()) {
-        if (Symbol *def = findDefinition(lastSymbol))
+        if (Symbol *def = findDefinition(lastSymbol, snapshot))
             openCppEditorAt(linkToSymbol(def));
     }
 }
@@ -1444,7 +1444,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
         if (Symbol *symbol = result.lastVisibleSymbol()) {
             Symbol *def = 0;
             if (resolveTarget && !lastSymbol->isFunction())
-                def = findDefinition(symbol);
+                def = findDefinition(symbol, snapshot);
 
             link = linkToSymbol(def ? def : symbol);
             link.begin = beginOfToken;
@@ -1482,91 +1482,15 @@ void CPPEditor::jumpToDefinition()
     openLink(findLinkAt(textCursor()));
 }
 
-Symbol *CPPEditor::findDefinition(Symbol *symbol)
+Symbol *CPPEditor::findDefinition(Symbol *symbol, const Snapshot &snapshot)
 {
     if (symbol->isFunction())
         return 0; // symbol is a function definition.
 
-    Function *funTy = symbol->type()->asFunctionType();
-    if (! funTy)
-        return 0; // symbol does not have function type.
+    else if (! symbol->type()->isFunctionType())
+        return 0; // not a function declaration
 
-    const Name *name = symbol->name();
-    if (! name)
-        return 0; // skip anonymous functions!
-
-    if (const QualifiedNameId *q = name->asQualifiedNameId())
-        name = q->unqualifiedNameId();
-
-    // map from file names to function definitions.
-    QMap<QString, QList<Function *> > functionDefinitions;
-
-    // find function definitions.
-    FindFunctionDefinitions findFunctionDefinitions;
-
-    // save the current snapshot
-    const Snapshot snapshot = m_modelManager->snapshot();
-
-    foreach (Document::Ptr doc, snapshot) {
-        if (Scope *globals = doc->globalSymbols()) {
-            QList<Function *> *localFunctionDefinitions =
-                    &functionDefinitions[doc->fileName()];
-
-            findFunctionDefinitions(name, globals,
-                                    localFunctionDefinitions);
-        }
-    }
-
-    // a dummy document.
-    Document::Ptr expressionDocument = Document::create("<empty>");
-
-    Function *bestMatch = 0;
-    int bestScore = -1;
-
-    QMapIterator<QString, QList<Function *> > it(functionDefinitions);
-    while (it.hasNext()) {
-        it.next();
-
-        // get the instance of the document.
-        Document::Ptr thisDocument = snapshot.document(it.key());
-
-        foreach (Function *f, it.value()) {
-            int score = 0; // current function's score
-
-            const int funTyArgsCount = funTy->argumentCount();
-            const int fArgsCount = f->argumentCount();
-
-            // max score if arguments count equals
-            if (funTyArgsCount == fArgsCount)
-                score += funTyArgsCount + 1;
-            else
-                score += (funTyArgsCount < fArgsCount) ? funTyArgsCount : fArgsCount;
-
-            // +1 to score for every equal parameter
-            unsigned minCount = (funTyArgsCount < fArgsCount) ? funTyArgsCount : fArgsCount;
-            for (unsigned i = 0; i < minCount; ++i)
-                if (Symbol *funTyArg = funTy->argumentAt(i))
-                    if (Symbol *fArg = f->argumentAt(i))
-                        if (funTyArg->type().isEqualTo(fArg->type()))
-                            score++;
-
-            if (score > bestScore) {
-                // create a lookup context
-                const DeprecatedLookupContext context(f, expressionDocument,
-                                            thisDocument, snapshot);
-
-                // search the matching definition for the function declaration `symbol'.
-                foreach (Symbol *s, context.resolve(f->name())) {
-                    if (s == symbol) {
-                        bestMatch = f;
-                        bestScore = score;
-                    }
-                }
-            }
-        }
-    }
-
-    return bestMatch;
+    return snapshot.findMatchingDefinition(symbol);
 }
 
 unsigned CPPEditor::editorRevision() const
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 8ab0ab0c6b3b3122d2a01ed3b6f368be1547f485..4e59ffccad4d68358293b8979abf61ceaf7b543b 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -252,7 +252,7 @@ private:
 
     CPlusPlus::Symbol *markSymbols();
     bool sortedMethodOverview() const;
-    CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol);
+    CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot);
     virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
 
     TextEditor::ITextEditor *openCppEditorAt(const QString &fileName, int line,