From 26267c03445266233159b2f61bbc3a4d5864c01a Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Tue, 28 Jul 2009 16:34:15 +0200
Subject: [PATCH] Improved ObjC parsing, and added semantic checks.

---
 src/libs/cplusplus/CheckUndefinedSymbols.cpp  |   8 +
 src/libs/cplusplus/Icons.cpp                  |   4 +
 src/shared/cplusplus/AST.cpp                  | 132 +++++++++---
 src/shared/cplusplus/AST.h                    | 193 ++++++++++++++++--
 src/shared/cplusplus/ASTClone.cpp             |  65 ++++--
 src/shared/cplusplus/ASTVisit.cpp             |  56 ++++-
 src/shared/cplusplus/ASTVisitor.h             |  22 +-
 src/shared/cplusplus/ASTfwd.h                 |  12 +-
 .../cplusplus/CPlusPlusForwardDeclarations.h  |   6 +
 src/shared/cplusplus/CheckDeclaration.cpp     | 142 +++++++++++++
 src/shared/cplusplus/CheckDeclaration.h       |   7 +
 src/shared/cplusplus/CheckDeclarator.cpp      |  37 ++++
 src/shared/cplusplus/CheckDeclarator.h        |   5 +
 src/shared/cplusplus/CheckName.cpp            |  35 ++++
 src/shared/cplusplus/CheckName.h              |   5 +
 src/shared/cplusplus/Control.cpp              |  47 +++++
 src/shared/cplusplus/Control.h                |  12 ++
 src/shared/cplusplus/Parser.cpp               | 170 ++++++++-------
 src/shared/cplusplus/Parser.h                 |   4 +-
 src/shared/cplusplus/Semantic.cpp             |  47 +++++
 src/shared/cplusplus/Semantic.h               |   9 +
 src/shared/cplusplus/Symbol.cpp               |  12 ++
 src/shared/cplusplus/Symbol.h                 |  23 ++-
 src/shared/cplusplus/SymbolVisitor.h          |   6 +
 src/shared/cplusplus/Symbols.cpp              | 134 ++++++++++++
 src/shared/cplusplus/Symbols.h                | 127 ++++++++++++
 src/shared/cplusplus/Type.cpp                 |  12 ++
 src/shared/cplusplus/Type.h                   |  12 ++
 src/shared/cplusplus/TypeVisitor.h            |   4 +
 29 files changed, 1192 insertions(+), 156 deletions(-)

diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
index d0d69187468..3e7304c6179 100644
--- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp
+++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
@@ -154,6 +154,14 @@ void CheckUndefinedSymbols::buildTypeMap(NamespaceBinding *binding, QSet<Namespa
                 } else if (Declaration *decl = member->asDeclaration()) {
                     if (decl->isTypedef())
                         addType(decl->name());
+                } else if (ObjCForwardClassDeclaration *fKlass = member->asObjCForwardClassDeclaration()) {
+                    addType(fKlass->name());
+                } else if (ObjCClass *klass = member->asObjCClass()) {
+                    addType(klass->name());
+                } else if (ObjCForwardProtocolDeclaration *fProto = member->asObjCForwardProtocolDeclaration()) {
+                    addType(fProto->name());
+                } else if (ObjCProtocol *proto = member->asObjCProtocol()) {
+                    addType(proto->name());
                 }
             }
         }
diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index 90b03f871ab..894cf86eebd 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -98,6 +98,10 @@ QIcon Icons::iconForSymbol(const Symbol *symbol) const
         return _enumIcon;
     } else if (symbol->isClass() || symbol->isForwardClassDeclaration()) {
         return _classIcon;
+    } else if (symbol->isObjCClass() || symbol->isObjCForwardClassDeclaration()) {
+        return _classIcon;
+    } else if (symbol->isObjCProtocol() || symbol->isObjCForwardProtocolDeclaration()) {
+        return _classIcon;
     } else if (symbol->isNamespace()) {
         return _namespaceIcon;
     } else if (symbol->isUsingNamespaceDirective() ||
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 0eae1bd0fed..967894cc743 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -1906,14 +1906,17 @@ unsigned WhileStatementAST::lastToken() const
 // ObjC++
 unsigned IdentifierListAST::firstToken() const
 {
-    return identifier_token;
+    if (name)
+        return name->firstToken();
+    else
+        return comma_token;
 }
 
 unsigned IdentifierListAST::lastToken() const
 {
     for (const IdentifierListAST *it = this; it; it = it->next) {
-        if (! it->next && it->identifier_token) {
-            return it->identifier_token + 1;
+        if (! it->next && it->name) {
+            return it->name->lastToken();
         }
     }
     // ### assert?
@@ -1934,8 +1937,8 @@ unsigned ObjCClassDeclarationAST::lastToken() const
         return semicolon_token + 1;
 
     for (IdentifierListAST *it = identifier_list; it; it = it->next) {
-        if (! it->next && it->identifier_token)
-            return it->identifier_token + 1;
+        if (! it->next && it->name)
+            return it->name->lastToken();
     }
 
     for (SpecifierAST *it = attributes; it; it = it->next) {
@@ -1959,8 +1962,8 @@ unsigned ObjCProtocolDeclarationAST::lastToken() const
         return semicolon_token + 1;
 
     for (IdentifierListAST *it = identifier_list; it; it = it->next) {
-        if (! it->next && it->identifier_token)
-            return it->identifier_token + 1;
+        if (! it->next && it->name)
+            return it->name->lastToken();
     }
 
     for (SpecifierAST *it = attributes; it; it = it->next) {
@@ -1971,21 +1974,21 @@ unsigned ObjCProtocolDeclarationAST::lastToken() const
     return protocol_token + 1;
 }
 
-unsigned ObjCClassInterfaceDeclarationAST::firstToken() const
+unsigned ObjCClassInterfaceDefinitionAST::firstToken() const
 {
     if (attributes)
         return attributes->firstToken();
     return interface_token;
 }
 
-unsigned ObjCClassInterfaceDeclarationAST::lastToken() const
+unsigned ObjCClassInterfaceDefinitionAST::lastToken() const
 {
     if (end_token)                   return end_token + 1;
     if (member_declarations)         return member_declarations->lastToken();
     if (inst_vars_decl)              return inst_vars_decl->lastToken();
     if (superclass_identifier_token) return superclass_identifier_token + 1;
     if (colon_token)                 return colon_token + 1;
-    if (class_identifier_token)      return class_identifier_token + 1;
+    if (class_name)                  return class_name->lastToken();
 
     for (SpecifierAST *it = attributes; it; it = it->next) {
         if (! it->next)
@@ -2036,8 +2039,8 @@ unsigned ObjCProtocolDefinitionAST::lastToken() const
     if (protocol_refs)
         return protocol_refs->lastToken();
 
-    if (identifier_token)
-        return identifier_token + 1;
+    if (name)
+        return name->lastToken();
 
     for (SpecifierAST *it = attributes; it; it = it->next) {
         if (! it->next)
@@ -2057,8 +2060,8 @@ unsigned ObjCProtocolRefsAST::lastToken() const
     if (greater_token) return greater_token + 1;
 
     for (IdentifierListAST *it = identifier_list; it; it = it->next) {
-        if (! it->next && it->identifier_token)
-            return it->identifier_token + 1;
+        if (! it->next && it->name)
+            return it->name->lastToken();
     }
 
     return less_token + 1;
@@ -2169,6 +2172,74 @@ unsigned ObjCEncodeExpressionAST::lastToken() const
     return encode_token + 1;
 }
 
+unsigned ObjCSelectorWithoutArgumentsAST::firstToken() const
+{
+    return name_token;
+}
+
+unsigned ObjCSelectorWithoutArgumentsAST::lastToken() const
+{
+    return name_token + 1;
+}
+
+unsigned ObjCSelectorArgumentAST::firstToken() const
+{
+    return name_token;
+}
+
+unsigned ObjCSelectorArgumentAST::lastToken() const
+{
+    if (colon_token)
+        return colon_token + 1;
+    else
+        return name_token + 1;
+}
+
+unsigned ObjCSelectorArgumentListAST::firstToken() const
+{
+    if (argument)
+        return argument->firstToken();
+
+    // ### assert?
+    return 0;
+}
+
+unsigned ObjCSelectorArgumentListAST::lastToken() const
+{
+    for (const ObjCSelectorArgumentListAST *it = this; it; it = it->next)
+        if (!it->next && it->argument)
+            return it->argument->lastToken();
+
+    // ### assert?
+    return 0;
+}
+
+unsigned ObjCSelectorWithArgumentsAST::firstToken() const
+{
+    return selector_arguments->firstToken();
+}
+
+unsigned ObjCSelectorWithArgumentsAST::lastToken() const
+{
+    return selector_arguments->lastToken();
+}
+
+unsigned ObjCSelectorExpressionAST::firstToken() const
+{
+    return selector_token;
+}
+
+unsigned ObjCSelectorExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (selector)
+        return selector->lastToken();
+    if (lparen_token)
+        return rparen_token + 1;
+    return selector_token + 1;
+}
+
 unsigned ObjCInstanceVariablesDeclarationAST::firstToken() const
 {
     return lbrace_token;
@@ -2179,9 +2250,6 @@ unsigned ObjCInstanceVariablesDeclarationAST::lastToken() const
     if (rbrace_token)
         return rbrace_token + 1;
 
-    if (member_declarations)
-        return member_declarations->lastToken();
-
     if (instance_variables)
         return instance_variables->lastToken();
 
@@ -2198,24 +2266,22 @@ unsigned ObjCVisibilityDeclarationAST::lastToken() const
     return visibility_token + 1;
 }
 
-unsigned ObjcPropertyAttributeAST::firstToken() const
+unsigned ObjCPropertyAttributeAST::firstToken() const
 {
     return attribute_identifier_token;
 }
 
-unsigned ObjcPropertyAttributeAST::lastToken() const
+unsigned ObjCPropertyAttributeAST::lastToken() const
 {
-    if (colon_token)
-        return colon_token + 1;
-    if (method_selector_identifier_token)
-        return method_selector_identifier_token + 1;
+    if (method_selector)
+        return method_selector->lastToken();
     if (equals_token)
         return equals_token + 1;
 
     return attribute_identifier_token + 1;
 }
 
-unsigned ObjcPropertyAttributeListAST::firstToken() const
+unsigned ObjCPropertyAttributeListAST::firstToken() const
 {
     if (attr)
         return attr->firstToken();
@@ -2228,9 +2294,9 @@ unsigned ObjcPropertyAttributeListAST::firstToken() const
         return 0;
 }
 
-unsigned ObjcPropertyAttributeListAST::lastToken() const
+unsigned ObjCPropertyAttributeListAST::lastToken() const
 {
-    for (const ObjcPropertyAttributeListAST *it = this; it; it = it->next) {
+    for (const ObjCPropertyAttributeListAST *it = this; it; it = it->next) {
         if (! it->next && (comma_token || it->attr)) {
             if (comma_token)
                 return comma_token + 1;
@@ -2266,21 +2332,21 @@ unsigned ObjCPropertyDeclarationAST::lastToken() const
 
 unsigned ObjCMessageArgumentDeclarationAST::firstToken() const
 {
-    return param_selector_token;
+    if (type_name)
+        return type_name->firstToken();
+    else
+        return param_name_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;
+
+    // ### assert?
+    return 0;
 }
 
 unsigned ObjCMessageArgumentDeclarationListAST::firstToken() const
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index cbbbc5da69f..df54fc106c7 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -196,9 +196,40 @@ public:
     virtual UsingDirectiveAST *asUsingDirective() { return 0; }
     virtual WhileStatementAST *asWhileStatement() { return 0; }
     virtual IdentifierListAST *asIdentifierList() { return 0; }
+
     virtual ObjCClassDeclarationAST *asObjCClassDeclaration() { return 0; }
     virtual ObjCProtocolDeclarationAST *asObjCProtocolDeclaration() { return 0; }
     virtual ObjCProtocolDefinitionAST *asObjCProtocolDefinition() { return 0; }
+    virtual ObjCProtocolRefsAST *asObjCProtocolRefs() { return 0; }
+    virtual ObjCMessageArgumentAST *asObjCMessageArgument() { return 0; }
+    virtual ObjCMessageArgumentListAST *asObjCMessageArgumentList() { return 0; }
+    virtual ObjCMessageExpressionAST *asObjCMessageExpression() { return 0; }
+    virtual ObjCProtocolExpressionAST *asObjCProtocolExpression() { return 0; }
+    virtual ObjCTypeNameAST *asObjCTypeName() { return 0; }
+    virtual ObjCEncodeExpressionAST *asObjCEncodeExpression() { return 0; }
+    virtual ObjCSelectorAST *asObjCSelector() { return 0; }
+    virtual ObjCSelectorWithoutArgumentsAST *asObjCSelectorWithoutArguments() { return 0; }
+    virtual ObjCSelectorArgumentAST *asObjCSelectorArgument() { return 0; }
+    virtual ObjCSelectorArgumentListAST *asObjCSelectorArgumentList() { return 0; }
+    virtual ObjCSelectorWithArgumentsAST *asObjCSelectorWithArguments() { return 0; }
+    virtual ObjCSelectorExpressionAST *asObjCSelectorExpression() { return 0; }
+    virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration() { return 0; }
+    virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration() { return 0; }
+    virtual ObjCPropertyAttributeAST *asObjCPropertyAttribute() { return 0; }
+    virtual ObjCPropertyAttributeListAST *asObjCPropertyAttributeList() { return 0; }
+    virtual ObjCPropertyDeclarationAST *asObjCPropertyDeclaration() { return 0; }
+    virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration() { return 0; }
+    virtual ObjCMessageArgumentDeclarationListAST *asObjCMessageArgumentDeclarationList() { return 0; }
+    virtual ObjCMethodPrototypeAST *asObjCMethodPrototype() { return 0; }
+    virtual ObjCMethodDeclarationAST *asObjCMethodDeclaration() { return 0; }
+    virtual ObjCMethodDefinitionAST *asObjCMethodDefinition() { return 0; }
+    virtual ObjCClassImplementationAST *asObjCClassImplementation() { return 0; }
+    virtual ObjCCategoryImplementationAST *asObjCCategoryImplementation() { return 0; }
+    virtual ObjCSynthesizedPropertyAST *asObjCSynthesizedProperty() { return 0; }
+    virtual ObjCSynthesizedPropertyListAST *asObjCSynthesizedPropertyList() { return 0; }
+    virtual ObjCSynthesizedPropertiesDeclarationAST *asObjCSynthesizedPropertiesDeclaration() { return 0; }
+    virtual ObjCDynamicPropertiesDeclarationAST *asObjCDynamicPropertiesDeclaration() { return 0; }
+    virtual ObjCFastEnumerationAST *asObjCFastEnumeration() { return 0; }
 
     virtual AST *clone(MemoryPool *pool) const = 0;
 
@@ -2444,7 +2475,7 @@ protected:
 class CPLUSPLUS_EXPORT IdentifierListAST: public AST
 {
 public:
-    unsigned identifier_token;
+    SimpleNameAST *name;
     unsigned comma_token;
     IdentifierListAST *next;
 
@@ -2469,6 +2500,9 @@ public:
     IdentifierListAST *identifier_list;
     unsigned semicolon_token;
 
+public: // annotations
+    List<ObjCForwardClassDeclaration *> *symbols;
+
 public:
     virtual ObjCClassDeclarationAST *asObjCClassDeclaration()
     { return this; }
@@ -2482,12 +2516,12 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjCClassInterfaceDeclarationAST: public DeclarationAST
+class CPLUSPLUS_EXPORT ObjCClassInterfaceDefinitionAST: public DeclarationAST
 {
 public:
     SpecifierAST *attributes;
     unsigned interface_token;
-    unsigned class_identifier_token;
+    SimpleNameAST *class_name;
     unsigned colon_token;
     unsigned superclass_identifier_token;
     ObjCProtocolRefsAST *protocol_refs;
@@ -2495,14 +2529,17 @@ public:
     DeclarationListAST *member_declarations;
     unsigned end_token;
 
+public: // annotations
+    ObjCClass *symbol;
+
 public:
-    virtual ObjCClassInterfaceDeclarationAST *asObjCClassInterfaceDeclaration()
+    virtual ObjCClassInterfaceDefinitionAST *asObjCClassInterfaceDefinition()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjCClassInterfaceDeclarationAST *clone(MemoryPool *pool) const;
+    virtual ObjCClassInterfaceDefinitionAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
@@ -2542,6 +2579,9 @@ public:
     IdentifierListAST *identifier_list;
     unsigned semicolon_token;
 
+public: // annotations
+    List<ObjCForwardProtocolDeclaration *> *symbols;
+
 public:
     virtual ObjCProtocolDeclarationAST *asObjCProtocolDeclaration()
     { return this; }
@@ -2560,11 +2600,14 @@ class CPLUSPLUS_EXPORT ObjCProtocolDefinitionAST: public DeclarationAST
 public:
     SpecifierAST *attributes;
     unsigned protocol_token;
-    unsigned identifier_token;
+    SimpleNameAST *name;
     ObjCProtocolRefsAST *protocol_refs;
     DeclarationListAST *member_declarations;
     unsigned end_token;
 
+public: // annotations
+    ObjCProtocol *symbol;
+
 public:
     virtual ObjCProtocolDefinitionAST *asObjCProtocolDefinition()
     { return this; }
@@ -2719,12 +2762,118 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
+class CPLUSPLUS_EXPORT ObjCSelectorAST: public AST
+{
+public: // annotation
+    Name *selector_name;
+
+public:
+    virtual ObjCSelectorAST *asObjCSelector()
+    { return this; }
+
+    virtual ObjCSelectorAST *clone(MemoryPool *pool) const = 0;
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorWithoutArgumentsAST: public ObjCSelectorAST
+{
+public:
+    unsigned name_token;
+
+public:
+    virtual ObjCSelectorWithoutArgumentsAST *asObjCSelectorWithoutArguments()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorWithoutArgumentsAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorArgumentAST: public AST
+{
+public:
+    unsigned name_token;
+    unsigned colon_token;
+
+public:
+    virtual ObjCSelectorArgumentAST *asObjCSelectorArgument()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorArgumentAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorArgumentListAST: public AST
+{
+public:
+    ObjCSelectorArgumentAST *argument;
+    ObjCSelectorArgumentListAST *next;
+
+public:
+    virtual ObjCSelectorArgumentListAST *asObjCSelectorArgumentList()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorArgumentListAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorWithArgumentsAST: public ObjCSelectorAST
+{
+public:
+    ObjCSelectorArgumentListAST *selector_arguments;
+
+public:
+    virtual ObjCSelectorWithArgumentsAST *asObjCSelectorWithArguments()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorWithArgumentsAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSelectorExpressionAST: public ExpressionAST
+{
+public:
+    unsigned selector_token;
+    unsigned lparen_token;
+    ObjCSelectorAST *selector;
+    unsigned rparen_token;
+
+public:
+    virtual ObjCSelectorExpressionAST *asObjCSelectorExpression()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSelectorExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
 class CPLUSPLUS_EXPORT ObjCInstanceVariablesDeclarationAST: public AST
 {
 public:
     unsigned lbrace_token;
     DeclarationListAST *instance_variables;
-    DeclarationListAST *member_declarations;
     unsigned rbrace_token;
 
 public:
@@ -2758,42 +2907,41 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjcPropertyAttributeAST: public AST
+class CPLUSPLUS_EXPORT ObjCPropertyAttributeAST: public AST
 {
 public:
     unsigned attribute_identifier_token;
     unsigned equals_token;
-    unsigned method_selector_identifier_token;
-    unsigned colon_token;
+    ObjCSelectorAST *method_selector;
 
 public:
-    virtual ObjcPropertyAttributeAST *asObjcPropertyAttribute()
+    virtual ObjCPropertyAttributeAST *asObjCPropertyAttribute()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjcPropertyAttributeAST *clone(MemoryPool *pool) const;
+    virtual ObjCPropertyAttributeAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjcPropertyAttributeListAST: public AST
+class CPLUSPLUS_EXPORT ObjCPropertyAttributeListAST: public AST
 {
 public:
-    ObjcPropertyAttributeAST *attr;
+    ObjCPropertyAttributeAST *attr;
     unsigned comma_token;
-    ObjcPropertyAttributeListAST *next;
+    ObjCPropertyAttributeListAST *next;
 
 public:
-    virtual ObjcPropertyAttributeListAST *asObjcPropertyAttributeList()
+    virtual ObjCPropertyAttributeListAST *asObjCPropertyAttributeList()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjcPropertyAttributeListAST *clone(MemoryPool *pool) const;
+    virtual ObjCPropertyAttributeListAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
@@ -2805,7 +2953,7 @@ public:
     SpecifierAST *attributes;
     unsigned property_token;
     unsigned lparen_token;
-    ObjcPropertyAttributeListAST *property_attributes;
+    ObjCPropertyAttributeListAST *property_attributes;
     unsigned rparen_token;
     DeclarationAST *simple_declaration;
 
@@ -2825,12 +2973,13 @@ protected:
 class CPLUSPLUS_EXPORT ObjCMessageArgumentDeclarationAST: public AST
 {
 public:
-    unsigned param_selector_token;
-    unsigned colon_token;
     ObjCTypeNameAST* type_name;
     SpecifierAST *attributes;
     unsigned param_name_token;
 
+public: // annotations
+    Name *param_name;
+
 public:
     virtual ObjCMessageArgumentDeclarationAST *asObjCMessageArgumentDeclaration()
     { return this; }
@@ -2868,9 +3017,13 @@ class CPLUSPLUS_EXPORT ObjCMethodPrototypeAST: public AST
 public:
     unsigned method_type_token;
     ObjCTypeNameAST *type_name;
+    ObjCSelectorAST *selector;
     ObjCMessageArgumentDeclarationListAST *arguments;
     SpecifierAST *attributes;
 
+public: // annotations
+    Function *symbol;
+
 public:
     virtual ObjCMethodPrototypeAST *asObjCMethodPrototype()
     { return this; }
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 3340a39f25c..24717e300a4 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1207,7 +1207,8 @@ IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const
 {
     IdentifierListAST *ast = new (pool) IdentifierListAST;
     // copy IdentifierListAST
-    ast->identifier_token = identifier_token;
+    if (ast->name) ast->name = name->clone(pool);
+    ast->comma_token = comma_token;
     if (next) ast->next = next->clone(pool);
     return ast;
 }
@@ -1224,14 +1225,14 @@ ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
     return ast;
 }
 
-ObjCClassInterfaceDeclarationAST *ObjCClassInterfaceDeclarationAST::clone(MemoryPool *pool) const
+ObjCClassInterfaceDefinitionAST *ObjCClassInterfaceDefinitionAST::clone(MemoryPool *pool) const
 {
-    ObjCClassInterfaceDeclarationAST *ast = new (pool) ObjCClassInterfaceDeclarationAST;
+    ObjCClassInterfaceDefinitionAST *ast = new (pool) ObjCClassInterfaceDefinitionAST;
     // copy DeclarationAST
     // copy ObjCClassInterfaceDeclarationAST
     if (attributes) ast->attributes = attributes->clone(pool);
     ast->interface_token = interface_token;
-    ast->class_identifier_token = class_identifier_token;
+    if (class_name) ast->class_name = class_name->clone(pool);
     ast->colon_token = colon_token;
     ast->superclass_identifier_token = superclass_identifier_token;
     if (protocol_refs) ast->protocol_refs = protocol_refs->clone(pool);
@@ -1273,7 +1274,7 @@ ObjCProtocolDefinitionAST *ObjCProtocolDefinitionAST::clone(MemoryPool *pool) co
     ObjCProtocolDefinitionAST *ast = new (pool) ObjCProtocolDefinitionAST;
     if (attributes) ast->attributes = attributes->clone(pool);
     ast->protocol_token = protocol_token;
-    ast->identifier_token = identifier_token;
+    if (name) ast->name = name->clone(pool);
     if (protocol_refs) ast->protocol_refs = protocol_refs->clone(pool);
     if (member_declarations) ast->member_declarations = member_declarations->clone(pool);
     ast->end_token = end_token;
@@ -1344,12 +1345,51 @@ ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorWithoutArgumentsAST *ast = new (pool) ObjCSelectorWithoutArgumentsAST;
+    ast->name_token = name_token;
+    return ast;
+}
+
+ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorArgumentAST *ast = new (pool) ObjCSelectorArgumentAST;
+    ast->name_token = name_token;
+    ast->colon_token = colon_token;
+    return ast;
+}
+
+ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorArgumentListAST *ast = new (pool) ObjCSelectorArgumentListAST;
+    if (argument) ast->argument = argument->clone(pool);
+    if (next) ast->next = next->clone(pool);
+    return ast;
+}
+
+ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorWithArgumentsAST *ast = new (pool) ObjCSelectorWithArgumentsAST;
+    if (selector_arguments) ast->selector_arguments = selector_arguments->clone(pool);
+    return ast;
+}
+
+ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) const
+{
+    ObjCSelectorExpressionAST *ast = new (pool) ObjCSelectorExpressionAST;
+    ast->selector_token = selector_token;
+    ast->lparen_token = lparen_token;
+    if (selector) ast->selector = selector->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(MemoryPool *pool) const
 {
     ObjCInstanceVariablesDeclarationAST *ast = new (pool) ObjCInstanceVariablesDeclarationAST;
     ast->lbrace_token = lbrace_token;
     if (instance_variables) ast->instance_variables = instance_variables->clone(pool);
-    if (member_declarations) ast->member_declarations = member_declarations->clone(pool);
     ast->rbrace_token = rbrace_token;
     return ast;
 }
@@ -1361,19 +1401,18 @@ ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *po
     return ast;
 }
 
-ObjcPropertyAttributeAST *ObjcPropertyAttributeAST::clone(MemoryPool *pool) const
+ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) const
 {
-    ObjcPropertyAttributeAST *ast = new (pool) ObjcPropertyAttributeAST;
+    ObjCPropertyAttributeAST *ast = new (pool) ObjCPropertyAttributeAST;
     ast->attribute_identifier_token = attribute_identifier_token;
     ast->equals_token = equals_token;
-    ast->method_selector_identifier_token = method_selector_identifier_token;
-    ast->colon_token = colon_token;
+    if (method_selector) ast->method_selector = method_selector->clone(pool);
     return ast;
 }
 
-ObjcPropertyAttributeListAST *ObjcPropertyAttributeListAST::clone(MemoryPool *pool) const
+ObjCPropertyAttributeListAST *ObjCPropertyAttributeListAST::clone(MemoryPool *pool) const
 {
-    ObjcPropertyAttributeListAST *ast = new (pool) ObjcPropertyAttributeListAST;
+    ObjCPropertyAttributeListAST *ast = new (pool) ObjCPropertyAttributeListAST;
     if (attr) ast->attr = attr->clone(pool);
     ast->comma_token = comma_token;
     if (next) ast->next = next->clone(pool);
@@ -1395,8 +1434,6 @@ ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool)
 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;
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 9b43a34bfd7..dbf8d0a91d2 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1122,6 +1122,9 @@ void IdentifierListAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit IdentifierListAST
+        if (name)
+            accept(name, visitor);
+        // visit AST
     }
     visitor->endVisit(this);
 }
@@ -1139,7 +1142,7 @@ void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
-void ObjCClassInterfaceDeclarationAST::accept0(ASTVisitor *visitor)
+void ObjCClassInterfaceDefinitionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCClassInterfaceDeclarationAST
@@ -1189,6 +1192,8 @@ void ObjCProtocolDefinitionAST::accept0(ASTVisitor *visitor)
         // visit ObjCProtocolDefinitionAST
         for (SpecifierAST *it = attributes; it; it = it->next)
             accept(it, visitor);
+        if (name)
+            accept(name, visitor);
         if (protocol_refs)
             accept(protocol_refs, visitor);
         if (member_declarations)
@@ -1277,14 +1282,53 @@ void ObjCEncodeExpressionAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void ObjCSelectorWithoutArgumentsAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorArgumentAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorArgumentListAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        if (argument)
+            accept(argument, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorWithArgumentsAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (ObjCSelectorArgumentListAST *it = selector_arguments; it; it = it->next)
+            accept(it, visitor);
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSelectorExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        if (selector)
+            accept(selector, visitor);
+    }
+    visitor->endVisit(this);
+}
+
 void ObjCInstanceVariablesDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCInstanceVariablesDeclarationAST
         if (instance_variables)
             accept(instance_variables, visitor);
-        if (member_declarations)
-            accept(member_declarations, visitor);
         // visit AST
     }
     visitor->endVisit(this);
@@ -1299,7 +1343,7 @@ void ObjCVisibilityDeclarationAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
-void ObjcPropertyAttributeAST::accept0(ASTVisitor *visitor)
+void ObjCPropertyAttributeAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjcPropertyAttributeAST
@@ -1308,7 +1352,7 @@ void ObjcPropertyAttributeAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
-void ObjcPropertyAttributeListAST::accept0(ASTVisitor *visitor)
+void ObjCPropertyAttributeListAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjcPropertyAttributeListAST
@@ -1325,7 +1369,7 @@ void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
         // visit ObjCPropertyDeclarationAST:
         for (SpecifierAST *it = attributes; it; it = it->next)
             accept(it, visitor);
-        for (ObjcPropertyAttributeListAST *it = property_attributes; it; it = it->next)
+        for (ObjCPropertyAttributeListAST *it = property_attributes; it; it = it->next)
             accept(it, visitor);
         if (simple_declaration)
             accept(simple_declaration, visitor);
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index dc289fdcb5a..ebe28a83da0 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -198,7 +198,7 @@ public:
     // ObjC++
     virtual bool visit(IdentifierListAST *) { return true; }
     virtual bool visit(ObjCClassDeclarationAST *) { return true; }
-    virtual bool visit(ObjCClassInterfaceDeclarationAST *) { return true; }
+    virtual bool visit(ObjCClassInterfaceDefinitionAST *) { return true; }
     virtual bool visit(ObjCCategoryInterfaceDeclarationAST *) { return true; }
     virtual bool visit(ObjCProtocolDeclarationAST *) { return true; }
     virtual bool visit(ObjCProtocolDefinitionAST *) { return true; }
@@ -209,10 +209,15 @@ public:
     virtual bool visit(ObjCProtocolExpressionAST *) { return true; }
     virtual bool visit(ObjCTypeNameAST *) { return true; }
     virtual bool visit(ObjCEncodeExpressionAST *) { return true; }
+    virtual bool visit(ObjCSelectorWithoutArgumentsAST *) { return true; }
+    virtual bool visit(ObjCSelectorArgumentAST *) { return true; }
+    virtual bool visit(ObjCSelectorArgumentListAST *) { return true; }
+    virtual bool visit(ObjCSelectorWithArgumentsAST *) { return true; }
+    virtual bool visit(ObjCSelectorExpressionAST *) { return true; }
     virtual bool visit(ObjCInstanceVariablesDeclarationAST *) { return true; }
     virtual bool visit(ObjCVisibilityDeclarationAST *) { return true; }
-    virtual bool visit(ObjcPropertyAttributeAST *) { return true; }
-    virtual bool visit(ObjcPropertyAttributeListAST *) { return true; }
+    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(ObjCMethodDeclarationAST *) { return true; }
@@ -335,7 +340,7 @@ public:
     // ObjC++
     virtual void endVisit(IdentifierListAST *) { }
     virtual void endVisit(ObjCClassDeclarationAST *) { }
-    virtual void endVisit(ObjCClassInterfaceDeclarationAST *) { }
+    virtual void endVisit(ObjCClassInterfaceDefinitionAST *) { }
     virtual void endVisit(ObjCCategoryInterfaceDeclarationAST *) { }
     virtual void endVisit(ObjCProtocolDeclarationAST *) { }
     virtual void endVisit(ObjCProtocolDefinitionAST *) { }
@@ -346,10 +351,15 @@ public:
     virtual void endVisit(ObjCProtocolExpressionAST *) { }
     virtual void endVisit(ObjCTypeNameAST *) { }
     virtual void endVisit(ObjCEncodeExpressionAST *) { }
+    virtual void endVisit(ObjCSelectorWithoutArgumentsAST *) { }
+    virtual void endVisit(ObjCSelectorArgumentAST *) { }
+    virtual void endVisit(ObjCSelectorArgumentListAST *) { }
+    virtual void endVisit(ObjCSelectorWithArgumentsAST *) { }
+    virtual void endVisit(ObjCSelectorExpressionAST *) { }
     virtual void endVisit(ObjCInstanceVariablesDeclarationAST *) { }
     virtual void endVisit(ObjCVisibilityDeclarationAST *) { }
-    virtual void endVisit(ObjcPropertyAttributeAST *) { }
-    virtual void endVisit(ObjcPropertyAttributeListAST *) { }
+    virtual void endVisit(ObjCPropertyAttributeAST *) { }
+    virtual void endVisit(ObjCPropertyAttributeListAST *) { }
     virtual void endVisit(ObjCPropertyDeclarationAST *) { }
     virtual void endVisit(ObjCMethodPrototypeAST *) { }
     virtual void endVisit(ObjCMethodDeclarationAST *) { }
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index a6ad8261756..be29bc7eea8 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -173,7 +173,7 @@ class IdentifierListAST;
 class ObjCClassDeclarationAST;
 class ObjCProtocolDeclarationAST;
 class ObjCProtocolDefinitionAST;
-class ObjCClassInterfaceDeclarationAST;
+class ObjCClassInterfaceDefinitionAST;
 class ObjCCategoryInterfaceDeclarationAST;
 class ObjCProtocolRefsAST;
 class ObjCMessageExpressionAST;
@@ -182,11 +182,17 @@ class ObjCMessageArgumentAST;
 class ObjCProtocolExpressionAST;
 class ObjCTypeNameAST;
 class ObjCEncodeExpressionAST;
+class ObjCSelectorAST;
+class ObjCSelectorWithoutArgumentsAST;
+class ObjCSelectorArgumentAST;
+class ObjCSelectorArgumentListAST;
+class ObjCSelectorWithArgumentsAST;
+class ObjCSelectorExpressionAST;
 class ObjCInstanceVariablesDeclarationAST;
 class ObjCVisibilityDeclarationAST;
 class ObjCPropertyDeclarationAST;
-class ObjcPropertyAttributeListAST;
-class ObjcPropertyAttributeAST;
+class ObjCPropertyAttributeListAST;
+class ObjCPropertyAttributeAST;
 class ObjCMethodPrototypeAST;
 class ObjCMethodDeclarationAST;
 class ObjCMethodDefinitionAST;
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index a60d0fe10f7..76ee3061dc5 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -133,6 +133,12 @@ class ForwardClassDeclaration;
 
 class Token;
 
+// Objective-C symbols
+class ObjCClass;
+class ObjCForwardClassDeclaration;
+class ObjCProtocol;
+class ObjCForwardProtocolDeclaration;
+
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
 
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 83fbc1dd0ef..1a9877db156 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -464,4 +464,146 @@ bool CheckDeclaration::visit(UsingDirectiveAST *ast)
     return false;
 }
 
+bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast)
+{
+    const unsigned sourceLocation = ast->firstToken();
+
+    List<ObjCForwardProtocolDeclaration *> **symbolIter = &ast->symbols;
+    for (IdentifierListAST *it = ast->identifier_list; it; it = it->next) {
+        unsigned declarationLocation;
+        if (it->name)
+            declarationLocation = it->name->firstToken();
+        else
+            declarationLocation = sourceLocation;
+
+        Name *protocolName = semantic()->check(it->name, _scope);
+        ObjCForwardProtocolDeclaration *fwdProtocol = control()->newObjCForwardProtocolDeclaration(sourceLocation, protocolName);
+        fwdProtocol->setStartOffset(tokenAt(ast->firstToken()).offset);
+        fwdProtocol->setEndOffset(tokenAt(ast->lastToken()).offset);
+
+        _scope->enterSymbol(fwdProtocol);
+
+        *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardProtocolDeclaration *>();
+        (*symbolIter)->value = fwdProtocol;
+        symbolIter = &(*symbolIter)->next;
+    }
+
+    return false;
+}
+
+bool CheckDeclaration::visit(ObjCProtocolDefinitionAST *ast)
+{
+    unsigned sourceLocation;
+    if (ast->name)
+        sourceLocation = ast->name->firstToken();
+    else
+        sourceLocation = ast->firstToken();
+
+    Name *protocolName = semantic()->check(ast->name, _scope);
+    ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName);
+    protocol->setStartOffset(tokenAt(ast->firstToken()).offset);
+    protocol->setEndOffset(tokenAt(ast->lastToken()).offset);
+    ast->symbol = protocol;
+
+    _scope->enterSymbol(protocol);
+
+    // TODO EV: walk protocols and method prototypes
+    return false;
+}
+
+bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast)
+{
+    const unsigned sourceLocation = ast->firstToken();
+
+    List<ObjCForwardClassDeclaration *> **symbolIter = &ast->symbols;
+    for (IdentifierListAST *it = ast->identifier_list; it; it = it->next) {
+        unsigned declarationLocation;
+        if (it->name)
+            declarationLocation = it->name->firstToken();
+        else
+            declarationLocation = sourceLocation;
+
+        Name *className = semantic()->check(it->name, _scope);
+        ObjCForwardClassDeclaration *fwdClass = control()->newObjCForwardClassDeclaration(sourceLocation, className);
+        fwdClass->setStartOffset(tokenAt(ast->firstToken()).offset);
+        fwdClass->setEndOffset(tokenAt(ast->lastToken()).offset);
+
+        _scope->enterSymbol(fwdClass);
+
+        *symbolIter = new (translationUnit()->memoryPool()) List<ObjCForwardClassDeclaration *>();
+        (*symbolIter)->value = fwdClass;
+        symbolIter = &(*symbolIter)->next;
+    }
+
+    return false;
+}
+
+bool CheckDeclaration::visit(ObjCClassInterfaceDefinitionAST *ast)
+{
+    unsigned sourceLocation;
+    if (ast->class_name)
+        sourceLocation = ast->class_name->firstToken();
+    else
+        sourceLocation = ast->firstToken();
+
+    Name *className = semantic()->check(ast->class_name, _scope);
+    ObjCClass *klass = control()->newObjCClass(sourceLocation, className);
+    klass->setStartOffset(tokenAt(ast->firstToken()).offset);
+    klass->setEndOffset(tokenAt(ast->lastToken()).offset);
+    ast->symbol = klass;
+
+    // TODO: walk super-class, and protocols (EV)
+    _scope->enterSymbol(klass);
+
+    int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected);
+
+    if (ast->inst_vars_decl) {
+        for (DeclarationListAST *it = ast->inst_vars_decl->instance_variables; it; it = it->next) {
+            semantic()->check(it->declaration, klass->members());
+        }
+    }
+
+    for (DeclarationListAST *it = ast->member_declarations; it; it = it->next) {
+        semantic()->check(it->declaration, klass->members());
+    }
+
+    (void) semantic()->switchObjCVisibility(previousObjCVisibility);
+
+    return false;
+}
+
+bool CheckDeclaration::visit(ObjCMethodDeclarationAST *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);
+
+    return false;
+}
+
+bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
+{
+    int accessSpecifier = tokenKind(ast->visibility_token);
+    int visibility = semantic()->visibilityForObjCAccessSpecifier(accessSpecifier);
+    semantic()->switchObjCVisibility(visibility);
+    return false;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h
index 4abd8598479..97c4d5ff449 100644
--- a/src/shared/cplusplus/CheckDeclaration.h
+++ b/src/shared/cplusplus/CheckDeclaration.h
@@ -91,6 +91,13 @@ protected:
     virtual bool visit(UsingAST *ast);
     virtual bool visit(UsingDirectiveAST *ast);
 
+    virtual bool visit(ObjCProtocolDeclarationAST *ast);
+    virtual bool visit(ObjCProtocolDefinitionAST *ast);
+    virtual bool visit(ObjCClassDeclarationAST *ast);
+    virtual bool visit(ObjCClassInterfaceDefinitionAST *ast);
+    virtual bool visit(ObjCMethodDeclarationAST *ast);
+    virtual bool visit(ObjCVisibilityDeclarationAST *ast);
+
 private:
     DeclarationAST *_declaration;
     Scope *_scope;
diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp
index bf9ae94cb97..27a0a03fc3d 100644
--- a/src/shared/cplusplus/CheckDeclarator.cpp
+++ b/src/shared/cplusplus/CheckDeclarator.cpp
@@ -94,6 +94,15 @@ FullySpecifiedType CheckDeclarator::check(PtrOperatorAST *ptrOperators,
     return switchFullySpecifiedType(previousType);
 }
 
+FullySpecifiedType CheckDeclarator::check(ObjCMethodPrototypeAST *methodPrototype,
+                                          Scope *scope)
+{
+    Scope *previousScope = switchScope(scope);
+    accept(methodPrototype);
+    (void) switchScope(previousScope);
+    return _fullySpecifiedType;
+}
+
 DeclaratorAST *CheckDeclarator::switchDeclarator(DeclaratorAST *declarator)
 {
     DeclaratorAST *previousDeclarator = _declarator;
@@ -237,6 +246,34 @@ bool CheckDeclarator::visit(ReferenceAST *ast)
     return false;
 }
 
+bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast)
+{
+    unsigned location = ast->firstToken();
+
+    Name *name = semantic()->check(ast->selector, _scope);
+
+    Function *fun = control()->newFunction(location, name);
+    ast->symbol = fun;
+    fun->setSourceLocation(location);
+    fun->setScope(_scope);
+    fun->setMethodKey(Function::NormalMethod);
+    fun->setVisibility(semantic()->currentVisibility());
+    fun->setPureVirtual(false);
+
+    // TODO: check return type (EV)
+//    fun->setReturnType(semantic()->check(ast->type_name, _scope));
+    // TODO: check the parameters (EV)
+    //    fun->setVariadic(...);
+    // TODO: add arguments (EV)
+
+    FullySpecifiedType mTy(fun);
+    _fullySpecifiedType = mTy;
+
+    // TODO: check which specifiers are allowed here (EV)
+
+    return false;
+}
+
 void CheckDeclarator::applyCvQualifiers(SpecifierAST *cv)
 {
     for (; cv; cv = cv->next) {
diff --git a/src/shared/cplusplus/CheckDeclarator.h b/src/shared/cplusplus/CheckDeclarator.h
index 75d027f001b..1903c6e26a7 100644
--- a/src/shared/cplusplus/CheckDeclarator.h
+++ b/src/shared/cplusplus/CheckDeclarator.h
@@ -71,6 +71,9 @@ public:
                                   FullySpecifiedType type,
                                   Scope *scope);
 
+    FullySpecifiedType check(ObjCMethodPrototypeAST *methodPrototype,
+                             Scope *scope);
+
 protected:
     DeclaratorAST *switchDeclarator(DeclaratorAST *declarator);
     FullySpecifiedType switchFullySpecifiedType(FullySpecifiedType type);
@@ -90,6 +93,8 @@ protected:
     // postfix declarators
     virtual bool visit(FunctionDeclaratorAST *ast);
     virtual bool visit(ArrayDeclaratorAST *ast);
+    // ObjC
+    virtual bool visit(ObjCMethodPrototypeAST *ast);
 
     void applyCvQualifiers(SpecifierAST *cv);
 
diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp
index 8045ea9a961..c18a9f34002 100644
--- a/src/shared/cplusplus/CheckName.cpp
+++ b/src/shared/cplusplus/CheckName.cpp
@@ -97,6 +97,17 @@ Name *CheckName::check(NestedNameSpecifierAST *nested_name_specifier, Scope *sco
     return switchName(previousName);
 }
 
+Name *CheckName::check(ObjCSelectorAST *args, Scope *scope)
+{
+    Name *previousName = switchName(0);
+    Scope *previousScope = switchScope(scope);
+
+    accept(args);
+
+    (void) switchScope(previousScope);
+    return switchName(previousName);
+}
+
 Name *CheckName::switchName(Name *name)
 {
     Name *previousName = _name;
@@ -351,4 +362,28 @@ bool CheckName::visit(TemplateIdAST *ast)
     return false;
 }
 
+bool CheckName::visit(ObjCSelectorWithoutArgumentsAST *ast)
+{
+    Identifier *id = identifier(ast->name_token);
+    _name = control()->nameId(id);
+    ast->selector_name = _name;
+
+    return false;
+}
+
+bool CheckName::visit(ObjCSelectorWithArgumentsAST *ast)
+{
+    std::vector<Name *> names;
+    for (ObjCSelectorArgumentListAST *it = ast->selector_arguments; it; it = it->next) {
+        Identifier *id =  identifier(it->argument->name_token);
+        Name *name = control()->nameId(id);
+
+        names.push_back(name);
+    }
+    _name = control()->qualifiedNameId(&names[0], names.size(), false);
+    ast->selector_name = _name;
+
+    return false;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/CheckName.h b/src/shared/cplusplus/CheckName.h
index 4d12497988e..21bd550a7c4 100644
--- a/src/shared/cplusplus/CheckName.h
+++ b/src/shared/cplusplus/CheckName.h
@@ -63,6 +63,7 @@ public:
 
     Name *check(NameAST *name, Scope *scope);
     Name *check(NestedNameSpecifierAST *name, Scope *scope);
+    Name *check(ObjCSelectorAST *args, Scope *scope);
 
 protected:
     Name *switchName(Name *name);
@@ -77,6 +78,10 @@ protected:
     virtual bool visit(DestructorNameAST *ast);
     virtual bool visit(TemplateIdAST *ast);
 
+    // ObjC
+    virtual bool visit(ObjCSelectorWithoutArgumentsAST *ast);
+    virtual bool visit(ObjCSelectorWithArgumentsAST *ast);
+
 private:
     Name *_name;
     Scope *_scope;
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index fe94d79d824..49f965f7da3 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -121,6 +121,10 @@ public:
         delete_array_entries(enums);
         delete_array_entries(usingDeclarations);
         delete_array_entries(classForwardDeclarations);
+        delete_array_entries(objcClasses);
+        delete_array_entries(objcProtocols);
+        delete_array_entries(objcForwardClassDeclarations);
+        delete_array_entries(objcForwardProtocolDeclarations);
     }
 
     NameId *findOrInsertNameId(Identifier *id)
@@ -327,6 +331,34 @@ public:
         return c;
     }
 
+    ObjCClass *newObjCClass(unsigned sourceLocation, Name *name)
+    {
+        ObjCClass *c = new ObjCClass(translationUnit, sourceLocation, name);
+        objcClasses.push_back(c);
+        return c;
+    }
+
+    ObjCForwardClassDeclaration *newObjCForwardClassDeclaration(unsigned sourceLocation, Name *name)
+    {
+        ObjCForwardClassDeclaration *fwd = new ObjCForwardClassDeclaration(translationUnit, sourceLocation, name);
+        objcForwardClassDeclarations.push_back(fwd);
+        return fwd;
+    }
+
+    ObjCProtocol *newObjCProtocol(unsigned sourceLocation, Name *name)
+    {
+        ObjCProtocol *p = new ObjCProtocol(translationUnit, sourceLocation, name);
+        objcProtocols.push_back(p);
+        return p;
+    }
+
+    ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, Name *name)
+    {
+        ObjCForwardProtocolDeclaration *fwd = new ObjCForwardProtocolDeclaration(translationUnit, sourceLocation, name);
+        objcForwardProtocolDeclarations.push_back(fwd);
+        return fwd;
+    }
+
     Enum *newEnum(unsigned sourceLocation, Name *name)
     {
         Enum *e = new Enum(translationUnit,
@@ -482,6 +514,10 @@ public:
     std::vector<Enum *> enums;
     std::vector<UsingDeclaration *> usingDeclarations;
     std::vector<ForwardClassDeclaration *> classForwardDeclarations;
+    std::vector<ObjCClass *> objcClasses;
+    std::vector<ObjCProtocol *> objcProtocols;
+    std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
+    std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
 };
 
 Control::Control()
@@ -638,5 +674,16 @@ ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLoca
                                                              Name *name)
 { return d->newForwardClassDeclaration(sourceLocation, name); }
 
+ObjCClass *Control::newObjCClass(unsigned sourceLocation, Name *name)
+{ return d->newObjCClass(sourceLocation, name); }
+
+ObjCForwardClassDeclaration *Control::newObjCForwardClassDeclaration(unsigned sourceLocation, Name *name)
+{ return d->newObjCForwardClassDeclaration(sourceLocation, name); }
+
+ObjCProtocol *Control::newObjCProtocol(unsigned sourceLocation, Name *name)
+{ return d->newObjCProtocol(sourceLocation, name); }
+
+ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsigned sourceLocation, Name *name)
+{ return d->newObjCForwardProtocolDeclaration(sourceLocation, name); }
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index 8b4f09afffb..a9b85b7baee 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -147,6 +147,18 @@ public:
     /// Creates a new ForwardClassDeclaration symbol.
     ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0);
 
+    /// Creates a new Objective-C class symbol.
+    ObjCClass *newObjCClass(unsigned sourceLocation, Name *name = 0);
+
+    /// Creates a new Objective-C class forward declaration symbol.
+    ObjCForwardClassDeclaration *newObjCForwardClassDeclaration(unsigned sourceLocation, Name *name = 0);
+
+    /// Creates a new Objective-C protocol symbol.
+    ObjCProtocol *newObjCProtocol(unsigned sourceLocation, Name *name = 0);
+
+    /// Creates a new Objective-C protocol forward declaration symbol.
+    ObjCForwardProtocolDeclaration *newObjCForwardProtocolDeclaration(unsigned sourceLocation, Name *name = 0);
+
     Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
     Identifier *findOrInsertIdentifier(const char *chars);
 
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 616d2ed3e2a..b7151055a33 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -2894,48 +2894,41 @@ bool Parser::parseObjCProtocolExpression(ExpressionAST *&node)
     return true;
 }
 
-bool Parser::parseObjCSelectorExpression(ExpressionAST *&)
+bool Parser::parseObjCSelectorExpression(ExpressionAST *&node)
 {
     if (LA() != T_AT_SELECTOR)
         return false;
 
-    /*unsigned selector_token = */consumeToken();
-    unsigned lparen_token = 0, rparen_token = 0;
-    match(T_LPAREN, &lparen_token);
-
-    if (LA() == T_COLON || LA() == T_COLON_COLON) {
-        consumeToken();
-
-        if (LA() == T_RPAREN) {
-            _translationUnit->warning(cursor(),
-                                      "error expended a selector");
-            match(T_RPAREN, &rparen_token);
-            return true;
-        }
-    } else if (lookAtObjCSelector()) {
-        unsigned start = cursor();
-        consumeToken();
-        if (LA() != T_RPAREN)
-            rewind(start);
-        else {
-            match(T_RPAREN, &rparen_token);
-            return true;
-        }
-    }
+    ObjCSelectorExpressionAST *ast = new (_pool) ObjCSelectorExpressionAST;
+    ast->selector_token = consumeToken();
+    match(T_LPAREN, &(ast->lparen_token));
 
-    while (lookAtObjCSelector()) {
-        unsigned selector_token = 0;
-        parseObjCSelector(selector_token);
-        if (LA() == T_COLON)
-            consumeToken();
-        else {
-            _translationUnit->error(cursor(),
-                                    "expected :");
-            break;
+    unsigned identifier_token = 0;
+    match(T_IDENTIFIER, &identifier_token);
+    if (LA() == T_COLON) {
+        ObjCSelectorWithArgumentsAST *args = new (_pool) ObjCSelectorWithArgumentsAST;
+        ast->selector = args;
+        ObjCSelectorArgumentListAST *last = new (_pool) ObjCSelectorArgumentListAST;
+        args->selector_arguments = last;
+        last->argument = new (_pool) ObjCSelectorArgumentAST;
+        last->argument->name_token = identifier_token;
+        last->argument->colon_token = consumeToken();
+
+        while (LA() != T_RPAREN) {
+            last->next = new (_pool) ObjCSelectorArgumentListAST;
+            last = last->next;
+            last->argument = new (_pool) ObjCSelectorArgumentAST;
+            match(T_IDENTIFIER, &(last->argument->name_token));
+            match(T_COLON, &(last->argument->colon_token));
         }
+    } else {
+        ObjCSelectorWithoutArgumentsAST *args = new (_pool) ObjCSelectorWithoutArgumentsAST;
+        ast->selector = args;
+        args->name_token = identifier_token;
     }
 
-    match(T_RPAREN, &rparen_token);
+    match(T_RPAREN, &(ast->rparen_token));
+    node = ast;
     return true;
 }
 
@@ -3923,7 +3916,8 @@ bool Parser::parseObjCClassDeclaration(DeclarationAST *&node)
     match(T_IDENTIFIER, &identifier_token);
 
     ast->identifier_list = new (_pool) IdentifierListAST;
-    ast->identifier_list->identifier_token = identifier_token;
+    ast->identifier_list->name = new (_pool) SimpleNameAST;
+    ast->identifier_list->name->identifier_token = identifier_token;
     IdentifierListAST **nextId = &(ast->identifier_list->next);
 
     while (LA() == T_COMMA) {
@@ -3932,7 +3926,8 @@ bool Parser::parseObjCClassDeclaration(DeclarationAST *&node)
 
         *nextId = new (_pool) IdentifierListAST;
         (*nextId)->comma_token = comma_token;
-        (*nextId)->identifier_token = identifier_token;
+        (*nextId)->name = new (_pool) SimpleNameAST;
+        (*nextId)->name->identifier_token = identifier_token;
         nextId = &((*nextId)->next);
     }
 
@@ -4006,10 +4001,11 @@ bool Parser::parseObjCInterface(DeclarationAST *&node,
         return true;
     } else {
         // a class interface declaration
-        ObjCClassInterfaceDeclarationAST *ast = new (_pool) ObjCClassInterfaceDeclarationAST;
+        ObjCClassInterfaceDefinitionAST *ast = new (_pool) ObjCClassInterfaceDefinitionAST;
         ast->attributes = attributes;
         ast->interface_token = objc_interface_token;
-        ast->class_identifier_token = identifier_token;
+        ast->class_name = new (_pool) SimpleNameAST;
+        ast->class_name->identifier_token = identifier_token;
 
         if (LA() == T_COLON) {
             ast->colon_token = consumeToken();
@@ -4059,7 +4055,8 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node,
         ast->attributes = attributes;
         ast->protocol_token = protocol_token;
         ast->identifier_list = new (_pool) IdentifierListAST;
-        ast->identifier_list->identifier_token = identifier_token;
+        ast->identifier_list->name = new (_pool) SimpleNameAST;
+        ast->identifier_list->name->identifier_token = identifier_token;
         IdentifierListAST **nextId = &(ast->identifier_list->next);
 
         while (LA() == T_COMMA) {
@@ -4068,7 +4065,8 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node,
 
             *nextId = new (_pool) IdentifierListAST;
             (*nextId)->comma_token = comma_token;
-            (*nextId)->identifier_token = identifier_token;
+            (*nextId)->name = new (_pool) SimpleNameAST;
+            (*nextId)->name->identifier_token = identifier_token;
             nextId = &((*nextId)->next);
         }
 
@@ -4080,7 +4078,8 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node,
         ObjCProtocolDefinitionAST *ast = new (_pool) ObjCProtocolDefinitionAST;
         ast->attributes = attributes;
         ast->protocol_token = protocol_token;
-        ast->identifier_token = identifier_token;
+        ast->name = new (_pool) SimpleNameAST;
+        ast->name->identifier_token = identifier_token;
 
         parseObjCProtocolRefs(ast->protocol_refs);
 
@@ -4206,14 +4205,16 @@ bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node)
             ObjCDynamicPropertiesDeclarationAST *ast = new (_pool) ObjCDynamicPropertiesDeclarationAST;
             ast->dynamic_token = consumeToken();
             ast->property_identifiers = new (_pool) IdentifierListAST;
-            match(T_IDENTIFIER, &(ast->property_identifiers->identifier_token));
+            ast->property_identifiers->name = new (_pool) SimpleNameAST;
+            match(T_IDENTIFIER, &(ast->property_identifiers->name->identifier_token));
 
             IdentifierListAST *last = ast->property_identifiers;
             while (LA() == T_COMMA) {
                 last->comma_token = consumeToken();
                 last->next = new (_pool) IdentifierListAST;
                 last = last->next;
-                match(T_IDENTIFIER, &(last->identifier_token));
+                last->name = new (_pool) SimpleNameAST;
+                match(T_IDENTIFIER, &(last->name->identifier_token));
             }
 
             match(T_SEMICOLON, &(ast->semicolon_token));
@@ -4284,7 +4285,8 @@ bool Parser::parseObjCProtocolRefs(ObjCProtocolRefsAST *&node)
     unsigned identifier_token = 0;
     match(T_IDENTIFIER, &identifier_token);
     ast->identifier_list = new (_pool) IdentifierListAST;
-    ast->identifier_list->identifier_token = identifier_token;
+    ast->identifier_list->name = new (_pool) SimpleNameAST;
+    ast->identifier_list->name->identifier_token = identifier_token;
     IdentifierListAST **nextId = &(ast->identifier_list->next);
 
     while (LA() == T_COMMA) {
@@ -4293,7 +4295,8 @@ bool Parser::parseObjCProtocolRefs(ObjCProtocolRefsAST *&node)
 
         *nextId = new (_pool) IdentifierListAST;
         (*nextId)->comma_token = comma_token;
-        (*nextId)->identifier_token = identifier_token;
+        (*nextId)->name = new (_pool) SimpleNameAST;
+        (*nextId)->name->identifier_token = identifier_token;
         nextId = &((*nextId)->next);
     }
 
@@ -4422,15 +4425,15 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *a
     if (LA() == T_LPAREN) {
         match(T_LPAREN, &(ast->lparen_token));
 
-        ObjcPropertyAttributeAST *property_attribute = 0;
+        ObjCPropertyAttributeAST *property_attribute = 0;
         if (parseObjCPropertyAttribute(property_attribute)) {
-            ast->property_attributes = new (_pool) ObjcPropertyAttributeListAST;
+            ast->property_attributes = new (_pool) ObjCPropertyAttributeListAST;
             ast->property_attributes->attr = property_attribute;
-            ObjcPropertyAttributeListAST *last = ast->property_attributes;
+            ObjCPropertyAttributeListAST *last = ast->property_attributes;
 
             while (LA() == T_COMMA) {
                 last->comma_token = consumeToken();
-                last->next = new (_pool) ObjcPropertyAttributeListAST;
+                last->next = new (_pool) ObjCPropertyAttributeListAST;
                 last = last->next;
                 parseObjCPropertyAttribute(last->attr);
             }
@@ -4461,17 +4464,28 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
     parseObjCTypeName(ast->type_name);
 
     if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) {
+        ObjCSelectorArgumentAST *argument = 0;
         ObjCMessageArgumentDeclarationAST *declaration = 0;
-        parseObjCKeywordDeclaration(declaration);
+        parseObjCKeywordDeclaration(argument, declaration);
+
+        ObjCSelectorWithArgumentsAST *sel = new (_pool) ObjCSelectorWithArgumentsAST;
+        ast->selector = sel;
+        ObjCSelectorArgumentListAST *lastSel = new (_pool) ObjCSelectorArgumentListAST;
+        sel->selector_arguments = lastSel;
+        sel->selector_arguments->argument = argument;
 
         ast->arguments = new (_pool) ObjCMessageArgumentDeclarationListAST;
         ast->arguments->argument_declaration = declaration;
-        ObjCMessageArgumentDeclarationListAST **last = &(ast->arguments);
+        ObjCMessageArgumentDeclarationListAST *lastArg = ast->arguments;
+
+        while (parseObjCKeywordDeclaration(argument, declaration)) {
+            lastSel->next = new (_pool) ObjCSelectorArgumentListAST;
+            lastSel = lastSel->next;
+            lastSel->argument = argument;
 
-        while (parseObjCKeywordDeclaration(declaration)) {
-            (*last)->next = new (_pool) ObjCMessageArgumentDeclarationListAST;
-            last = &((*last)->next);
-            (*last)->argument_declaration = declaration;
+            lastArg->next = new (_pool) ObjCMessageArgumentDeclarationListAST;
+            lastArg = lastArg->next;
+            lastArg->argument_declaration = declaration;
         }
 
         // TODO EV: get this in the ast
@@ -4487,9 +4501,9 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
             parseParameterDeclaration(parameter_declaration);
         }
     } else if (lookAtObjCSelector()) {
-        ast->arguments = new (_pool) ObjCMessageArgumentDeclarationListAST;
-        ast->arguments->argument_declaration = new (_pool) ObjCMessageArgumentDeclarationAST;
-        parseObjCSelector(ast->arguments->argument_declaration->param_selector_token);
+        ObjCSelectorWithoutArgumentsAST *sel = new (_pool) ObjCSelectorWithoutArgumentsAST;
+        parseObjCSelector(sel->name_token);
+        ast->selector = sel;
     } else {
         _translationUnit->error(cursor(), "expected a selector");
     }
@@ -4510,18 +4524,31 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
 // objc-property-attribute ::= retain
 // objc-property-attribute ::= copy
 // objc-property-attribute ::= nonatomic
-bool Parser::parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node)
+bool Parser::parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node)
 {
     if (LA() != T_IDENTIFIER)
         return false;
 
-    node = new (_pool) ObjcPropertyAttributeAST;
+    node = new (_pool) ObjCPropertyAttributeAST;
     match(T_IDENTIFIER, &(node->attribute_identifier_token));
     if (LA() == T_EQUAL) {
         node->equals_token = consumeToken();
-        match(T_IDENTIFIER, &(node->method_selector_identifier_token));
-        if (LA() == T_COLON)
-            node->colon_token = consumeToken();
+
+        unsigned identifier_token = 0;
+        match(T_IDENTIFIER, &identifier_token);
+
+        if (LA() == T_COLON) {
+            ObjCSelectorWithArgumentsAST *selector = new (_pool) ObjCSelectorWithArgumentsAST;
+            selector->selector_arguments = new (_pool) ObjCSelectorArgumentListAST;
+            selector->selector_arguments->argument = new (_pool) ObjCSelectorArgumentAST;
+            selector->selector_arguments->argument->name_token = identifier_token;
+            selector->selector_arguments->argument->colon_token = consumeToken();
+            node->method_selector = selector;
+        } else {
+            ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST;
+            selector->name_token = identifier_token;
+            node->method_selector = selector;
+        }
     }
 
     return true;
@@ -4556,24 +4583,25 @@ 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(ObjCMessageArgumentDeclarationAST *&node)
+bool Parser::parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, ObjCMessageArgumentDeclarationAST *&node)
 {
     if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON)))
         return false;
 
-    ObjCMessageArgumentDeclarationAST *ast = new (_pool) ObjCMessageArgumentDeclarationAST;
+    node = new (_pool) ObjCMessageArgumentDeclarationAST;
+    argument = new (_pool) ObjCSelectorArgumentAST;
 
-    parseObjCSelector(ast->param_selector_token);
-    match(T_COLON, &(ast->colon_token));
-    parseObjCTypeName(ast->type_name);
+    parseObjCSelector(argument->name_token);
+    match(T_COLON, &(argument->colon_token));
 
-    SpecifierAST **attr = &(ast->attributes);
+    parseObjCTypeName(node->type_name);
+
+    SpecifierAST **attr = &(node->attributes);
     while (parseAttributeSpecifier(*attr))
         attr = &(*attr)->next;
 
-    match(T_IDENTIFIER, &(ast->param_name_token));
+    match(T_IDENTIFIER, &(node->param_name_token));
 
-    node = ast;
     return true;
 }
 
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 5fd5253e348..2fc12384f24 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -239,10 +239,10 @@ public:
                                       SpecifierAST *attributes = 0);
     bool parseObjCImplementation(DeclarationAST *&node);
     bool parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node);
