diff --git a/src/libs/cplusplus/NamePrettyPrinter.cpp b/src/libs/cplusplus/NamePrettyPrinter.cpp
index 75aa582cded3d691f0556857eee74a9cc2e4393f..788c418c09ab0401f43eac2630570eeb5e4ce1ab 100644
--- a/src/libs/cplusplus/NamePrettyPrinter.cpp
+++ b/src/libs/cplusplus/NamePrettyPrinter.cpp
@@ -253,3 +253,20 @@ void NamePrettyPrinter::visit(QualifiedNameId *name)
         _name += operator()(name->nameAt(index));
     }
 }
+
+void NamePrettyPrinter::visit(SelectorNameId *name)
+{
+    for (unsigned i = 0; i < name->nameCount(); ++i) {
+        Name *n = name->nameAt(i);
+        if (!n)
+            continue;
+
+        Identifier *id = n->identifier();
+        if (id) {
+            _name += QString::fromLatin1(id->chars(), id->size());
+
+            if (name->hasArguments() || name->nameCount() > 1)
+                _name += ':';
+        }
+    }
+}
diff --git a/src/libs/cplusplus/NamePrettyPrinter.h b/src/libs/cplusplus/NamePrettyPrinter.h
index 2e0ef2c9b1c2129a20c1f296908664e13145d610..6704099009c61356f2c3dd1072a74a2448c376cd 100644
--- a/src/libs/cplusplus/NamePrettyPrinter.h
+++ b/src/libs/cplusplus/NamePrettyPrinter.h
@@ -55,6 +55,7 @@ protected:
     virtual void visit(OperatorNameId *name);
     virtual void visit(ConversionNameId *name);
     virtual void visit(QualifiedNameId *name);
+    virtual void visit(SelectorNameId *name);
 
 private:
     const Overview *_overview;
diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp
index 008fb97abe9d1bbd70e3ae29368f214092429c9a..ed119824af982dae33a84e66618d7845238ffc7c 100644
--- a/src/libs/cplusplus/OverviewModel.cpp
+++ b/src/libs/cplusplus/OverviewModel.cpp
@@ -164,6 +164,12 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const
         QString name = _overview.prettyName(symbol->name());
         if (name.isEmpty())
             name = QLatin1String("anonymous");
