diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 8383beef3bbcf131976ba9592bb75f1e1e21d417..6af10cf7614ee222dcc1897368c0ae20558d1547 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -42,6 +42,9 @@
 #include <AST.h>
 #include <Scope.h>
 #include <SymbolVisitor.h>
+#include <NameVisitor.h>
+#include <TypeVisitor.h>
+#include <CoreTypes.h>
 
 #include <QtCore/QByteArray>
 #include <QtCore/QBitArray>
@@ -789,9 +792,8 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
             Function *best = 0;
 
             foreach (Function *fun, viableFunctions) {
-                if (fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName()))
+                if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())))
                     continue;
-
                 else if (fun->argumentCount() == declarationTy->argumentCount()) {
                     if (! best)
                         best = fun;
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 13547593ca15cb27033b08116c6a54805c02863c..965d399d3e743e94165c39f1384aa72cb63dc3e0 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -75,7 +75,8 @@ ResolveExpression::ResolveExpression(const LookupContext &context)
     : ASTVisitor(context.expressionDocument()->translationUnit()),
       _scope(0),
       _context(context),
-      bind(context.expressionDocument()->translationUnit())
+      bind(context.expressionDocument()->translationUnit()),
+      _reference(false)
 { }
 
 ResolveExpression::~ResolveExpression()
@@ -84,19 +85,26 @@ ResolveExpression::~ResolveExpression()
 QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope)
 { return resolve(ast, scope); }
 
-QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope)
+QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope)
+{ return resolve(ast, scope, true); }
+
+QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref)
 {
     if (! scope)
         return QList<LookupItem>();
 
-    Scope *previousVisibleSymbol = _scope;
-    _scope = scope;
-    const QList<LookupItem> result = resolve(ast);
-    _scope = previousVisibleSymbol;
+    std::swap(_scope, scope);
+    std::swap(_reference, ref);
+
+    const QList<LookupItem> result = expression(ast);
+
+    std::swap(_reference, ref);
+    std::swap(_scope, scope);
+
     return result;
 }
 
-QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast)
+QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast)
 {
     const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
     accept(ast);
@@ -441,27 +449,18 @@ bool ResolveExpression::visit(ConversionFunctionIdAST *)
     return false;
 }
 
-bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const
+bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount)
 {
-    unsigned minNumberArguments = 0;
-
-    for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) {
-        Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument();
-
-        if (arg->hasInitializer())
-            break;
-    }
-
-    if (actualArgumentCount < minNumberArguments) {
-        // not enough arguments.
-        return false;
-
-    } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) {
-        // too many arguments.
-        return false;
-    }
+    return funTy->maybeValidPrototype(actualArgumentCount);
+}
 
-    return true;
+bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
+{
+    if (sourceTy.isEqualTo(targetTy))
+        return true;
+    else if (sourceTy.simplified().isEqualTo(targetTy.simplified()))
+        return true;
+    return false;
 }
 
 bool ResolveExpression::visit(CallAST *ast)
@@ -469,14 +468,55 @@ bool ResolveExpression::visit(CallAST *ast)
     const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
 
     // Compute the types of the actual arguments.
-    int actualArgumentCount = 0;
+    unsigned actualArgumentCount = 0;
 
-    //QList< QList<Result> > arguments;
+    QList< QList<LookupItem> > arguments;
     for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
-        //arguments.append(resolve(exprIt->expression));
+        if (_reference)
+            arguments.append(resolve(exprIt->value, _scope));
+
         ++actualArgumentCount;
     }
 