-    bool parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node);
+    bool parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node);
     bool parseObjCTypeName(ObjCTypeNameAST *&node);
     bool parseObjCSelector(unsigned &selector_token);
-    bool parseObjCKeywordDeclaration(ObjCMessageArgumentDeclarationAST *&node);
+    bool parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, ObjCMessageArgumentDeclarationAST *&node);
     bool parseObjCTypeQualifiers(unsigned &type_qualifier);
     bool parseObjCContextKeyword(int kind, unsigned &in_token);
 
diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp
index 6f44072302e..23e69decd00 100644
--- a/src/shared/cplusplus/Semantic.cpp
+++ b/src/shared/cplusplus/Semantic.cpp
@@ -69,6 +69,7 @@ public:
           control(control),
           skipFunctionBodies(false),
           visibility(Symbol::Public),
+          ojbcVisibility(Symbol::Protected),
           methodKey(Function::NormalMethod),
           checkSpecifier(0),
           checkDeclaration(0),
@@ -92,6 +93,7 @@ public:
     Control *control;
     bool skipFunctionBodies;
     int visibility;
+    int ojbcVisibility;
     int methodKey;
     CheckSpecifier *checkSpecifier;
     CheckDeclaration *checkDeclaration;
@@ -132,6 +134,9 @@ FullySpecifiedType Semantic::check(PtrOperatorAST *ptrOperators, FullySpecifiedT
                                    Scope *scope)
 { return d->checkDeclarator->check(ptrOperators, type, scope); }
 