+        if (symbol->isObjCForwardClassDeclaration())
+            name = QLatin1String("@class ") + name;
+        if (symbol->isObjCForwardProtocolDeclaration() || symbol->isObjCProtocol())
+            name = QLatin1String("@protocol ") + name;
+        if (symbol->isObjCClass())
+            name = QLatin1String("@interface ") + name;
         if (! symbol->isScopedSymbol() || symbol->isFunction()) {
             QString type = _overview.prettyType(symbol->type());
             if (! type.isEmpty()) {
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 0a16fa774ca54c413774a06f311ff0f19bbee162..cba0a7a39dc4a6ccd222125100c324e662b3554c 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -2080,6 +2080,9 @@ unsigned ObjCMessageExpressionAST::lastToken() const
     if (receiver_expression)
         return receiver_expression->lastToken();
 
+    if (selector)
+        return selector->lastToken();
+
     if (argument_list)
         return argument_list->lastToken();
 
@@ -2107,7 +2110,7 @@ unsigned ObjCMessageArgumentListAST::lastToken() const
 
 unsigned ObjCMessageArgumentAST::firstToken() const
 {
-    return parameter_key_identifier;
+    return parameter_value_expression->firstToken();
 }
 
 unsigned ObjCMessageArgumentAST::lastToken() const
@@ -2115,10 +2118,8 @@ unsigned ObjCMessageArgumentAST::lastToken() const
     if (parameter_value_expression)
         return parameter_value_expression->lastToken();
 
-    if (colon_token)
-        return colon_token + 1;
-
-    return parameter_key_identifier + 1;
+    // ### assert?
+    return 0;
 }
 
 unsigned ObjCProtocolExpressionAST::firstToken() const
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index d9e541302870ef0e9ddbe162bda77ab6289f6c22..fb84d4d0a917634fcb5aa2403441a5ce768adf98 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2644,8 +2644,6 @@ protected:
 class CPLUSPLUS_EXPORT ObjCMessageArgumentAST: public AST
 {
 public:
-    unsigned parameter_key_identifier;
-    unsigned colon_token;
     ExpressionAST *parameter_value_expression;
 
 public:
@@ -2685,6 +2683,7 @@ class CPLUSPLUS_EXPORT ObjCMessageExpressionAST: public ExpressionAST
 public:
     unsigned lbracket_token;
     ExpressionAST *receiver_expression;
+    ObjCSelectorAST *selector;
     ObjCMessageArgumentListAST *argument_list;
     unsigned rbracket_token;
 
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 1fbb5a651b143b25ba962242f5dd3b1239d14a37..87e74d9ee485201666ac7f210e3e668a37d47615 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1295,6 +1295,7 @@ ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) cons
     ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST;
     ast->lbracket_token = lbracket_token;
     if (receiver_expression) ast->receiver_expression = receiver_expression->clone(pool);
+    if (selector) ast->selector = selector->clone(pool);
     if (argument_list) ast->argument_list = argument_list->clone(pool);
     ast->rbracket_token = rbracket_token;
     return ast;
@@ -1311,8 +1312,6 @@ ObjCMessageArgumentListAST *ObjCMessageArgumentListAST::clone(MemoryPool *pool)
 ObjCMessageArgumentAST *ObjCMessageArgumentAST::clone(MemoryPool *pool) const
 {
     ObjCMessageArgumentAST *ast = new (pool) ObjCMessageArgumentAST;
-    ast->parameter_key_identifier = parameter_key_identifier;
-    ast->colon_token = colon_token;
     if (parameter_value_expression) ast->parameter_value_expression = parameter_value_expression->clone(pool);
     return ast;
 }
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index f258ac1125e36ddca551f1aa75a95f9a12913398..a76d80df6bbd5e154adb2f2f5ddeab23997eedd1 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1220,6 +1220,8 @@ void ObjCMessageExpressionAST::accept0(ASTVisitor *visitor)
         // visit ObjCMessageExpressionAST
         if (receiver_expression)
             accept(receiver_expression, visitor);
+        if (selector)
+            accept(selector, visitor);
         if (argument_list)
             accept(argument_list, visitor);
         // visit ExpressionAST
@@ -1231,10 +1233,9 @@ void ObjCMessageArgumentListAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCMessageArgumentListAST
-        if (arg)
-            accept(arg, visitor);
-        if (next)
-            accept(next, visitor);
+        for (ObjCMessageArgumentListAST *it = this; it; it = it->next)
+            if (it->arg)
+                accept(it->arg, visitor);
         // visit AST
     }
     visitor->endVisit(this);
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index 76ee3061dc577f116fd6f86f236a89de3d9fa792..e85dda262f75e53246ab60ae45987cb12fea816c 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -100,6 +100,7 @@ class DestructorNameId;
 class OperatorNameId;
 class ConversionNameId;
 class QualifiedNameId;
+class SelectorNameId;
 
 // types
 class FullySpecifiedType;
@@ -138,6 +139,7 @@ class ObjCClass;
 class ObjCForwardClassDeclaration;
 class ObjCProtocol;
 class ObjCForwardProtocolDeclaration;
+class ObjCMethod;
 
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 1a9877db156770919744b25d8899316818ee9d66..f3157e7bc673b5d3a802a337e2673b09119bf87e 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -598,6 +598,36 @@ bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast)
     return false;
 }
 
