diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 08fcb2fa9d0912643ce54c438933d49c6df47993..51a3c1ac34899523dc50593dd570c0f4abe65c1c 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -2258,4 +2258,62 @@ unsigned ObjCPropertyDeclarationAST::lastToken() const
         return property_token + 1;
 }
 
+unsigned ObjCMessageArgumentDeclarationAST::firstToken() const
+{
+    return param_selector_token;
+}
+
+unsigned ObjCMessageArgumentDeclarationAST::lastToken() const
+{
+    if (param_name_token)
+        return param_name_token + 1;
+    else if (colon_token)
+        return colon_token + 1;
+    else if (type_name)
+        return type_name->lastToken();
+    else if (attributes)
+        return attributes->lastToken();
+    else
+        return param_name_token + 1;
+}
+
+unsigned ObjCMessageArgumentDeclarationListAST::firstToken() const
+{
+    if (argument_declaration)
+        return argument_declaration->firstToken();
+    else if (next)
+        return next->firstToken();
+    else
+        // ### Assert?
+        return 0;
+}
+
+unsigned ObjCMessageArgumentDeclarationListAST::lastToken() const
+{
+    for (const ObjCMessageArgumentDeclarationListAST *it = this; it; it = it->next) {
+        if (! it->next && it->argument_declaration) {
+            return it->argument_declaration->lastToken();
+        }
+    }
+    // ### assert?
+    return 0;
+}
+
+unsigned ObjCMethodPrototypeAST::firstToken() const
+{
+    return method_type_token;
+}
+
+unsigned ObjCMethodPrototypeAST::lastToken() const
+{
+    if (attributes)
+        return attributes->lastToken();
+    else if (arguments)
+        return arguments->lastToken();
+    else if (type_name)
+        return type_name->lastToken();
+    else
+        return method_type_token + 1;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 6fef4cafef415c241f2e67f8ebf5e5282a155f52..898fd16c87df3c8c771e2cba744fb7190fb2bf11 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2820,6 +2820,68 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
+class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationAST: public AST
+{
+public:
+    unsigned param_selector_token;
+    unsigned colon_token;
+    ObjCTypeNameAST* type_name;
+    SpecifierAST *attributes;
+    unsigned param_name_token;
+
+public:
+    virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMessageArgumentDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationListAST: public AST
+{
+public:
+    ObjCMessageArgumentDeclarationAST *argument_declaration;
+    ObjCMessageArgumentDeclarationListAST *next;
+
+public:
+    virtual ObjCMessageArgumentDeclarationListAST *asObjCMessageArgumentDeclarationList()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMessageArgumentDeclarationListAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCMethodPrototypeAST: public DeclarationAST
+{
+public:
+    unsigned method_type_token;
+    ObjCTypeNameAST *type_name;
+    ObjCMessageArgumentDeclarationListAST *arguments;
+    SpecifierAST *attributes;
+
+public:
+    virtual ObjCMethodPrototypeAST *asObjCMethodPrototype()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMethodPrototypeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
 
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 2a95a1c0f347e3a06b8c71ac7d77ac598bc2d923..385958d47c6a11441f07427afe356e78b86912ff 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1390,4 +1390,33 @@ ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool)
     return ast;
 }
 
+ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCMessageArgumentDeclarationAST *ast = new (pool) ObjCMessageArgumentDeclarationAST;
+    ast->param_selector_token = param_selector_token;
+    ast->colon_token = colon_token;
+    if (type_name) ast->type_name = type_name->clone(pool);
+    if (attributes) ast->attributes = attributes->clone(pool);
+    ast->param_name_token = param_name_token;
+    return ast;
+}
+
+ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::clone(MemoryPool *pool) const
+{
+    ObjCMessageArgumentDeclarationListAST *ast = new (pool) ObjCMessageArgumentDeclarationListAST;
+    if (argument_declaration) ast->argument_declaration = argument_declaration->clone(pool);
+    if (next) ast->next = next->clone(pool);
+    return ast;
+}
+
+ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
+{
+    ObjCMethodPrototypeAST *ast = new (pool) ObjCMethodPrototypeAST;
+    ast->method_type_token = method_type_token;
+    if (type_name) ast->type_name = type_name->clone(pool);
+    if (arguments) ast->arguments = arguments->clone(pool);
+    if (attributes) ast->attributes = attributes->clone(pool);
+    return ast;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index d5238f52a63aa3f0af5e3ee8bc2ad16a121d97cf..b6b21ad357191a57f5a69fad1a5523b3cf8c67f5 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1309,8 +1309,6 @@ void ObjcPropertyAttributeListAST::accept0(ASTVisitor *visitor)
         // visit ObjcPropertyAttributeListAST
         if (attr)
             accept(attr, visitor);
-        if (next)
-            accept(next, visitor);
         // visit AST
     }
     visitor->endVisit(this);
@@ -1320,8 +1318,8 @@ void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCPropertyDeclarationAST:
-        if (property_attributes)
-            accept(property_attributes, visitor);
+        for (ObjcPropertyAttributeListAST *it = property_attributes; it; it = it->next)
+            accept(it, visitor);
         if (simple_declaration)
             accept(simple_declaration, visitor);
         // visit DeclarationAST:
@@ -1329,4 +1327,43 @@ void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void ObjCMessageArgumentDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCMessageArgumentDeclarationAST
+        if (type_name)
+            accept(type_name, visitor);
+        if (attributes)
+            accept(attributes, visitor);
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMessageArgumentDeclarationListAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCMessageArgumentDeclarationListAST
+        if (argument_declaration)
+            accept(argument_declaration, visitor);
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMethodPrototypeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCMethodPrototypeAST
+        if (type_name)
+            accept(type_name, visitor);
+        for (ObjCMessageArgumentDeclarationListAST *it = arguments; it; it = it->next)
+            accept(it, visitor);
+        if (attributes)
+            accept(attributes, visitor);
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index 0e056324c22d5d77a601662a54b3a1bb2c0edaa7..b272c7077a9bc15ce275cf39ad9ba0befcc9eeba 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -214,6 +214,9 @@ public:
     virtual bool visit(ObjcPropertyAttributeAST *) { return true; }
     virtual bool visit(ObjcPropertyAttributeListAST *) { return true; }
     virtual bool visit(ObjCPropertyDeclarationAST *) { return true; }
+    virtual bool visit(ObjCMethodPrototypeAST *) { return true; }
+    virtual bool visit(ObjCMessageArgumentDeclarationListAST *) { return true; }
+    virtual bool visit(ObjCMessageArgumentDeclarationAST *) { return true; }
 
     virtual bool visit(DeclarationListAST *) { return true; }
     virtual void endVisit(DeclarationListAST *) { }
@@ -339,6 +342,9 @@ public:
     virtual void endVisit(ObjcPropertyAttributeAST *) { }
     virtual void endVisit(ObjcPropertyAttributeListAST *) { }
     virtual void endVisit(ObjCPropertyDeclarationAST *) { }
+    virtual void endVisit(ObjCMethodPrototypeAST *) { }
+    virtual void endVisit(ObjCMessageArgumentDeclarationListAST *) { }
+    virtual void endVisit(ObjCMessageArgumentDeclarationAST *) { }
 
 private:
     Control *_control;
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index 91564058e215315a7627eefffe74898bfd758b93..f123e736897b5a170cb65b93200f31464780cbdf 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -187,6 +187,9 @@ class ObjCVisibilityDeclarationAST;
 class ObjCPropertyDeclarationAST;
 class ObjcPropertyAttributeListAST;
 class ObjcPropertyAttributeAST;
+class ObjCMethodPrototypeAST;
+class ObjCMessageArgumentDeclarationListAST;
+class ObjCMessageArgumentDeclarationAST;
 
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 09271cc773617aab25aa1cf1d6e4233b98a7d7ec..b75c10d9ddca4e63e769543d202dd80e5b04f813 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -4195,7 +4195,8 @@ bool Parser::parseObjCMethodDefinitionList()
 
 bool Parser::parseObjCMethodDefinition()
 {
-    if (! parseObjCMethodPrototype())
+    DeclarationAST *ast = 0;
+    if (! parseObjCMethodPrototype(ast))
         return false;
 
     if (LA() == T_SEMICOLON)
@@ -4298,7 +4299,7 @@ bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node)
 
     case T_PLUS:
     case T_MINUS:
-        return parseObjCMethodPrototype();
+        return parseObjCMethodPrototype(node);
 
     case T_ENUM:
     case T_CLASS:
@@ -4377,22 +4378,31 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *)
 // objc-method-decl ::= objc-type-name? objc-selector
 // objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt
 //