+    if (_reference) {
+        _results.clear();
+        foreach (const LookupItem &base, baseResults) {
+            if (Function *funTy = base.type()->asFunctionType()) {
+                if (! maybeValidPrototype(funTy, actualArgumentCount))
+                    continue;
+
+                int score = 0;
+
+                for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
+                    const FullySpecifiedType formalTy = funTy->argumentAt(i)->type();
+
+                    FullySpecifiedType actualTy;
+                    if (i < unsigned(arguments.size())) {
+                        const QList<LookupItem> actual = arguments.at(i);
+                        if (actual.isEmpty())
+                            continue;
+
+                        actualTy = actual.first().type();
+                    } else
+                        actualTy = formalTy;
+
+                    if (implicitConversion(actualTy, formalTy))
+                        ++score;
+                }
+
+                if (score)
+                    _results.prepend(base);
+                else
+                    _results.append(base);
+            }
+        }
+
+        if (_results.isEmpty())
+            _results = baseResults;
+
+        return false;
+    }
+
     const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
 
     foreach (const LookupItem &result, baseResults) {
@@ -513,7 +553,7 @@ bool ResolveExpression::visit(CallAST *ast)
 bool ResolveExpression::visit(ArrayAccessAST *ast)
 {
     const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
-    const QList<LookupItem> indexResults = resolve(ast->expression);
+    const QList<LookupItem> indexResults = resolve(ast->expression, _scope);
 
     const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
 
@@ -709,7 +749,7 @@ bool ResolveExpression::visit(PostIncrDecrAST *ast)
 
 bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
 {
-    const QList<LookupItem> receiverResults = resolve(ast->receiver_expression);
+    const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
 
     foreach (const LookupItem &result, receiverResults) {
         FullySpecifiedType ty = result.type().simplified();
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index de42964176aa981c0136cb73fbc302cf6330b8f9..70fad7ef3e686d5405dddbf9d9c3d9fa4488fcd1 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -45,7 +45,8 @@ public:
     virtual ~ResolveExpression();
 
     QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope);
-    QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope);
+    QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
+    QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
 
     ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
                                      int accessOp,
@@ -56,7 +57,7 @@ public:
 protected:
     ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope) const;
 
-    QList<LookupItem> resolve(ExpressionAST *ast);
+    QList<LookupItem> expression(ExpressionAST *ast);
 
     QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
     FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
@@ -69,7 +70,8 @@ protected:
     void addResults(const QList<Symbol *> &symbols);
     void addResults(const QList<LookupItem> &items);
 
-    bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
+    static bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount);
+    bool implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const;
 
     using ASTVisitor::visit;
 
@@ -119,6 +121,7 @@ private:
     LookupContext _context;
     Bind bind;
     QList<LookupItem> _results;
+    bool _reference;
 };
 
 } // end of namespace CPlusPlus
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index 2177cdd9306712ab63f36f6b4c9ed520f9ad3bdf..1a0d84bd0576f7a9ebcee734e526cef3dcccfcdc 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -84,6 +84,20 @@ QList<LookupItem> TypeOfExpression::operator()(const QString &expression,
                              scope);
 }
 
+QList<LookupItem> TypeOfExpression::reference(const QString &expression,
+                                              Scope *scope,
+                                              PreprocessMode mode)
+{
+    QString code = expression;
+
+    if (mode == Preprocess)
+        code = preprocessedExpression(expression);
+
+    Document::Ptr expressionDoc = documentForExpression(code);
+    expressionDoc->check();
+    return reference(extractExpressionAST(expressionDoc), expressionDoc, scope);
+}
+
 QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
                                                Document::Ptr document,
                                                Scope *scope)
@@ -104,6 +118,26 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
     return items;
 }
 
+QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
+                                              Document::Ptr document,
+                                              Scope *scope)
+{
+    m_ast = expression;
+
+    m_scope = scope;
+
+    m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
+    m_lookupContext.setBindings(m_bindings);
+
+    ResolveExpression resolve(m_lookupContext);
+    const QList<LookupItem> items = resolve.reference(m_ast, scope);
+
+    if (! m_bindings)
+        m_lookupContext = resolve.context();
+
+    return items;
+}
+
 QString TypeOfExpression::preprocess(const QString &expression) const
 {
     return preprocessedExpression(expression);
@@ -179,3 +213,4 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression) cons
     const QByteArray preprocessedCode = preproc("<expression>", code);
     return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size());
 }
+
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index c1ab1288aac582cdc1e340e604b0837c5962a0e6..bb28c6f938114ea630f8eeb1b48e14de17c1f343 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -98,6 +98,14 @@ public:
                                  Document::Ptr document,
                                  Scope *scope);
 