+bool CheckDeclaration::visit(ObjCMethodDefinitionAST *ast)
+{
+    if (!ast->method_prototype)
+        return false;
+
+    FullySpecifiedType ty = semantic()->check(ast->method_prototype, _scope);
+    Function *fun = ty.type()->asFunctionType();
+    if (!fun)
+        return false;
+
+    Declaration *symbol = control()->newDeclaration(ast->firstToken(), fun->name());
+    symbol->setStartOffset(tokenAt(ast->firstToken()).offset);
+    symbol->setEndOffset(tokenAt(ast->lastToken()).offset);
+
+    symbol->setType(fun->returnType());
+
+    symbol->setVisibility(semantic()->currentVisibility());
+
+    if (semantic()->isObjCClassMethod(ast->method_prototype->method_type_token))
+        symbol->setStorage(Symbol::Static);
+
+    _scope->enterSymbol(symbol);
+
+     if (! semantic()->skipFunctionBodies()) {
+        semantic()->check(ast->function_body, fun->members());
+    }
+
+    return false;
+}
+
 bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
 {
     int accessSpecifier = tokenKind(ast->visibility_token);
diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h
index 97c4d5ff449021aa30d173faf2e8b59b417cf540..b1880c5377f405ed2c9446f647c294655e113be2 100644
--- a/src/shared/cplusplus/CheckDeclaration.h
+++ b/src/shared/cplusplus/CheckDeclaration.h
@@ -96,6 +96,7 @@ protected:
     virtual bool visit(ObjCClassDeclarationAST *ast);
     virtual bool visit(ObjCClassInterfaceDefinitionAST *ast);
     virtual bool visit(ObjCMethodDeclarationAST *ast);
+    virtual bool visit(ObjCMethodDefinitionAST *ast);
     virtual bool visit(ObjCVisibilityDeclarationAST *ast);
 
 private:
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index 25cfe8ba43a70c5eeed90528879fda5614be4570..ac93a1a9de0c2603c11a9d48c35274728e8c7620 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -383,4 +383,29 @@ bool CheckExpression::visit(MemberAccessAST *ast)
     return false;
 }
 
+bool CheckExpression::visit(ObjCMessageExpressionAST *ast)
+{
+    semantic()->check(ast->receiver_expression, _scope);
+
+    if (Name *name = semantic()->check(ast->selector, _scope))
+        _scope->addUse(ast->selector->firstToken(), name);
+
+    accept(ast->argument_list);
+    return false;
+}
+
+bool CheckExpression::visit(ObjCEncodeExpressionAST * /*ast*/)
+{
+    // TODO: visit the type name, but store the type here? (EV)
+    return true;
+}
+
+bool CheckExpression::visit(ObjCSelectorExpressionAST *ast)
+{
+    if (Name *name = semantic()->check(ast->selector, _scope))
+        _scope->addUse(ast->selector->firstToken(), name);
+
+    return false;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h
index dad53ed3b76abda3ff36c8b17ff1d28a5ea5108e..41c3393d7ae9e1279018dea938c525a63f9b0277 100644
--- a/src/shared/cplusplus/CheckExpression.h
+++ b/src/shared/cplusplus/CheckExpression.h
@@ -110,6 +110,11 @@ protected:
     virtual bool visit(PostIncrDecrAST *ast);
     virtual bool visit(MemberAccessAST *ast);
 
+    // ObjC
+    virtual bool visit(ObjCMessageExpressionAST *ast);
+    virtual bool visit(ObjCEncodeExpressionAST *ast);
+    virtual bool visit(ObjCSelectorExpressionAST *ast);
+
 private:
     ExpressionAST *_expression;
     FullySpecifiedType _fullySpecifiedType;
diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp
index 48ab067f03b8ebdfd662eaa2a6126bc678531421..0fad66cccf97fc624d383a7c672a77f7aa94e882 100644
--- a/src/shared/cplusplus/CheckName.cpp
+++ b/src/shared/cplusplus/CheckName.cpp
@@ -376,8 +376,10 @@ bool CheckName::visit(TemplateIdAST *ast)
 
 bool CheckName::visit(ObjCSelectorWithoutArgumentsAST *ast)
 {
+    std::vector<Name *> names;
     Identifier *id = identifier(ast->name_token);
-    _name = control()->nameId(id);
+    names.push_back(control()->nameId(id));
+    _name = control()->selectorNameId(&names[0], names.size(), false);
     ast->selector_name = _name;
 
     return false;
@@ -392,7 +394,7 @@ bool CheckName::visit(ObjCSelectorWithArgumentsAST *ast)
 
         names.push_back(name);
     }
-    _name = control()->qualifiedNameId(&names[0], names.size(), false);
+    _name = control()->selectorNameId(&names[0], names.size(), true);
     ast->selector_name = _name;
 
     return false;
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 49f965f7da3caa9f38c986904a830d33f8323dcc..96a6719611969b41a52387b78905a5a083ae39b3 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -196,6 +196,15 @@ public:
         return it->second;
     }
 