+FullySpecifiedType Semantic::check(ObjCMethodPrototypeAST *methodPrototype, Scope *scope)
+{ return d->checkDeclarator->check(methodPrototype, scope); }
+
 FullySpecifiedType Semantic::check(ExpressionAST *expression, Scope *scope)
 { return d->checkExpression->check(expression, scope); }
 
@@ -144,6 +149,9 @@ Name *Semantic::check(NameAST *name, Scope *scope)
 Name *Semantic::check(NestedNameSpecifierAST *name, Scope *scope)
 { return d->checkName->check(name, scope); }
 
+Name *Semantic::check(ObjCSelectorAST *args, Scope *scope)
+{ return d->checkName->check(args, scope); }
+
 bool Semantic::skipFunctionBodies() const
 { return d->skipFunctionBodies; }
 
@@ -160,6 +168,16 @@ int Semantic::switchVisibility(int visibility)
     return previousVisibility;
 }
 
+int Semantic::currentObjCVisibility() const
+{ return d->ojbcVisibility; }
+
+int Semantic::switchObjCVisibility(int visibility)
+{
+    int previousOjbCVisibility = d->ojbcVisibility;
+    d->ojbcVisibility = visibility;
+    return previousOjbCVisibility;
+}
+
 int Semantic::currentMethodKey() const
 { return d->methodKey; }
 
