diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 31d75c346f7165de3aaa6d8e6029aa1d483ae71c..7b79b0ac16d2c2ac16acdebf8aaefa52ad307c86 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -458,3 +458,30 @@ bool FindUsages::visit(SimpleDeclarationAST *)
 
 void FindUsages::endVisit(SimpleDeclarationAST *)
 { --_inSimpleDeclaration; }
+
+bool FindUsages::visit(ObjCSelectorWithoutArgumentsAST *ast)
+{
+    const Identifier *id = identifier(ast->name_token);
+    if (id == _id) {
+        LookupContext context = currentContext(ast);
+        const QList<Symbol *> candidates = context.resolve(ast->selector_name);
+        reportResult(ast->name_token, candidates);
+    }
+
+    return false;
+}
+
+bool FindUsages::visit(ObjCSelectorWithArgumentsAST *ast)
+{
+    for (ObjCSelectorArgumentListAST *iter = ast->selector_argument_list; iter;
+         iter = iter->next) {
+        const Identifier *id = identifier(iter->value->name_token);
+        if (id == _id) {
+            LookupContext context = currentContext(iter->value);
+            const QList<Symbol *> candidates = context.resolve(ast->selector_name);
+            reportResult(iter->value->name_token, candidates);
+        }
+    }
+
+    return false;
+}
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index 1a61cca4e6c57b1aeb168860541c6fb7b9450f75..2b066fa2fa53b7f2aaf7101c767e27f008fbd6cf 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -100,6 +100,8 @@ protected:
     virtual bool visit(FunctionDeclaratorAST *ast);
     virtual bool visit(SimpleDeclarationAST *);
     virtual void endVisit(SimpleDeclarationAST *);
+    virtual bool visit(ObjCSelectorWithoutArgumentsAST *ast);
+    virtual bool visit(ObjCSelectorWithArgumentsAST *ast);
 
 private:
     const Identifier *_id;
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 86976b03400f795c965731a6307c3e5f8f033b4a..c4fdf3518e9642f7885cab89c25b6806a463f390 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -261,9 +261,6 @@ protected:
     virtual bool visit(SimpleNameAST *ast)
     { return findMemberForToken(ast->firstToken(), ast); }
 
-    virtual bool visit(ObjCMessageArgumentDeclarationAST *ast)
-    { return findMemberForToken(ast->param_name_token, ast); }
-
     bool findMemberForToken(unsigned tokenIdx, NameAST *ast)
     {
         unsigned line, column;
@@ -1276,6 +1273,49 @@ void CPPEditor::switchDeclarationDefinition()
     }
 }
 