+    SelectorNameId *findOrInsertSelectorNameId(const std::vector<Name *> &names, bool hasArguments)
+    {
+        const SelectorNameIdKey key(names, hasArguments);
+        std::map<SelectorNameIdKey, SelectorNameId *>::iterator it = selectorNameIds.lower_bound(key);
+        if (it == selectorNameIds.end() || it->first != key)
+            it = selectorNameIds.insert(it, std::make_pair(key, new SelectorNameId(&names[0], names.size(), hasArguments)));
+        return it->second;
+    }
+
     IntegerType *findOrInsertIntegerType(int kind)
     {
         const int key = int(kind);
@@ -423,6 +432,27 @@ public:
         }
     };
 
+    struct SelectorNameIdKey {
+        std::vector<Name *> _names;
+        bool _hasArguments;
+
+        SelectorNameIdKey(const std::vector<Name *> &names, bool hasArguments): _names(names), _hasArguments(hasArguments) {}
+
+        bool operator==(const SelectorNameIdKey &other) const
+        { return _names == other._names && _hasArguments == other._hasArguments; }
+
+        bool operator!=(const SelectorNameIdKey &other) const
+        { return !operator==(other); }
+
+        bool operator<(const SelectorNameIdKey &other) const
+        {
+            if (_hasArguments == other._hasArguments)
+                return std::lexicographical_compare(_names.begin(), _names.end(), other._names.begin(), other._names.end());
+            else
+                return _hasArguments < other._hasArguments;
+        }
+    };
+
     struct ArrayKey {
         FullySpecifiedType type;
         size_t size;
@@ -491,6 +521,7 @@ public:
     std::map<FullySpecifiedType, ConversionNameId *> conversionNameIds;
     std::map<TemplateNameIdKey, TemplateNameId *> templateNameIds;
     std::map<QualifiedNameIdKey, QualifiedNameId *> qualifiedNameIds;
+    std::map<SelectorNameIdKey, SelectorNameId *> selectorNameIds;
 
     // types
     VoidType voidType;
@@ -615,6 +646,15 @@ QualifiedNameId *Control::qualifiedNameId(Name *const *names,
     return d->findOrInsertQualifiedNameId(classOrNamespaceNames, isGlobal);
 }
 
+SelectorNameId *Control::selectorNameId(Name *const *names,
+                                        unsigned nameCount,
+                                        bool hasArguments)
+{
+    std::vector<Name *> selectorNames(names, names + nameCount);
+    return d->findOrInsertSelectorNameId(selectorNames, hasArguments);
+}
+
+
 VoidType *Control::voidType()
 { return &d->voidType; }
 
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index a9b85b7baee8d44e5c520847af7c19baa738def2..5e90e0947b9e68825f80893e78983a780c5d74ec 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -89,6 +89,10 @@ public:
                                      unsigned nameCount,
                                      bool isGlobal = false);
 