-bool Parser::parseObjCMethodPrototype()
+bool Parser::parseObjCMethodPrototype(DeclarationAST *&node)
 {
     if (LA() != T_PLUS && LA() != T_MINUS)
         return false;
 
-    /*unsigned method_type_token = */ consumeToken();
+    ObjCMethodPrototypeAST *ast = new (_pool) ObjCMethodPrototypeAST;
+    ast->method_type_token = consumeToken();
 
-    ObjCTypeNameAST *type_name = 0;
-    parseObjCTypeName(type_name);
-
-    unsigned selector_token = 0;
+    parseObjCTypeName(ast->type_name);
 
     if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) {
-        while (parseObjCKeywordDeclaration()) {
+        ObjCMessageArgumentDeclarationAST *declaration = 0;
+        parseObjCKeywordDeclaration(declaration);
+
+        ast->arguments = new (_pool) ObjCMessageArgumentDeclarationListAST;
+        ast->arguments->argument_declaration = declaration;
+        ObjCMessageArgumentDeclarationListAST **last = &(ast->arguments);
+
+        while (parseObjCKeywordDeclaration(declaration)) {
+            (*last)->next = new (_pool) ObjCMessageArgumentDeclarationListAST;
+            last = &((*last)->next);
+            (*last)->argument_declaration = declaration;
         }
 
+        // TODO: err, what does this parse?
         while (LA() == T_COMMA) {
             consumeToken();
 
@@ -4405,15 +4415,18 @@ bool Parser::parseObjCMethodPrototype()
             parseParameterDeclaration(parameter_declaration);
         }
     } else if (lookAtObjCSelector()) {
-        parseObjCSelector(selector_token);
+        ast->arguments = new (_pool) ObjCMessageArgumentDeclarationListAST;
+        ast->arguments->argument_declaration = new (_pool) ObjCMessageArgumentDeclarationAST;
+        parseObjCSelector(ast->arguments->argument_declaration->param_selector_token);
     } else {
         _translationUnit->error(cursor(), "expected a selector");
     }
 
-    SpecifierAST *attributes = 0, **attr = &attributes;
+    SpecifierAST **attr = &(ast->attributes);
     while (parseAttributeSpecifier(*attr))
         attr = &(*attr)->next;
 
+    node = ast;
     return true;
 }
 