@@ -186,6 +204,35 @@ int Semantic::visibilityForAccessSpecifier(int tokenKind) const
     }
 }
 
+int Semantic::visibilityForObjCAccessSpecifier(int tokenKind) const
+{
+    switch (tokenKind) {
+    case T_AT_PUBLIC:
+        return Symbol::Public;
+    case T_AT_PROTECTED:
+        return Symbol::Protected;
+    case T_AT_PRIVATE:
+        return Symbol::Private;
+    case T_AT_PACKAGE:
+        return Symbol::Package;
+    default:
+        return Symbol::Protected;
+    }
+}
+
+bool Semantic::isObjCClassMethod(int tokenKind) const
+{
+    switch (tokenKind) {
+    case T_PLUS:
+        return true;
+    case T_MINUS:
+        return false;
+    default:
+        // TODO EV: assert here?
+        return false;
+    }
+}
+
 int Semantic::visibilityForClassKey(int tokenKind) const
 {
     switch (tokenKind) {
diff --git a/src/shared/cplusplus/Semantic.h b/src/shared/cplusplus/Semantic.h
index 9b9a4195be8..113796bafb2 100644
--- a/src/shared/cplusplus/Semantic.h
+++ b/src/shared/cplusplus/Semantic.h
@@ -74,6 +74,8 @@ public:
     FullySpecifiedType check(PtrOperatorAST *ptrOperators, FullySpecifiedType type,
                              Scope *scope);
 
+    FullySpecifiedType check(ObjCMethodPrototypeAST *methodPrototype, Scope *scope);
+
     FullySpecifiedType check(ExpressionAST *expression, Scope *scope);
 
     void check(DeclarationAST *declaration, Scope *scope, Scope *templateParameters = 0);
@@ -84,17 +86,24 @@ public:
 
     Name *check(NestedNameSpecifierAST *name, Scope *scope);
 
+    Name *check(ObjCSelectorAST *args, Scope *scope);
+
     bool skipFunctionBodies() const;
     void setSkipFunctionBodies(bool skipFunctionBodies);
 
     int currentVisibility() const;
     int switchVisibility(int visibility);
 
+    int currentObjCVisibility() const;
+    int switchObjCVisibility(int visibility);
+
     int currentMethodKey() const;
     int switchMethodKey(int methodKey);
 
     int visibilityForClassKey(int tokenKind) const;
     int visibilityForAccessSpecifier(int tokenKind) const;
+    int visibilityForObjCAccessSpecifier(int tokenKind) const;
+    bool isObjCClassMethod(int tokenKind) const;
 
 private:
     class Data;
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
index 31c33039255..37909bf98b1 100644
--- a/src/shared/cplusplus/Symbol.cpp
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -453,4 +453,16 @@ bool Symbol::isArgument() const
 bool Symbol::isBaseClass() const
 { return asBaseClass() != 0; }
 
+bool Symbol::isObjCClass() const
+{ return asObjCClass() != 0; }
+
+bool Symbol::isObjCForwardClassDeclaration() const
+{ return asObjCForwardClassDeclaration() != 0; }
+
+bool Symbol::isObjCProtocol() const
+{ return asObjCProtocol() != 0; }
+
+bool Symbol::isObjCForwardProtocolDeclaration() const
+{ return asObjCForwardProtocolDeclaration() != 0; }
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index 403deceb123..c34416078d8 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -75,7 +75,8 @@ public:
     enum Visibility {
         Public,
         Protected,
-        Private
+        Private,
+        Package
     };
 
 public:
@@ -209,6 +210,18 @@ public:
     /// Returns true if this Symbol is a ForwardClassDeclaration.
     bool isForwardClassDeclaration() const;
 
+    /// Returns true if this Symbol is a Objective-C Class definition.
+    bool isObjCClass() const;
+
+    /// Returns true if this Symbol is a Objective-C Class forward declaration.
+    bool isObjCForwardClassDeclaration() const;
+
+    /// Returns true if this Symbol is a Objective-C Protocol definition.
+    bool isObjCProtocol() const;
+
+    /// Returns true if this Symbol is a Objective-C Protocol forward declaration.
+    bool isObjCForwardProtocolDeclaration() const;
+
     virtual const ScopedSymbol *asScopedSymbol() const { return 0; }
     virtual const Enum *asEnum() const { return 0; }
     virtual const Function *asFunction() const { return 0; }
@@ -221,6 +234,10 @@ public:
     virtual const Argument *asArgument() const { return 0; }
     virtual const BaseClass *asBaseClass() const { return 0; }
     virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; }
+    virtual const ObjCClass *asObjCClass() const { return 0; }
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const { return 0; }
+    virtual const ObjCProtocol *asObjCProtocol() const { return 0; }
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const { return 0; }
 
     virtual ScopedSymbol *asScopedSymbol() { return 0; }
     virtual Enum *asEnum() { return 0; }
@@ -234,6 +251,10 @@ public:
     virtual Argument *asArgument() { return 0; }
     virtual BaseClass *asBaseClass() { return 0; }
     virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; }