+static inline LookupItem skipForwardDeclarations(const QList<LookupItem> &resolvedSymbols)
+{
+    QList<LookupItem> candidates = resolvedSymbols;
+
+    LookupItem result = candidates.first();
+    const FullySpecifiedType ty = result.type().simplified();
+
+    if (ty->isForwardClassDeclarationType()) {
+        while (! candidates.isEmpty()) {
+            LookupItem r = candidates.takeFirst();
+
+            if (! r.type()->isForwardClassDeclarationType()) {
+                result = r;
+                break;
+            }
+        }
+    }
+
+    if (ty->isObjCForwardClassDeclarationType()) {
+        while (! candidates.isEmpty()) {
+            LookupItem r = candidates.takeFirst();
+
+            if (! r.type()->isObjCForwardClassDeclarationType()) {
+                result = r;
+                break;
+            }
+        }
+    }
+
+    if (ty->isObjCForwardProtocolDeclarationType()) {
+        while (! candidates.isEmpty()) {
+            LookupItem r = candidates.takeFirst();
+
+            if (! r.type()->isObjCForwardProtocolDeclarationType()) {
+                result = r;
+                break;
+            }
+        }
+    }
+
+    return result;
+}
+
 CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
                                       bool resolveTarget)
 {
@@ -1340,41 +1380,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
             typeOfExpression(expression, doc, lastSymbol);
 
     if (!resolvedSymbols.isEmpty()) {
-        LookupItem result = resolvedSymbols.first();
-        const FullySpecifiedType ty = result.type().simplified();
-
-        if (ty->isForwardClassDeclarationType()) {
-            while (! resolvedSymbols.isEmpty()) {
-                LookupItem r = resolvedSymbols.takeFirst();
-
-                if (! r.type()->isForwardClassDeclarationType()) {
-                    result = r;
-                    break;
-                }
-            }
-        }
-
-        if (ty->isObjCForwardClassDeclarationType()) {
-            while (! resolvedSymbols.isEmpty()) {
-                LookupItem r = resolvedSymbols.takeFirst();
-
-                if (! r.type()->isObjCForwardClassDeclarationType()) {
-                    result = r;
-                    break;
-                }
-            }
-        }
-
-        if (ty->isObjCForwardProtocolDeclarationType()) {
-            while (! resolvedSymbols.isEmpty()) {
-                LookupItem r = resolvedSymbols.takeFirst();
-
-                if (! r.type()->isObjCForwardProtocolDeclarationType()) {
-                    result = r;
-                    break;
-                }
-            }
-        }
+        LookupItem result = skipForwardDeclarations(resolvedSymbols);
 
         if (Symbol *symbol = result.lastVisibleSymbol()) {
             Symbol *def = 0;
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 348f9cddd72deb1362d6d72fd5c57c46d7b944ca..4504d9eadc165fbf46a3c12178791d83e7c74e6b 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -2250,13 +2250,13 @@ unsigned ObjCMessageArgumentDeclarationAST::firstToken() const
     if (type_name)
         return type_name->firstToken();
     else
-        return param_name_token;
+        return param_name->firstToken();
 }
 
 unsigned ObjCMessageArgumentDeclarationAST::lastToken() const
 {
-    if (param_name_token)
-        return param_name_token + 1;
+    if (param_name)
+        return param_name->lastToken();
     else if (type_name)
         return type_name->lastToken();
 
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index eef6ec7528bc83b3d31d67299156d2ee408eee0f..11bcaf0f1c01cee284aa5c95397e0a4bddbdf2d4 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2996,12 +2996,12 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
-class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationAST: public NameAST
+class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationAST: public AST
 {
 public:
     ObjCTypeNameAST* type_name;
     SpecifierListAST *attribute_list;
-    unsigned param_name_token;
+    SimpleNameAST *param_name;
 
 public: // annotations
     Argument *argument;
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 183cce037a6bb5b6a50a99f050debcb90eeaa80b..805e7837b7a728c64ef6e195c2ee14b7a0e5c5b1 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1466,7 +1466,8 @@ ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(Memo
     for (SpecifierListAST *iter = attribute_list, **ast_iter = &ast->attribute_list;
          iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
         *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
-    ast->param_name_token = param_name_token;
+    if (param_name)
+        ast->param_name = param_name->clone(pool);
     return ast;
 }
 
diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp
index 6992a1d1cc2f488a2dbc9459da6c2db778867e9e..7f86349551c2ce993470733c5f456e77d65dc90f 100644
--- a/src/shared/cplusplus/ASTMatcher.cpp
+++ b/src/shared/cplusplus/ASTMatcher.cpp
@@ -2459,7 +2459,10 @@ bool ASTMatcher::match(ObjCMessageArgumentDeclarationAST *node, ObjCMessageArgum
     else if (! AST::match(node->attribute_list, pattern->attribute_list, this))
         return false;
 
-    pattern->param_name_token = node->param_name_token;
+    if (! pattern->param_name)
+        pattern->param_name = node->param_name;
+    else if (! AST::match(node->param_name, pattern->param_name, this))
+        return false;
 
     return true;
 }
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 22d9bd20ded0af877a04a0e5c82f30fc1b793a64..1b9f50df58d3a06645e5c9e1f5f2de4d968870bd 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1087,6 +1087,7 @@ void ObjCMessageArgumentDeclarationAST::accept0(ASTVisitor *visitor)
     if (visitor->visit(this)) {
         accept(type_name, visitor);
         accept(attribute_list, visitor);
+        accept(param_name, visitor);
     }
     visitor->endVisit(this);
 }
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index faeac37e106dff9d837479a9473d67888f31b5be..7ad7662af319efc0ff42c891b92ea9357afad66f 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -319,18 +319,14 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
 
     const bool isQ_SLOT   = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT;
     const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL;
-#ifdef ICHECK_BUILD
-    const bool isQ_INVOKABLE = (ast->invoke_token > 0);
-#endif
+    const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE;
 
     if (isQ_SIGNAL)
         fun->setMethodKey(Function::SignalMethod);
     else if (isQ_SLOT)
         fun->setMethodKey(Function::SlotMethod);
-#ifdef ICHECK_BUILD
     else if (isQ_INVOKABLE)
-        fun->setInvokable(true);
-#endif
+        fun->setMethodKey(Function::InvokableMethod);
 
     checkFunctionArguments(fun);
 
@@ -672,10 +668,14 @@ bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
 
 bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
 {
-    if (!ast->method_prototype)
+    ObjCMethodPrototypeAST *methodProto = ast->method_prototype;
+    if (!methodProto)
+        return false;
+    ObjCSelectorAST *selector = methodProto->selector;
+    if (!selector)
         return false;
 
-    FullySpecifiedType ty = semantic()->check(ast->method_prototype, _scope);
+    FullySpecifiedType ty = semantic()->check(methodProto, _scope);
     ObjCMethod *methodTy = ty.type()->asObjCMethodType();
     if (!methodTy)
         return false;
@@ -688,15 +688,15 @@ bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
 
         symbol = methodTy;
     } else {
-        Declaration *decl = control()->newDeclaration(ast->firstToken(), methodTy->name());
+        Declaration *decl = control()->newDeclaration(selector->firstToken(), methodTy->name());
         decl->setType(methodTy);
         symbol = decl;
         symbol->setStorage(methodTy->storage());
     }
 
-    symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
-    symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
-    symbol->setVisibility(semantic()->currentVisibility());
+    symbol->setStartOffset(tokenAt(selector->firstToken()).offset);
+    symbol->setEndOffset(tokenAt(selector->lastToken()).offset);
+    symbol->setVisibility(semantic()->currentObjCVisibility());
 
     _scope->enterSymbol(symbol);
 
diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp
index afee09023b43f92687c0ac912e40ed63fb6f133d..b16806139364f593b7e6f34db05bf91356a56ff3 100644
--- a/src/shared/cplusplus/CheckDeclarator.cpp
+++ b/src/shared/cplusplus/CheckDeclarator.cpp
@@ -259,7 +259,7 @@ bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast)
 
     FullySpecifiedType returnType = semantic()->check(ast->type_name, _scope);
 
-    unsigned location = ast->firstToken();
+    unsigned location = ast->selector->firstToken();
 
     semantic()->check(ast->selector, _scope);
 
diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp
index 26fa9c21ee1a7b4180016f54a2c28d4278a32ba6..98b5adea253fef3361805974cbe266d8d9dcd405 100644
--- a/src/shared/cplusplus/CheckName.cpp
+++ b/src/shared/cplusplus/CheckName.cpp
@@ -418,12 +418,11 @@ bool CheckName::visit(ObjCMessageArgumentDeclarationAST *ast)
     if (ast->type_name)
         type = semantic()->check(ast->type_name, _scope);
 
-    if (ast->param_name_token) {
-        const Identifier *id = identifier(ast->param_name_token);
-        _name = control()->nameId(id);
-        ast->name = _name;
+    if (ast->param_name) {
+        accept(ast->param_name);
 
-        Argument *arg = control()->newArgument(ast->param_name_token, _name);
+        Argument *arg = control()->newArgument(ast->param_name->firstToken(),
+                                               ast->param_name->name);
         ast->argument = arg;
         arg->setType(type);
         arg->setInitializer(0);
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 60828aa6fe5640d651493a6916cbbc7794e7d1ea..86fb18dd2c3bb66e97901929f715ff0fa3a9eb2a 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -5269,7 +5269,8 @@ bool Parser::parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, Obj
     while (parseAttributeSpecifier(*attr))
         attr = &(*attr)->next;
 
-    match(T_IDENTIFIER, &node->param_name_token);
+    node->param_name = new (_pool) SimpleNameAST;
+    match(T_IDENTIFIER, &node->param_name->identifier_token);
 
     return true;
 }