@@ -4471,27 +4484,24 @@ bool Parser::parseObjCSelector(unsigned &selector_token)
 
 // objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER
 //
-bool Parser::parseObjCKeywordDeclaration()
+bool Parser::parseObjCKeywordDeclaration(ObjCMessageArgumentDeclarationAST *&node)
 {
     if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON)))
         return false;
 
-    unsigned selector_token = 0;
-    parseObjCSelector(selector_token);
-
-    unsigned colon_token = 0;
-    match(T_COLON, &colon_token);
+    ObjCMessageArgumentDeclarationAST *ast = new (_pool) ObjCMessageArgumentDeclarationAST;
 
-    ObjCTypeNameAST *type_name = 0;
-    parseObjCTypeName(type_name);
+    parseObjCSelector(ast->param_selector_token);
+    match(T_COLON, &(ast->colon_token));
+    parseObjCTypeName(ast->type_name);
 
-    SpecifierAST *attributes = 0, **attr = &attributes;
+    SpecifierAST **attr = &(ast->attributes);
     while (parseAttributeSpecifier(*attr))
         attr = &(*attr)->next;
 
-    unsigned identifier_token = 0;
-    match(T_IDENTIFIER, &identifier_token);
+    match(T_IDENTIFIER, &(ast->param_name_token));
 
+    node = ast;
     return true;
 }
 
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index d292c5b935138f603f76f00a1605a014f61b2698..d29749834442873802825806d6d115c7a8e8c3bc 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -238,11 +238,11 @@ public:
     bool parseObjCPropertyDeclaration(DeclarationAST *&node,
                                       SpecifierAST *attributes = 0);
     bool parseObjCImplementation(DeclarationAST *&node);
-    bool parseObjCMethodPrototype();
+    bool parseObjCMethodPrototype(DeclarationAST *&node);
     bool parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node);
     bool parseObjCTypeName(ObjCTypeNameAST *&node);
     bool parseObjCSelector(unsigned &selector_token);
-    bool parseObjCKeywordDeclaration();
+    bool parseObjCKeywordDeclaration(ObjCMessageArgumentDeclarationAST *&node);
     bool parseObjCTypeQualifiers(unsigned &type_qualifier);
     bool parseObjCEnd(DeclarationAST *&node);