+    virtual ObjCClass *asObjCClass() { return 0; }
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return 0; }
+    virtual ObjCProtocol *asObjCProtocol() { return 0; }
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() { return 0; }
 
     /// Returns this Symbol's type.
     virtual FullySpecifiedType type() const = 0;
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
index 552dd05052c..cfac498887b 100644
--- a/src/shared/cplusplus/SymbolVisitor.h
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -79,6 +79,12 @@ public:
     virtual bool visit(Class *) { return true; }
     virtual bool visit(Block *) { return true; }
     virtual bool visit(ForwardClassDeclaration *) { return true; }
+
+    // Objective-C
+    virtual bool visit(ObjCClass *) { return true; }
+    virtual bool visit(ObjCForwardClassDeclaration *) { return true; }
+    virtual bool visit(ObjCProtocol *) { return true; }
+    virtual bool visit(ObjCForwardProtocolDeclaration *) { return true; }
 };
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index dddc1539288..d7446f98525 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -553,4 +553,138 @@ void Class::visitSymbol0(SymbolVisitor *visitor)
     }
 }
 
+ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
+        ScopedSymbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCClass::~ObjCClass()
+{}
+
+FullySpecifiedType ObjCClass::type() const
+{ return FullySpecifiedType(const_cast<ObjCClass *>(this)); }
+
+bool ObjCClass::isEqualTo(const Type *other) const
+{
+    const ObjCClass *o = other->asObjCClassType();
+    if (!o)
+        return false;
+
+    Name *l = identity();
+    Name *r = o->identity();
+    if (l == r || (l && l->isEqualTo(r)))
+        return true;
+    else
+        return false;
+}
+
+void ObjCClass::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < _baseClasses.size(); ++i)
+            visitSymbol(_baseClasses.at(i), visitor);
+        for (unsigned i = 0; i < _protocols.size(); ++i)
+            visitSymbol(_protocols.at(i), visitor);
+    }
+}
+
+void ObjCClass::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+ObjCProtocol::ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
+        ScopedSymbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCProtocol::~ObjCProtocol()
+{}
+
+FullySpecifiedType ObjCProtocol::type() const
+{ return FullySpecifiedType(const_cast<ObjCProtocol *>(this)); }
+
+bool ObjCProtocol::isEqualTo(const Type *other) const
+{
+    const ObjCProtocol *o = other->asObjCProtocolType();
+    if (!o)
+        return false;
+
+    Name *l = identity();
+    Name *r = o->identity();
+    if (l == r || (l && l->isEqualTo(r)))
+        return true;
+    else
+        return false;
+}
+
+void ObjCProtocol::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < _protocols.size(); ++i)
+            visitSymbol(_protocols.at(i), visitor);
+    }
+}
+
+void ObjCProtocol::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
+        Symbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCForwardClassDeclaration::~ObjCForwardClassDeclaration()
+{}
+
+FullySpecifiedType ObjCForwardClassDeclaration::type() const
+{ return FullySpecifiedType(const_cast<ObjCForwardClassDeclaration *>(this)); }
+
+bool ObjCForwardClassDeclaration::isEqualTo(const Type *other) const
+{
+    if (const ObjCForwardClassDeclaration *otherForward = other->asObjCForwardClassDeclarationType()) {
+        if (name() == otherForward->name())
+            return true;
+        else if (name() && otherForward->name())
+            return name()->isEqualTo(otherForward->name());
+
+        return false;
+    }
+    return false;
+}
+
+void ObjCForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ObjCForwardClassDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name):
+        Symbol(translationUnit, sourceLocation, name)
+{
+}
+
+ObjCForwardProtocolDeclaration::~ObjCForwardProtocolDeclaration()
+{}
+
+FullySpecifiedType ObjCForwardProtocolDeclaration::type() const
+{ return FullySpecifiedType(const_cast<ObjCForwardProtocolDeclaration *>(this)); }
+
+bool ObjCForwardProtocolDeclaration::isEqualTo(const Type *other) const
+{
+    if (const ObjCForwardProtocolDeclaration *otherForward = other->asObjCForwardProtocolDeclarationType()) {
+        if (name() == otherForward->name())
+            return true;
+        else if (name() && otherForward->name())
+            return name()->isEqualTo(otherForward->name());
+
+        return false;
+    }
+    return false;
+}
+
+void ObjCForwardProtocolDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ObjCForwardProtocolDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index 03a66778d74..a35dbf30b56 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -463,6 +463,133 @@ private:
     Array<BaseClass *> _baseClasses;
 };
 