+    SelectorNameId *selectorNameId(Name *const *names,
+                                   unsigned nameCount,
+                                   bool hasArguments);
+
     /// Returns a Type object of type VoidType.
     VoidType *voidType();
 
diff --git a/src/shared/cplusplus/Name.cpp b/src/shared/cplusplus/Name.cpp
index b3c9019f7d98c1eadffd97df245fb90354f9d847..7420bd496bd7562cdc21c2e0768d971f8ac1a1e4 100644
--- a/src/shared/cplusplus/Name.cpp
+++ b/src/shared/cplusplus/Name.cpp
@@ -76,6 +76,9 @@ bool Name::isConversionNameId() const
 bool Name::isQualifiedNameId() const
 { return asQualifiedNameId() != 0; }
 
+bool Name::isSelectorNameId() const
+{ return asSelectorNameId() != 0; }
+
 void Name::accept(NameVisitor *visitor)
 {
     if (visitor->preVisit(this))
diff --git a/src/shared/cplusplus/Name.h b/src/shared/cplusplus/Name.h
index 145b3344b986279dd753fc3dc8d387c9d1768558..3604aca570a7909f981e14f2d08a1b119ad4951a 100644
--- a/src/shared/cplusplus/Name.h
+++ b/src/shared/cplusplus/Name.h
@@ -71,6 +71,7 @@ public:
     bool isOperatorNameId() const;
     bool isConversionNameId() const;
     bool isQualifiedNameId() const;
+    bool isSelectorNameId() const;
 
     virtual const NameId *asNameId() const { return 0; }
     virtual const TemplateNameId *asTemplateNameId() const { return 0; }
@@ -78,6 +79,7 @@ public:
     virtual const OperatorNameId *asOperatorNameId() const { return 0; }
     virtual const ConversionNameId *asConversionNameId() const { return 0; }
     virtual const QualifiedNameId *asQualifiedNameId() const { return 0; }
+    virtual const SelectorNameId *asSelectorNameId() const { return 0; }
 
     virtual NameId *asNameId() { return 0; }
     virtual TemplateNameId *asTemplateNameId() { return 0; }
@@ -85,6 +87,7 @@ public:
     virtual OperatorNameId *asOperatorNameId() { return 0; }
     virtual ConversionNameId *asConversionNameId() { return 0; }
     virtual QualifiedNameId *asQualifiedNameId() { return 0; }
+    virtual SelectorNameId *asSelectorNameId() { return 0; }
 
     virtual bool isEqualTo(const Name *other) const = 0;
 
diff --git a/src/shared/cplusplus/NameVisitor.h b/src/shared/cplusplus/NameVisitor.h
index 1892137563208c00a2b94914c45bc065080ebad5..16ba837d6454a1ed10f49d5b4d6e7c9ec83b247d 100644
--- a/src/shared/cplusplus/NameVisitor.h
+++ b/src/shared/cplusplus/NameVisitor.h
@@ -74,6 +74,7 @@ public:
     virtual void visit(OperatorNameId *) {}
     virtual void visit(ConversionNameId *) {}
     virtual void visit(QualifiedNameId *) {}
+    virtual void visit(SelectorNameId *) {}
 };
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Names.cpp b/src/shared/cplusplus/Names.cpp
index 3dafad910b21bb5bac3982c3da35eb266eba54e2..32762841b6fc027cfc89a4cb734e48c6c2311412 100644
--- a/src/shared/cplusplus/Names.cpp
+++ b/src/shared/cplusplus/Names.cpp
@@ -268,5 +268,62 @@ bool ConversionNameId::isEqualTo(const Name *other) const
     return _type.isEqualTo(c->type());
 }
 
