diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 0886416e48dffe223ff35fc00d1126e2b5e2e2d2..46586aa5971f543cdc40be90e20345185b8030d4 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -717,239 +717,3 @@ void Snapshot::simplified_helper(Document::Ptr doc, Snapshot *snapshot) const
     }
 }
 
-namespace {
-class FindMatchingDefinition: public SymbolVisitor
-{
-    Symbol *_declaration;
-    const OperatorNameId *_oper;
-    QList<Function *> _result;
-
-public:
-    FindMatchingDefinition(Symbol *declaration)
-        : _declaration(declaration)
-        , _oper(0)
-    {
-        if (_declaration->name())
-            _oper = _declaration->name()->asOperatorNameId();
-    }
-
-    QList<Function *> result() const { return _result; }
-
-    using SymbolVisitor::visit;
-
-    virtual bool visit(Function *fun)
-    {
-        if (_oper) {
-            if (const Name *name = fun->unqualifiedName()) {
-                    if (_oper->isEqualTo(name))
-                        _result.append(fun);
-            }
-        } else if (const Identifier *id = _declaration->identifier()) {
-            if (id->isEqualTo(fun->identifier()))
-                _result.append(fun);
-        }
-
-        return false;
-    }
-
-    virtual bool visit(Block *)
-    {
-        return false;
-    }
-};
-} // end of anonymous namespace
-
-// strict means the returned symbol has to match exactly,
-// including argument count and argument types
-Symbol *Snapshot::findMatchingDefinition(Symbol *declaration, bool strict) const
-{
-    if (!declaration)
-        return 0;
-
-    Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()));
-    if (! thisDocument) {
-        qWarning() << "undefined document:" << declaration->fileName();
-        return 0;
-    }
-
-    Function *declarationTy = declaration->type()->asFunctionType();
-    if (! declarationTy) {
-        qWarning() << "not a function:" << declaration->fileName() << declaration->line() << declaration->column();
-        return 0;
-    }
-
-    foreach (Document::Ptr doc, *this) {
-        const Identifier *id = declaration->identifier();
-        if (id && ! doc->control()->findIdentifier(id->chars(),
-                                                   id->size()))
-            continue;
-        if (!id) {
-            if (!declaration->name())
-                continue;
-            const OperatorNameId *oper = declaration->name()->asOperatorNameId();
-            if (!oper)
-                continue;
-            if (!doc->control()->findOperatorNameId(oper->kind()))
-                continue;
-        }
-
-        FindMatchingDefinition candidates(declaration);
-        candidates.accept(doc->globalNamespace());
-
-        const QList<Function *> result = candidates.result();
-        if (! result.isEmpty()) {
-            LookupContext context(doc, *this);
-
-            QList<Function *> viableFunctions;
-
-            ClassOrNamespace *enclosingType = context.lookupType(declaration);
-            if (! enclosingType)
-                continue; // nothing to do
-
-            foreach (Function *fun, result) {
-                const QList<LookupItem> declarations = context.lookup(fun->name(), fun->enclosingScope());
-                if (declarations.isEmpty())
-                    continue;
-
-                const LookupItem best = declarations.first();
-                if (enclosingType == context.lookupType(best.declaration()))
-                    viableFunctions.append(fun);
-            }
-
-            if (viableFunctions.isEmpty())
-                continue;
-
-            else if (! strict && viableFunctions.length() == 1)
-                return viableFunctions.first();
-
-            Function *best = 0;
-
-            foreach (Function *fun, viableFunctions) {
-                if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
-                    continue;
-                else if (fun->argumentCount() == declarationTy->argumentCount()) {
-                    if (! strict && ! 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 (strict && ! best)
-                continue;
-
-            if (! best)
-                best = viableFunctions.first();
-            return best;
-        }
-    }
-
-    return 0;
-}
-
-Class *Snapshot::findMatchingClassDeclaration(Symbol *declaration) const
-{
-    if (! declaration->identifier())
-        return 0;
-
-    foreach (Document::Ptr doc, *this) {
-        if (! doc->control()->findIdentifier(declaration->identifier()->chars(),
-                                             declaration->identifier()->size()))
-            continue;
-
-        LookupContext context(doc, *this);
-
-        ClassOrNamespace *type = context.lookupType(declaration);
-        if (!type)
-            continue;
-
-        foreach (Symbol *s, type->symbols()) {
-            if (Class *c = s->asClass())
-                return c;
-        }
-    }
-
-    return 0;
-}
-
-void CPlusPlus::findMatchingDeclaration(const LookupContext &context,
-                                        Function *functionType,
-                                        QList<Declaration *> *typeMatch,
-                                        QList<Declaration *> *argumentCountMatch,
-                                        QList<Declaration *> *nameMatch)
-{
-    Scope *enclosingScope = functionType->enclosingScope();
-    while (! (enclosingScope->isNamespace() || enclosingScope->isClass()))
-        enclosingScope = enclosingScope->enclosingScope();
-    Q_ASSERT(enclosingScope != 0);
-
-    const Name *functionName = functionType->name();
-    if (! functionName)
-        return; // anonymous function names are not valid c++
-
-    ClassOrNamespace *binding = 0;
-    const QualifiedNameId *qName = functionName->asQualifiedNameId();
-    if (qName) {
-        if (qName->base())
-            binding = context.lookupType(qName->base(), enclosingScope);
-        else
-            binding = context.globalNamespace();
-        functionName = qName->name();
-    }
-
-    if (!binding) { // declaration for a global function
-        binding = context.lookupType(enclosingScope);
-
-        if (!binding)
-            return;
-    }
-
-    const Identifier *funcId = functionName->identifier();
-    if (!funcId) // E.g. operator, which we might be able to handle in the future...
-        return;
-
-    foreach (Symbol *s, binding->symbols()) {
-        Scope *scope = s->asScope();
-        if (!scope)
-            continue;
-
-        for (Symbol *s = scope->find(funcId); s; s = s->next()) {
-            if (! s->name())
-                continue;
-            else if (! funcId->isEqualTo(s->identifier()))
-                continue;
-            else if (! s->type()->isFunctionType())
-                continue;
-            else if (Declaration *decl = s->asDeclaration()) {
-                if (Function *declFunTy = decl->type()->asFunctionType()) {
-                    if (functionType->isEqualTo(declFunTy))
-                        typeMatch->prepend(decl);
-                    else if (functionType->argumentCount() == declFunTy->argumentCount())
-                        argumentCountMatch->prepend(decl);
-                    else
-                        nameMatch->append(decl);
-                }
-            }
-        }
-    }
-}
-
-QList<Declaration *> CPlusPlus::findMatchingDeclaration(const LookupContext &context, Function *functionType)
-{
-    QList<Declaration *> result;
-    QList<Declaration *> nameMatch, argumentCountMatch, typeMatch;
-    findMatchingDeclaration(context, functionType, &typeMatch, &argumentCountMatch, &nameMatch);
-    result.append(typeMatch);
-    result.append(argumentCountMatch);
-    result.append(nameMatch);
-    return result;
-}
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index fdd75447774c7db4d45a8a419db132310a2204e8..33447a4969285e48f99dd119f461537f5f9d2acb 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -381,9 +381,6 @@ public:
     Document::Ptr documentFromSource(const QByteArray &preprocessedCode,
                                      const QString &fileName) const;
 
-    Symbol *findMatchingDefinition(Symbol *symbol, bool strict = false) const;
-    Class *findMatchingClassDeclaration(Symbol *symbol) const;
-
 private:
     void simplified_helper(Document::Ptr doc, Snapshot *snapshot) const;
 
@@ -391,15 +388,6 @@ private:
     _Base _documents;
 };
 
-void CPLUSPLUS_EXPORT findMatchingDeclaration(
-        const LookupContext &context,
-        Function *functionType,
-        QList<Declaration *> *typeMatch,
-        QList<Declaration *> *argumentCountMatch,
-        QList<Declaration *> *nameMatch);
-QList<Declaration *> CPLUSPLUS_EXPORT findMatchingDeclaration(
-        const LookupContext &context, Function *functionType);
-
 } // namespace CPlusPlus
 
 #endif // CPLUSPLUS_CPPDOCUMENT_H
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 5b311ed3d5bb6f95b03cc4368ad88d83956d59f8..e9d25f2e2380c5956d16d64817b324cc07d0d0b5 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -71,6 +71,7 @@
 #include <cpptools/cpptoolsreuse.h>
 #include <cpptools/doxygengenerator.h>
 #include <cpptools/cpptoolssettings.h>