+class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration: public Symbol, public Type
+{
+public:
+    ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+    virtual ~ObjCForwardProtocolDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    // Type's interface
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const
+    { return this; }
+
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration()
+    { return this; }
+
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const
+    { return this; }
+
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+
+private:
+};
+
+class CPLUSPLUS_EXPORT ObjCProtocol: public ScopedSymbol, public Type
+{
+public:
+    ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+    virtual ~ObjCProtocol();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    // Type's interface
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const ObjCProtocol *asObjCProtocol() const
+    { return this; }
+
+    virtual ObjCProtocol *asObjCProtocol()
+    { return this; }
+
+    virtual const ObjCProtocol *asObjCProtocolType() const
+    { return this; }
+
+    virtual ObjCProtocol *asObjCProtocolType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+
+private:
+    Array<ObjCProtocol *> _protocols;
+};
+
+class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration: public Symbol, public Type
+{
+public:
+    ObjCForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+    virtual ~ObjCForwardClassDeclaration();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    // Type's interface
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const
+    { return this; }
+
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration()
+    { return this; }
+
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const
+    { return this; }
+
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+
+private:
+};
+
+class CPLUSPLUS_EXPORT ObjCClass: public ScopedSymbol, public Type
+{
+public:
+    ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+    virtual ~ObjCClass();
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    // Type's interface
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const ObjCClass *asObjCClass() const
+    { return this; }
+
+    virtual ObjCClass *asObjCClass()
+    { return this; }
+
+    virtual const ObjCClass *asObjCClassType() const
+    { return this; }
+
+    virtual ObjCClass *asObjCClassType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+
+private:
+    Array<ObjCClass *> _baseClasses;
+    Array<ObjCProtocol *> _protocols;
+};
+
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
 
diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp
index 5f5809c0c64..8b41f36407e 100644
--- a/src/shared/cplusplus/Type.cpp
+++ b/src/shared/cplusplus/Type.cpp
@@ -101,6 +101,18 @@ bool Type::isEnumType() const
 bool Type::isForwardClassDeclarationType() const
 { return asForwardClassDeclarationType() != 0; }
 
+bool Type::isObjCClassType() const
+{ return asObjCClassType() != 0; }
+
+bool Type::isObjCForwardClassDeclarationType() const
+{ return asObjCForwardClassDeclarationType() != 0; }
+
+bool Type::isObjCProtocolType() const
+{ return asObjCProtocolType() != 0; }
+
+bool Type::isObjCForwardProtocolDeclarationType() const
+{ return asObjCForwardProtocolDeclarationType() != 0; }
+
 void Type::accept(TypeVisitor *visitor)
 {
     if (visitor->preVisit(this))
diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h
index a0067bd0965..1ddc67eb58a 100644
--- a/src/shared/cplusplus/Type.h
+++ b/src/shared/cplusplus/Type.h
@@ -77,6 +77,10 @@ public:
     bool isClassType() const;
     bool isEnumType() const;
     bool isForwardClassDeclarationType() const;
+    bool isObjCClassType() const;
+    bool isObjCForwardClassDeclarationType() const;
+    bool isObjCProtocolType() const;
+    bool isObjCForwardProtocolDeclarationType() const;
 
     virtual const VoidType *asVoidType() const { return 0; }
     virtual const IntegerType *asIntegerType() const { return 0; }
@@ -91,6 +95,10 @@ public:
     virtual const Class *asClassType() const { return 0; }
     virtual const Enum *asEnumType() const { return 0; }
     virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
+    virtual const ObjCClass *asObjCClassType() const { return 0; }
+    virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() const { return 0; }
+    virtual const ObjCProtocol *asObjCProtocolType() const { return 0; }
+    virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() const { return 0; }
 
     virtual VoidType *asVoidType() { return 0; }
     virtual IntegerType *asIntegerType() { return 0; }
@@ -105,6 +113,10 @@ public:
     virtual Class *asClassType() { return 0; }
     virtual Enum *asEnumType() { return 0; }
     virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
+    virtual ObjCClass *asObjCClassType() { return 0; }
+    virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclarationType() { return 0; }
+    virtual ObjCProtocol *asObjCProtocoTypel() { return 0; }
+    virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclarationType() { return 0; }
 
     void accept(TypeVisitor *visitor);
     static void accept(Type *type, TypeVisitor *visitor);
diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h
index a29af362db7..a0de7065570 100644
--- a/src/shared/cplusplus/TypeVisitor.h
+++ b/src/shared/cplusplus/TypeVisitor.h
@@ -81,6 +81,10 @@ public:
     virtual void visit(Class *) {}
     virtual void visit(Enum *) {}
     virtual void visit(ForwardClassDeclaration *) {}
+    virtual void visit(ObjCClass *) {}
+    virtual void visit(ObjCProtocol *) {}
+    virtual void visit(ObjCForwardClassDeclaration *) {}
+    virtual void visit(ObjCForwardProtocolDeclaration *) {}
 };
 
 CPLUSPLUS_END_NAMESPACE
-- 
GitLab