+SelectorNameId::SelectorNameId(Name *const names[],
+                               unsigned nameCount,
+                               bool hasArguments)
+    : _names(0),
+      _nameCount(nameCount),
+      _hasArguments(hasArguments)
+{
+    if (_nameCount) {
+        _names = new Name *[_nameCount];
+        std::copy(&names[0], &names[nameCount], _names);
+    }
+}
+
+SelectorNameId::~SelectorNameId()
+{ delete[] _names; }
+
+void SelectorNameId::accept0(NameVisitor *visitor)
+{ visitor->visit(this); }
+
+Identifier *SelectorNameId::identifier() const
+{
+    // FIXME: (EV)
+    return nameAt(0)->identifier();
+}
+
+unsigned SelectorNameId::nameCount() const
+{ return _nameCount; }
+
+Name *SelectorNameId::nameAt(unsigned index) const
+{ return _names[index]; }
+
+Name *const *SelectorNameId::names() const
+{ return _names; }
+
+bool SelectorNameId::hasArguments() const
+{ return _hasArguments; }
+
+bool SelectorNameId::isEqualTo(const Name *other) const
+{
+    const SelectorNameId *q = other->asSelectorNameId();
+    if (! q)
+        return false;
+    else if (hasArguments() != q->hasArguments())
+        return false;
+    else {
+        const unsigned count = nameCount();
+        if (count != q->nameCount())
+            return false;
+        for (unsigned i = 0; i < count; ++i) {
+            Name *l = nameAt(i);
+            Name *r = q->nameAt(i);
+            if (! l->isEqualTo(r))
+                return false;
+        }
+    }
+    return true;
+}
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Names.h b/src/shared/cplusplus/Names.h
index c5758ba73843be7186652b8efa208dca21e2b283..b0dc395630156b0c361053704665e02df04749bd 100644
--- a/src/shared/cplusplus/Names.h
+++ b/src/shared/cplusplus/Names.h
@@ -271,6 +271,39 @@ private:
     FullySpecifiedType _type;
 };
 
+class CPLUSPLUS_EXPORT SelectorNameId: public Name
+{
+public:
+    SelectorNameId(Name *const names[],
+                   unsigned nameCount,
+                   bool hasArguments);
+    virtual ~SelectorNameId();
+
+    virtual Identifier *identifier() const;
+
+    unsigned nameCount() const;
+    Name *nameAt(unsigned index) const;
+    Name *const *names() const;
+
+    bool hasArguments() const;
+
+    virtual bool isEqualTo(const Name *other) const;
+
+    virtual const SelectorNameId *asSelectorNameId() const
+    { return this; }
+
+    virtual SelectorNameId *asSelectorNameId()
+    { return this; }
+
+protected:
+    virtual void accept0(NameVisitor *visitor);
+
+private:
+    Name **_names;
+    unsigned _nameCount;
+    bool _hasArguments;
+};
+
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
 
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index d0a7b05bcbec271a88b938d21f5453af839a9dbf..ee8e714f64e1d39036ef02b491c306a810405b09 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -2967,7 +2967,7 @@ bool Parser::parseObjCMessageExpression(ExpressionAST *&node)
     ast->lbracket_token = consumeToken();
 
     parseObjCMessageReceiver(ast->receiver_expression);
-    parseObjCMessageArguments(ast->argument_list);
+    parseObjCMessageArguments(ast->selector, ast->argument_list);
 
     match(T_RBRACKET, &(ast->rbracket_token));
     node = ast;
@@ -2979,25 +2979,34 @@ bool Parser::parseObjCMessageReceiver(ExpressionAST *&node)
     return parseExpression(node);
 }
 
-bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& node)
+bool Parser::parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode)
 {
     if (LA() == T_RBRACKET)
         return false; // nothing to do.
 
     unsigned start = cursor();
 
-    ObjCMessageArgumentListAST *ast = new (_pool) ObjCMessageArgumentListAST;
-    ObjCMessageArgumentAST *argument = 0;
+    ObjCSelectorArgumentAST *selectorArgument = 0;
+    ObjCMessageArgumentAST *messageArgument = 0;
 
-    if (parseObjCSelectorArg(argument)) {
-        ast->arg = argument;
-        ObjCMessageArgumentListAST *lastArgument = ast;
+    if (parseObjCSelectorArg(selectorArgument, messageArgument)) {
+        ObjCSelectorArgumentListAST *selAst = new (_pool) ObjCSelectorArgumentListAST;
+        selAst->argument = selectorArgument;
+        ObjCSelectorArgumentListAST *lastSelector = selAst;
 
-        while (parseObjCSelectorArg(argument)) {
+        ObjCMessageArgumentListAST *argAst = new (_pool) ObjCMessageArgumentListAST;
+        argAst->arg = messageArgument;
+        ObjCMessageArgumentListAST *lastArgument = argAst;
+
+        while (parseObjCSelectorArg(selectorArgument, messageArgument)) {
             // accept the selector args.
+            lastSelector->next = new (_pool) ObjCSelectorArgumentListAST;
+            lastSelector = lastSelector->next;
+            lastSelector->argument = selectorArgument;
+
             lastArgument->next = new (_pool) ObjCMessageArgumentListAST;
             lastArgument = lastArgument->next;
-            lastArgument->arg = argument;
+            lastArgument->arg = messageArgument;
         }
 
         if (LA() == T_COMMA) {
@@ -3011,17 +3020,24 @@ bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& node)
                 lastExpression = &(binaryExpression->right_expression);
             }
         }
+
+        ObjCSelectorWithArgumentsAST *selWithArgs = new (_pool) ObjCSelectorWithArgumentsAST;
+        selWithArgs->selector_arguments = selAst;
+
+        selNode = selWithArgs;
+        argNode = argAst;
     } else {
         rewind(start);
-        ast->arg = new (_pool) ObjCMessageArgumentAST;
-        parseObjCSelector(ast->arg->parameter_key_identifier);
+        ObjCSelectorWithoutArgumentsAST *sel = new (_pool) ObjCSelectorWithoutArgumentsAST;
+        parseObjCSelector(sel->name_token);
+        selNode = sel;
+        argNode = 0;
     }
 
-    node = ast;
     return true;
 }
 
-bool Parser::parseObjCSelectorArg(ObjCMessageArgumentAST *&node)
+bool Parser::parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode)
 {
     unsigned selector_token = 0;
     if (!parseObjCSelector(selector_token))
@@ -3030,12 +3046,12 @@ bool Parser::parseObjCSelectorArg(ObjCMessageArgumentAST *&node)
     if (LA() != T_COLON)
         return false;
 
-    ObjCMessageArgumentAST *argument = new (_pool) ObjCMessageArgumentAST;
-    argument->parameter_key_identifier = selector_token;
-    argument->colon_token = consumeToken();
+    selNode = new (_pool) ObjCSelectorArgumentAST;
+    selNode->name_token = selector_token;
+    selNode->colon_token = consumeToken();
 
-    parseAssignmentExpression(argument->parameter_value_expression);
-    node = argument;
+    argNode = new (_pool) ObjCMessageArgumentAST;
+    parseAssignmentExpression(argNode->parameter_value_expression);
     return true;
 }
 
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index ec40707613da10f481d046789bbd0a94f75e41c6..181e4b6b712fb735dfd293b8e1b3323a3eb857d0 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -226,8 +226,8 @@ public:
     bool parseObjCMethodSignature();
     bool parseObjCMessageExpression(ExpressionAST *&node);
     bool parseObjCMessageReceiver(ExpressionAST *&node);
-    bool parseObjCMessageArguments(ObjCMessageArgumentListAST *&node);
-    bool parseObjCSelectorArg(ObjCMessageArgumentAST *&node);
+    bool parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode);
+    bool parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode);
     bool parseObjCMethodDefinitionList(DeclarationListAST *&node);
     bool parseObjCMethodDefinition(DeclarationAST *&node);