+#include <cpptools/symbolfinder.h>
 
 #include <coreplugin/icore.h>
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -419,6 +420,7 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
     , m_firstRenameChange(false)
     , m_objcEnabled(false)
     , m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings())
+    , m_symbolFinder(new CppTools::SymbolFinder(QString()))
 {
     m_initialized = false;
     qRegisterMetaType<CppEditor::Internal::SemanticInfo>("CppEditor::Internal::SemanticInfo");
@@ -862,7 +864,9 @@ void CPPEditorWidget::onContentsChanged(int position, int charsRemoved, int char
 }
 
 void CPPEditorWidget::updateFileName()
-{ }
+{
+    m_symbolFinder.reset(new CppTools::SymbolFinder(file()->fileName()));
+}
 
 void CPPEditorWidget::jumpToOutlineElement(int)
 {
@@ -1076,7 +1080,7 @@ void CPPEditorWidget::switchDeclarationDefinition()
                 openCppEditorAt(linkToSymbol(best.first()));
 
         } else if (lastVisibleSymbol && lastVisibleSymbol->isDeclaration() && lastVisibleSymbol->type()->isFunctionType()) {
-            if (Symbol *def = snapshot.findMatchingDefinition(lastVisibleSymbol))
+            if (Symbol *def = m_symbolFinder->findMatchingDefinition(lastVisibleSymbol, snapshot))
                 openCppEditorAt(linkToSymbol(def));
         }
     }