+    QList<LookupItem> reference(const QString &expression,
+                                Scope *scope,
+                                PreprocessMode mode = NoPreprocess);
+
+    QList<LookupItem> reference(ExpressionAST *expression,
+                                Document::Ptr document,
+                                Scope *scope);
+
     QString preprocess(const QString &expression) const;
 
     /**
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 10672b0e8dceabeca07853bc896be05dfd319930..f80b61291f4b8912000d2ee35b4c5128d2298f45 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -76,6 +76,7 @@
 #include <extensionsystem/pluginmanager.h>
 #include <projectexplorer/projectexplorerconstants.h>
 #include <texteditor/basetextdocument.h>
+#include <texteditor/basetextdocumentlayout.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/tabsettings.h>
 #include <texteditor/texteditorconstants.h>
@@ -1265,6 +1266,13 @@ CPPEditor::Link CPPEditor::attemptFuncDeclDef(const QTextCursor &cursor, const D
             return result;
     }
 
+    for (int i = path.size() - 1; i != -1; --i) {
+        AST *node = path.at(i);
+
+        if (node->asParameterDeclaration() != 0)
+            return result;
+    }
+
     AST *declParent = 0;
     DeclaratorAST *decl = 0;
     for (int i = path.size() - 2; i > 0; --i) {
@@ -1431,11 +1439,27 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
 
     // Evaluate the type of the expression under the cursor
     ExpressionUnderCursor expressionUnderCursor;
-    const QString expression = expressionUnderCursor(tc);
+    QString expression = expressionUnderCursor(tc);
+
+    for (int pos = tc.position();; ++pos) {
+        const QChar ch = characterAt(pos);
+        if (ch.isSpace())
+            continue;
+        else {
+            if (ch == QLatin1Char('(') && ! expression.isEmpty()) {
+                tc.setPosition(pos);
+                if (TextEditor::TextBlockUserData::findNextClosingParenthesis(&tc, true)) {
+                    expression.append(tc.selectedText());
+                }
+            }
+
+            break;
+        }
+    }
 
     TypeOfExpression typeOfExpression;
     typeOfExpression.init(doc, snapshot);
-    const QList<LookupItem> resolvedSymbols = typeOfExpression(expression, scope, TypeOfExpression::Preprocess);
+    const QList<LookupItem> resolvedSymbols = typeOfExpression.reference(expression, scope, TypeOfExpression::Preprocess);
 
     if (!resolvedSymbols.isEmpty()) {
         LookupItem result = skipForwardDeclarations(resolvedSymbols);
@@ -1473,16 +1497,6 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
             link.begin = beginOfToken;
             link.end = endOfToken;
             return link;
-
-        // This would jump to the type of a name
-#if 0
-        } else if (NamedType *namedType = firstType->asNamedType()) {
-            QList<Symbol *> candidates = context.resolve(namedType->name());
-            if (!candidates.isEmpty()) {
-                Symbol *s = candidates.takeFirst();
-                openCppEditorAt(s->fileName(), s->line(), s->column());
-            }
-#endif
         }
     } else {
         // Handle macro uses
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 4cfd8de6368b8d04890add40659075f7470c0f2f..d36e8b809f70d24047238c6bd42302cb7ad39a6a 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -759,6 +759,22 @@ const Identifier *Control::objcCopyId() const
 const Identifier *Control::objcNonatomicId() const
 { return d->objcNonatomicId; }
 
+Symbol **Control::firstSymbol() const
+{
+    if (d->symbols.empty())
+        return 0;
+
+    return &*d->symbols.begin();
+}
+
+Symbol **Control::lastSymbol() const
+{
+    if (d->symbols.empty())
+        return 0;
+
+    return &*d->symbols.begin() + d->symbols.size();
+}
+
 bool Control::hasSymbol(Symbol *symbol) const
 {
     return std::find(d->symbols.begin(), d->symbols.end(), symbol) != d->symbols.end();
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index e475a17567ce49a138e228b591cc0808c2c012db..461c6453f6a72969dc5a165d6b7cc8962a855a21 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -212,6 +212,9 @@ public:
     const NumericLiteral *numericLiteral(const char *chars, unsigned size);
     const NumericLiteral *numericLiteral(const char *chars);
 
+    Symbol **firstSymbol() const;
+    Symbol **lastSymbol() const;
+
     bool hasSymbol(Symbol *symbol) const;
 
     void squeeze();
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 0bb231e79688c460708494078e257a8f2522523d..d2b402ea5f9e60b72583612c10b56c775c844ae4 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -362,6 +362,30 @@ void Function::visitSymbol0(SymbolVisitor *visitor)
     }
 }
 
+bool Function::maybeValidPrototype(unsigned actualArgumentCount) const
+{
+    unsigned minNumberArguments = 0;
+
+    for (; minNumberArguments < this->argumentCount(); ++minNumberArguments) {
+        Argument *arg = this->argumentAt(minNumberArguments)->asArgument();
+
+        if (arg->hasInitializer())
+            break;
+    }
+
+    if (actualArgumentCount < minNumberArguments) {
+        // not enough arguments.
+        return false;
+
+    } else if (! this->isVariadic() && actualArgumentCount > this->argumentCount()) {
+        // too many arguments.
+        return false;
+    }
+
+    return true;
+}
+
+
 Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
     : Scope(translationUnit, sourceLocation, /*name = */ 0)
 { }
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index cd618a9c876cee6f54b9e71854b002b1ae79a58c..f27502796aa7ead84d0c257f97003e638ca4ad24 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -350,6 +350,8 @@ public:
     bool isAmbiguous() const; // internal
     void setAmbiguous(bool isAmbiguous); // internal
 
+    bool maybeValidPrototype(unsigned actualArgumentCount) const;
+
 protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
     virtual void accept0(TypeVisitor *visitor);