@@ -1171,12 +1175,13 @@ CPPEditorWidget::Link CPPEditorWidget::attemptFuncDeclDef(const QTextCursor &cur
 
     Symbol *target = 0;
     if (FunctionDefinitionAST *funDef = declParent->asFunctionDefinition()) {
-        QList<Declaration *> candidates = findMatchingDeclaration(LookupContext(doc, snapshot),
-                                                                  funDef->symbol);
+        QList<Declaration *> candidates =
+                m_symbolFinder->findMatchingDeclaration(LookupContext(doc, snapshot),
+                                                        funDef->symbol);
         if (!candidates.isEmpty()) // TODO: improve disambiguation
             target = candidates.first();
     } else if (declParent->asSimpleDeclaration()) {
-        target = snapshot.findMatchingDefinition(funcDecl->symbol);
+        target = m_symbolFinder->findMatchingDefinition(funcDecl->symbol, snapshot);
     }
 
     if (target) {
@@ -1426,9 +1431,8 @@ CPPEditorWidget::Link CPPEditorWidget::findLinkAt(const QTextCursor &cursor,
                 if (def == lastVisibleSymbol)
                     def = 0; // jump to declaration then.
 
-                if (symbol->isForwardClassDeclaration()) {
-                    def = snapshot.findMatchingClassDeclaration(symbol);
-                }
+                if (symbol->isForwardClassDeclaration())
+                    def = m_symbolFinder->findMatchingClassDeclaration(symbol, snapshot);
             }
 
             link = linkToSymbol(def ? def : symbol);
@@ -1464,7 +1468,7 @@ Symbol *CPPEditorWidget::findDefinition(Symbol *symbol, const Snapshot &snapshot
     else if (! symbol->type()->isFunctionType())
         return 0; // not a function declaration
 
-    return snapshot.findMatchingDefinition(symbol);
+    return m_symbolFinder->findMatchingDefinition(symbol, snapshot);
 }
 
 unsigned CPPEditorWidget::editorRevision() const
@@ -2254,6 +2258,11 @@ void CPPEditorWidget::applyDeclDefLinkChanges(bool jumpToMatch)
     updateFunctionDeclDefLink();
 }
 
+CppTools::SymbolFinder *CPPEditorWidget::symbolFinder() const
+{
+    return m_symbolFinder.data();
+}
+
 void CPPEditorWidget::abortDeclDefLink()
 {
     if (!m_declDefLink)
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 2cc792006c612a008520867ada4b12eed6be6437..eb55422bcbf4ab18e87825c2c2185d1acc2eeb3b 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -50,6 +50,7 @@
 #include <QtCore/QFutureWatcher>
 #include <QtCore/QModelIndex>
 #include <QtCore/QVector>
+#include <QtCore/QScopedPointer>
 
 QT_BEGIN_NAMESPACE
 class QComboBox;
@@ -65,6 +66,7 @@ class CppModelManagerInterface;
 namespace CppTools {
 class CppCodeStyleSettings;
 class CppRefactoringFile;
+class SymbolFinder;
 }
 
 namespace TextEditor {
@@ -200,6 +202,8 @@ public:
     QSharedPointer<FunctionDeclDefLink> declDefLink() const;
     void applyDeclDefLinkChanges(bool jumpToMatch);
 
+    CppTools::SymbolFinder *symbolFinder() const;
+
 Q_SIGNALS:
     void outlineModelIndexChanged(const QModelIndex &index);
 
@@ -333,6 +337,7 @@ private:
     QSharedPointer<FunctionDeclDefLink> m_declDefLink;
 
     CppTools::CommentsSettings m_commentsSettings;
+    QScopedPointer<CppTools::SymbolFinder> m_symbolFinder;
 };
 
 
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
index 8e0c7bb46141b8019ee56d4c6f74075a36fc52f7..76dc4ec6eb2af0f2ce53a2fae4455c1419a03425 100644
--- a/src/plugins/cppeditor/cppelementevaluator.cpp
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -34,6 +34,7 @@
 
 #include <coreplugin/ifile.h>
 #include <cpptools/cpptoolsreuse.h>
+#include <cpptools/symbolfinder.h>
 
 #include <FullySpecifiedType.h>
 #include <Literals.h>
@@ -184,8 +185,11 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot,
                        && (declaration->asTemplate()->declaration()->isClass()
                            || declaration->asTemplate()->declaration()->isForwardClassDeclaration()))) {
             if (declaration->isForwardClassDeclaration())
-                if (Symbol *classDeclaration = snapshot.findMatchingClassDeclaration(declaration))
+                if (Symbol *classDeclaration =
+                        m_editor->symbolFinder()->findMatchingClassDeclaration(
+                            declaration, snapshot)) {
                     declaration = classDeclaration;
+                }
             CppClass *cppClass = new CppClass(declaration);
             if (m_lookupBaseClasses)
                 cppClass->lookupBases(declaration, context);
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
index e1dae57f518a1cf0120da3be18457d5a02632f4a..ee9bcb1fffdc5b3e29ce1c132e01606c7b77818c 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
@@ -45,6 +45,7 @@
 #include <cplusplus/LookupContext.h>
 #include <cplusplus/Overview.h>
 #include <cpptools/cpprefactoringchanges.h>
+#include <cpptools/symbolfinder.h>
 #include <texteditor/refactoroverlay.h>
 #include <texteditor/tooltip/tooltip.h>
 #include <texteditor/tooltip/tipcontents.h>
@@ -165,13 +166,16 @@ static QSharedPointer<FunctionDeclDefLink> findLinkHelper(QSharedPointer<Functio
     Symbol *target = 0;
     if (FunctionDefinitionAST *funcDef = link->sourceDeclaration->asFunctionDefinition()) {
         QList<Declaration *> nameMatch, argumentCountMatch, typeMatch;
-        findMatchingDeclaration(LookupContext(link->sourceDocument, snapshot),
-                                funcDef->symbol,
-                                &typeMatch, &argumentCountMatch, &nameMatch);
+        CppTools::SymbolFinder finder(funcDef->symbol->fileName(), funcDef->symbol->fileNameLength());
+        finder.findMatchingDeclaration(LookupContext(link->sourceDocument, snapshot),
+                                       funcDef->symbol,
+                                       &typeMatch, &argumentCountMatch, &nameMatch);
         if (!typeMatch.isEmpty())
             target = typeMatch.first();
     } else if (link->sourceDeclaration->asSimpleDeclaration()) {
-        target = snapshot.findMatchingDefinition(link->sourceFunctionDeclarator->symbol, true);
+        CppTools::SymbolFinder finder(link->sourceFunctionDeclarator->symbol->fileName(),
+                                      link->sourceFunctionDeclarator->symbol->fileNameLength());
+        target = finder.findMatchingDefinition(link->sourceFunctionDeclarator->symbol, snapshot, true);
     }
     if (!target) {
         return noResult;
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 34844936e880483e2347bd367935b680dfd003b2..113583e52253228654574fc30ab1d1a32aa0bd0f 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -64,6 +64,7 @@
 #include <cpptools/cpptoolsreuse.h>
 #include <cpptools/cppclassesfilter.h>
 #include <cpptools/searchsymbols.h>
+#include <cpptools/symbolfinder.h>
 #include <extensionsystem/iplugin.h>
 #include <extensionsystem/pluginmanager.h>
 
@@ -1552,7 +1553,10 @@ private:
         {
             Q_ASSERT(fwdClass != 0);
 
-            if (Class *k = assistInterface()->snapshot().findMatchingClassDeclaration(fwdClass)) {
+            CppTools::SymbolFinder symbolFinder(fwdClass->fileName(), fwdClass->fileNameLength());
+            if (Class *k =
+                    symbolFinder.findMatchingClassDeclaration(fwdClass,
+                                                              assistInterface()->snapshot())) {
                 const QString headerFile = QString::fromUtf8(k->fileName(), k->fileNameLength());
 
                 // collect the fwd headers
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index cbf4d3cd702561ec9773ca3edaebf2ebb54212fd..8bce1abd05d02c9e5bc16b93d2dfbcebd50b788f 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -37,7 +37,8 @@ HEADERS += completionsettingspage.h \
     cppcodestylepreferences.h \
     cpptoolsreuse.h \
     doxygengenerator.h \
-    commentssettings.h
+    commentssettings.h \
+    symbolfinder.h
 
 SOURCES += completionsettingspage.cpp \
     cppclassesfilter.cpp \
@@ -66,7 +67,8 @@ SOURCES += completionsettingspage.cpp \
     cppcodestylepreferences.cpp \
     cpptoolsreuse.cpp \
     doxygengenerator.cpp \
-    commentssettings.cpp
+    commentssettings.cpp \
+    symbolfinder.cpp
 
 FORMS += completionsettingspage.ui \
     cppfilesettingspage.ui \
diff --git a/src/plugins/cpptools/insertionpointlocator.cpp b/src/plugins/cpptools/insertionpointlocator.cpp
index 855e5075a071f06e99c010d84bda4f20b97c4f7f..baecd498c1f03fdb10087866b589a0036ac1cfe7 100644
--- a/src/plugins/cpptools/insertionpointlocator.cpp
+++ b/src/plugins/cpptools/insertionpointlocator.cpp
@@ -33,6 +33,7 @@
 #include "cpptoolsplugin.h"
 #include "cpprefactoringchanges.h"
 #include "insertionpointlocator.h"
+#include "symbolfinder.h"
 
 #include <AST.h>
 #include <ASTVisitor.h>
@@ -516,7 +517,10 @@ static InsertionLocation nextToSurroundingDefinitions(Declaration *declaration,
     }
 
     // find the declaration's definition
-    Symbol *definition = changes.snapshot().findMatchingDefinition(surroundingFunctionDecl);
+    CppTools::SymbolFinder symbolFinder(surroundingFunctionDecl->fileName(),
+                                        surroundingFunctionDecl->fileNameLength());
+    Symbol *definition = symbolFinder.findMatchingDefinition(surroundingFunctionDecl,
+                                                             changes.snapshot());
     if (!definition)
         return noResult;
 
@@ -555,7 +559,10 @@ QList<InsertionLocation> InsertionPointLocator::methodDefinition(
     if (!declaration)
         return result;
 
-    if (Symbol *s = m_refactoringChanges.snapshot().findMatchingDefinition(declaration, true)) {
+    CppTools::SymbolFinder symbolFinder(declaration->fileName(), declaration->fileNameLength());
+    if (Symbol *s = symbolFinder.findMatchingDefinition(declaration,
+                                                        m_refactoringChanges.snapshot(),
+                                                        true)) {
         if (Function *f = s->asFunction()) {
             if (f->isConst() == declaration->type().isConst()
                     && f->isVolatile() == declaration->type().isVolatile())
diff --git a/src/plugins/cpptools/symbolfinder.cpp b/src/plugins/cpptools/symbolfinder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bb7a795817204813e5ce08ed42215a13013d27e8
--- /dev/null
+++ b/src/plugins/cpptools/symbolfinder.cpp
@@ -0,0 +1,338 @@
+#if defined(_MSC_VER)
+#pragma warning(disable:4996)
+#endif
+
+#include "symbolfinder.h"
+
+#include <Symbols.h>
+#include <Names.h>
+#include <Literals.h>
+#include <SymbolVisitor.h>
+#include <Control.h>
+#include <LookupContext.h>
+
+#include <QtCore/QDebug>
+
+#include <algorithm>
+#include <utility>
+
+using namespace CPlusPlus;
+using namespace CppTools;
+
+namespace {
+
+class FindMatchingDefinition: public SymbolVisitor
+{
+    Symbol *_declaration;
+    const OperatorNameId *_oper;
+    QList<Function *> _result;
+
+public:
+    FindMatchingDefinition(Symbol *declaration)
+        : _declaration(declaration)
+        , _oper(0)
+    {
+        if (_declaration->name())
+            _oper = _declaration->name()->asOperatorNameId();
+    }
+
+    QList<Function *> result() const { return _result; }
+
+    using SymbolVisitor::visit;
+
+    virtual bool visit(Function *fun)
+    {
+        if (_oper) {
+            if (const Name *name = fun->unqualifiedName()) {
+                    if (_oper->isEqualTo(name))
+                        _result.append(fun);
+            }
+        } else if (const Identifier *id = _declaration->identifier()) {
+            if (id->isEqualTo(fun->identifier()))
+                _result.append(fun);
+        }
+
+        return false;
+    }
+
+    virtual bool visit(Block *)
+    {
+        return false;
+    }
+};
+
+} // end of anonymous namespace
+
+
+SymbolFinder::SymbolFinder(const QString &referenceFileName)
+    : m_referenceFile(referenceFileName)
+{}
+
+SymbolFinder::SymbolFinder(const char *referenceFileName, unsigned referenceFileLength)
+    : m_referenceFile(QString::fromUtf8(referenceFileName, referenceFileLength))
+{}
+
+// strict means the returned symbol has to match exactly,
+// including argument count and argument types
+Symbol *SymbolFinder::findMatchingDefinition(Symbol *declaration,
+                                             const Snapshot &snapshot,
+                                             bool strict)
+{
+    if (!declaration)
+        return 0;
+
+    QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
+    Q_ASSERT(declFile == m_referenceFile);
+
+    Document::Ptr thisDocument = snapshot.document(declFile);
+    if (! thisDocument) {
+        qWarning() << "undefined document:" << declaration->fileName();
+        return 0;
+    }
+
+    Function *declarationTy = declaration->type()->asFunctionType();
+    if (! declarationTy) {
+        qWarning() << "not a function:" << declaration->fileName()
+                   << declaration->line() << declaration->column();
+        return 0;
+    }
+
+    foreach (const QString &fileName, fileIterationOrder(snapshot)) {
+        Document::Ptr doc = snapshot.document(fileName);
+        if (!doc) {
+            clear(fileName);
+            continue;
+        }
+
+        const Identifier *id = declaration->identifier();
+        if (id && ! doc->control()->findIdentifier(id->chars(), id->size()))
+            continue;
+
+        if (!id) {
+            if (!declaration->name())
+                continue;
+            const OperatorNameId *oper = declaration->name()->asOperatorNameId();
+            if (!oper)
+                continue;
+            if (!doc->control()->findOperatorNameId(oper->kind()))
+                continue;
+        }
+
+        FindMatchingDefinition candidates(declaration);
+        candidates.accept(doc->globalNamespace());
+
+        const QList<Function *> result = candidates.result();
+        if (! result.isEmpty()) {
+            LookupContext context(doc, snapshot);
+
+            QList<Function *> viableFunctions;
+
+            ClassOrNamespace *enclosingType = context.lookupType(declaration);
+            if (! enclosingType)
+                continue; // nothing to do
+
+            foreach (Function *fun, result) {
+                const QList<LookupItem> declarations = context.lookup(fun->name(), fun->enclosingScope());
+                if (declarations.isEmpty())
+                    continue;
+
+                const LookupItem best = declarations.first();
+                if (enclosingType == context.lookupType(best.declaration()))
+                    viableFunctions.append(fun);
+            }
+
+            if (viableFunctions.isEmpty())
+                continue;
+
+            else if (! strict && viableFunctions.length() == 1)
+                return viableFunctions.first();
+
+            Function *best = 0;
+
+            foreach (Function *fun, viableFunctions) {
+                if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
+                    continue;
+                else if (fun->argumentCount() == declarationTy->argumentCount()) {
+                    if (! strict && ! 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 (strict && ! best)
+                continue;
+
+            if (! best)
+                best = viableFunctions.first();
+            return best;
+        }
+    }
+
+    return 0;
+}
+
+Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot)
+{
+    if (! declaration->identifier())
+        return 0;
+
+    QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
+    Q_ASSERT(declFile == m_referenceFile);
+
+    foreach (const QString &file, fileIterationOrder(snapshot)) {
+        Document::Ptr doc = snapshot.document(file);
+        if (!doc) {
+            clear(file);
+            continue;
+        }
+
+        if (! doc->control()->findIdentifier(declaration->identifier()->chars(),
+                                             declaration->identifier()->size()))
+            continue;
+
+        LookupContext context(doc, snapshot);
+
+        ClassOrNamespace *type = context.lookupType(declaration);
+        if (!type)
+            continue;
+
+        foreach (Symbol *s, type->symbols()) {
+            if (Class *c = s->asClass())
+                return c;
+        }
+    }
+
+    return 0;
+}
+
+void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
+                                           Function *functionType,
+                                           QList<Declaration *> *typeMatch,
+                                           QList<Declaration *> *argumentCountMatch,
+                                           QList<Declaration *> *nameMatch)
+{
+    Scope *enclosingScope = functionType->enclosingScope();
+    while (! (enclosingScope->isNamespace() || enclosingScope->isClass()))
+        enclosingScope = enclosingScope->enclosingScope();
+    Q_ASSERT(enclosingScope != 0);
+
+    const Name *functionName = functionType->name();
+    if (! functionName)
+        return; // anonymous function names are not valid c++
+
+    ClassOrNamespace *binding = 0;
+    const QualifiedNameId *qName = functionName->asQualifiedNameId();
+    if (qName) {
+        if (qName->base())
+            binding = context.lookupType(qName->base(), enclosingScope);
+        else
+            binding = context.globalNamespace();
+        functionName = qName->name();
+    }
+
+    if (!binding) { // declaration for a global function
+        binding = context.lookupType(enclosingScope);
+
+        if (!binding)
+            return;
+    }
+
+    const Identifier *funcId = functionName->identifier();
+    if (!funcId) // E.g. operator, which we might be able to handle in the future...
+        return;
+
+    foreach (Symbol *s, binding->symbols()) {
+        Scope *scope = s->asScope();
+        if (!scope)
+            continue;
+
+        for (Symbol *s = scope->find(funcId); s; s = s->next()) {
+            if (! s->name())
+                continue;
+            else if (! funcId->isEqualTo(s->identifier()))
+                continue;
+            else if (! s->type()->isFunctionType())
+                continue;
+            else if (Declaration *decl = s->asDeclaration()) {
+                if (Function *declFunTy = decl->type()->asFunctionType()) {
+                    if (functionType->isEqualTo(declFunTy))
+                        typeMatch->prepend(decl);
+                    else if (functionType->argumentCount() == declFunTy->argumentCount())
+                        argumentCountMatch->prepend(decl);
+                    else
+                        nameMatch->append(decl);
+                }
+            }
+        }
+    }
+}
+
+QList<Declaration *> SymbolFinder::findMatchingDeclaration(const LookupContext &context,
+                                                           Function *functionType)
+{
+    QList<Declaration *> result;
+    QList<Declaration *> nameMatch, argumentCountMatch, typeMatch;
+    findMatchingDeclaration(context, functionType, &typeMatch, &argumentCountMatch, &nameMatch);
+    result.append(typeMatch);
+    result.append(argumentCountMatch);
+    result.append(nameMatch);
+    return result;
+}
+
+#include <QtCore/QThread>
+QStringList SymbolFinder::fileIterationOrder(const Snapshot &snapshot)
+{
+    if (m_filePriorityCache.isEmpty()) {
+        foreach (const Document::Ptr &doc, snapshot)
+            insert(doc->fileName());
+    } else {
+        checkCacheConsistency(snapshot);
+    }
+
+    return m_filePriorityCache.values();
+}
+
+void SymbolFinder::checkCacheConsistency(const Snapshot &snapshot)
+{
+    // We only check for "new" files, which which are in the snapshot but not in the cache.
+    // The counterpart validation for "old" files is done when one tries to access the
+    // corresponding document and notices it's now null.
+    foreach (const Document::Ptr &doc, snapshot) {
+        if (!m_fileMetaCache.contains(doc->fileName()))
+            insert(doc->fileName());
+    }
+}
+
+void SymbolFinder::clear(const QString &comparingFile)
+{
+    m_filePriorityCache.remove(computeKey(m_referenceFile, comparingFile), comparingFile);
+    m_fileMetaCache.remove(comparingFile);
+}
+
+void SymbolFinder::insert(const QString &comparingFile)
+{
+    // We want an ordering such that the documents with the most common path appear first.
+    m_filePriorityCache.insert(computeKey(m_referenceFile, comparingFile), comparingFile);
+    m_fileMetaCache.insert(comparingFile);
+}
+
+int SymbolFinder::computeKey(const QString &referenceFile, const QString &comparingFile)
+{
+    // As similar the path from the comparing file is to the path from the reference file,
+    // the smaller the key is, which is then used for sorting the map.
+    std::pair<QString::const_iterator,
+              QString::const_iterator> r = std::mismatch(referenceFile.begin(),
+                                                         referenceFile.end(),
+                                                         comparingFile.begin());
+    return referenceFile.length() - (r.first - referenceFile.begin());
+}
diff --git a/src/plugins/cpptools/symbolfinder.h b/src/plugins/cpptools/symbolfinder.h
new file mode 100644
index 0000000000000000000000000000000000000000..80330e98c68b5159c4724508140a2a769ce30fa6
--- /dev/null
+++ b/src/plugins/cpptools/symbolfinder.h
@@ -0,0 +1,55 @@
+#ifndef SYMBOLFINDER_H
+#define SYMBOLFINDER_H
+
+#include "cpptools_global.h"
+
+#include <CppDocument.h>
+#include <CPlusPlusForwardDeclarations.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+#include <QtCore/QQueue>
+#include <QtCore/QMultiMap>
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT SymbolFinder
+{
+public:
+    SymbolFinder(const QString &referenceFileName);
+    SymbolFinder(const char *referenceFileName, unsigned referenceFileLength);
+
+    CPlusPlus::Symbol *findMatchingDefinition(CPlusPlus::Symbol *symbol,
+                                              const CPlusPlus::Snapshot &snapshot,
+                                              bool strict = false);
+
+    CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration,
+                                                   const CPlusPlus::Snapshot &snapshot);
+
+    void findMatchingDeclaration(const CPlusPlus::LookupContext &context,
+                                 CPlusPlus::Function *functionType,
+                                 QList<CPlusPlus::Declaration *> *typeMatch,
+                                 QList<CPlusPlus::Declaration *> *argumentCountMatch,
+                                 QList<CPlusPlus::Declaration *> *nameMatch);
+
+    QList<CPlusPlus::Declaration *> findMatchingDeclaration(const CPlusPlus::LookupContext &context,
+                                                            CPlusPlus::Function *functionType);
+
+private:
+    QStringList fileIterationOrder(const CPlusPlus::Snapshot &snapshot);
+
+    void checkCacheConsistency(const CPlusPlus::Snapshot &snapshot);
+    void clear(const QString &comparingFile);
+    void insert(const QString &comparingFile);
+
+    static int computeKey(const QString &referenceFile, const QString &comparingFile);
+
+    QMultiMap<int, QString> m_filePriorityCache;
+    QSet<QString> m_fileMetaCache;
+    QString m_referenceFile;
+};
+
+} // namespace CppTools
+
+#endif // SYMBOLFINDER_H
+
diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp
index e63074b8ec96cc8af556a9330b68132da6195953..c5c34c014b6aabcfb6c8f0b2d455e5f09836ef95 100644
--- a/src/plugins/designer/qtcreatorintegration.cpp
+++ b/src/plugins/designer/qtcreatorintegration.cpp
@@ -42,6 +42,7 @@
 #include <cpptools/cpprefactoringchanges.h>
 #include <cpptools/cpptoolsconstants.h>
 #include <cpptools/insertionpointlocator.h>
+#include <cpptools/symbolfinder.h>
 #include <cplusplus/ModelManagerInterface.h>
 #include <cplusplus/Symbols.h>
 #include <cplusplus/Overview.h>
@@ -273,8 +274,9 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line)
 {
     if (CppModelManagerInterface *cppModelManager = CppModelManagerInterface::instance()) {
         const Snapshot snapshot = cppModelManager->snapshot();
-
-        if (Symbol *def = snapshot.findMatchingDefinition(functionDeclaration)) {
+        CppTools::SymbolFinder symbolFinder(functionDeclaration->fileName(),
+                                            functionDeclaration->fileNameLength());
+        if (Symbol *def = symbolFinder.findMatchingDefinition(functionDeclaration, snapshot)) {
             if (line)
                 *line = def->line();