diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 51a3c1ac34899523dc50593dd570c0f4abe65c1c..e8ecfa07cdba7fbcd5948c1d94ee04d05ed4d0c2 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -2241,6 +2241,9 @@ unsigned ObjcPropertyAttributeListAST::lastToken() const
 
 unsigned ObjCPropertyDeclarationAST::firstToken() const
 {
+    if (attributes)
+        return attributes->firstToken();
+
     return property_token;
 }
 
@@ -2316,4 +2319,150 @@ unsigned ObjCMethodPrototypeAST::lastToken() const
         return method_type_token + 1;
 }
 
+unsigned ObjCClassImplementationAST::firstToken() const
+{
+    return implementation_token;
+}
+
+unsigned ObjCClassImplementationAST::lastToken() const
+{
+    if (end_token)
+        return end_token + 1;
+
+    for (DeclarationListAST *it = declarations; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (inst_vars_decl)
+        return inst_vars_decl->lastToken();
+    if (super_class_identifier)
+        return super_class_identifier + 1;
+    if (colon_token)
+        return colon_token + 1;
+    if (class_identifier)
+        return class_identifier + 1;
+
+    return implementation_token + 1;
+}
+
+unsigned ObjCCategoryImplementationAST::firstToken() const
+{
+    return implementation_token;
+}
+
+unsigned ObjCCategoryImplementationAST::lastToken() const
+{
+    if (end_token)
+        return end_token + 1;
+
+    for (DeclarationListAST *it = declarations; it; it = it->next) {
+        if (! it->next)
+            return it->lastToken();
+    }
+
+    if (rparen_token)
+        return rparen_token + 1;
+    if (category_name_token)
+        return category_name_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (class_identifier)
+        return class_identifier + 1;
+
+    return implementation_token + 1;
+}
+
+unsigned ObjCSynthesizedPropertyAST::firstToken() const
+{
+    if (property_identifier)
+        return property_identifier;
+    else if (equals_token)
+        return equals_token;
+    else
+        return property_alias_identifier;
+}
+
+unsigned ObjCSynthesizedPropertyAST::lastToken() const
+{
+    if (property_alias_identifier)
+        return property_alias_identifier + 1;
+    else if (equals_token)
+        return equals_token + 1;
+    else
+        return property_identifier + 1;
+}
+
+unsigned ObjCSynthesizedPropertyListAST::firstToken() const
+{
+    if (synthesized_property)
+        return synthesized_property->firstToken();
+    else
+        return comma_token;
+}
+
+unsigned ObjCSynthesizedPropertyListAST::lastToken() const
+{
+    for (const ObjCSynthesizedPropertyListAST *it = this; it; it = it->next) {
+        if (! it->next && it->synthesized_property) {
+            return it->synthesized_property->lastToken();
+        }
+    }
+    // ### assert?
+    return 0;
+}
+
+unsigned ObjCSynthesizedPropertiesDeclarationAST::firstToken() const
+{
+    return synthesized_token;
+}
+
+unsigned ObjCSynthesizedPropertiesDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else if (property_identifiers)
+        return property_identifiers->lastToken();
+    else
+        return synthesized_token + 1;
+}
+
+unsigned ObjCDynamicPropertiesDeclarationAST::firstToken() const
+{
+    return dynamic_token;
+}
+
+unsigned ObjCDynamicPropertiesDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else if (property_identifiers)
+        return property_identifiers->lastToken();
+    else
+        return dynamic_token + 1;
+}
+
+unsigned ObjCFastEnumerationAST::firstToken() const
+{
+    return for_token;
+}
+
+unsigned ObjCFastEnumerationAST::lastToken() const
+{
+    if (body_statement)
+        return body_statement->lastToken();
+    else if (rparen_token)
+        return rparen_token + 1;
+    else if (fast_enumeratable_expression)
+        return fast_enumeratable_expression->lastToken();
+    else if (in_token)
+        return in_token + 1;
+    else if (initializer)
+        return initializer->lastToken();
+    else if (lparen_token)
+        return lparen_token + 1;
+    else
+        return for_token + 1;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 898fd16c87df3c8c771e2cba744fb7190fb2bf11..f6ab2626eb6c6a3d8a24497f255541d7cbfdd694 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2801,6 +2801,7 @@ protected:
 class CPLUSPLUS_EXPORT ObjCPropertyDeclarationAST: public DeclarationAST
 {
 public:
+    SpecifierAST *attributes;
     unsigned property_token;
     unsigned lparen_token;
     ObjcPropertyAttributeListAST *property_attributes;
@@ -2882,6 +2883,158 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
+class CPLUSPLUS_EXPORT ObjCClassImplementationAST: public DeclarationAST
+{
+public:
+    unsigned implementation_token;
+    unsigned class_identifier;
+    unsigned colon_token;
+    unsigned super_class_identifier;
+    ObjCInstanceVariablesDeclarationAST *inst_vars_decl;
+    DeclarationListAST *declarations;
+    unsigned end_token;
+
+public:
+    virtual ObjCClassImplementationAST *asObjCClassImplementation()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCClassImplementationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCCategoryImplementationAST: public DeclarationAST
+{
+public:
+    unsigned implementation_token;
+    unsigned class_identifier;
+    unsigned lparen_token;
+    unsigned category_name_token;
+    unsigned rparen_token;
+    DeclarationListAST *declarations;
+    unsigned end_token;
+
+public:
+    virtual ObjCCategoryImplementationAST *asObjCCategoryImplementation()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCCategoryImplementationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynthesizedPropertyAST: public AST
+{
+public:
+    unsigned property_identifier;
+    unsigned equals_token;
+    unsigned property_alias_identifier;
+
+public:
+    virtual ObjCSynthesizedPropertyAST *asObjCSynthesizedProperty()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynthesizedPropertyAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynthesizedPropertyListAST: public AST
+{
+public:
+    ObjCSynthesizedPropertyAST *synthesized_property;
+    unsigned comma_token;
+    ObjCSynthesizedPropertyListAST *next;
+
+public:
+    virtual ObjCSynthesizedPropertyListAST *asObjCSynthesizedPropertyList()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynthesizedPropertyListAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCSynthesizedPropertiesDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned synthesized_token;
+    ObjCSynthesizedPropertyListAST *property_identifiers;
+    unsigned semicolon_token;
+
+public:
+    virtual ObjCSynthesizedPropertiesDeclarationAST *asObjCSynthesizedPropertiesDeclaration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCSynthesizedPropertiesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCDynamicPropertiesDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned dynamic_token;
+    IdentifierListAST *property_identifiers;
+    unsigned semicolon_token;
+
+public:
+    virtual ObjCDynamicPropertiesDeclarationAST *asObjCDynamicPropertiesDeclaration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCDynamicPropertiesDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCFastEnumerationAST: public StatementAST
+{
+public:
+    unsigned for_token;
+    unsigned lparen_token;
+    StatementAST *initializer;
+    unsigned in_token;
+    ExpressionAST *fast_enumeratable_expression;
+    unsigned rparen_token;
+    StatementAST *body_statement;
+
+public:
+    virtual ObjCFastEnumerationAST *asObjCFastEnumeration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCFastEnumerationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
 
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 385958d47c6a11441f07427afe356e78b86912ff..1e160ae2747a583c0824fd92e6d39c7a036adda5 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1382,6 +1382,7 @@ ObjcPropertyAttributeListAST *ObjcPropertyAttributeListAST::clone(MemoryPool *po
 ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const
 {
     ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST;
+    if (attributes) ast->attributes = attributes->clone(pool);
     ast->property_token = property_token;
     ast->lparen_token = lparen_token;
     if (property_attributes) ast->property_attributes = property_attributes->clone(pool);
@@ -1419,4 +1420,82 @@ ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+ObjCClassImplementationAST *ObjCClassImplementationAST::clone(MemoryPool *pool) const
+{
+    ObjCClassImplementationAST *ast = new (pool) ObjCClassImplementationAST;
+    ast->implementation_token = implementation_token;
+    ast->class_identifier = class_identifier;
+    ast->colon_token = colon_token;
+    ast->super_class_identifier = super_class_identifier;
+    if (inst_vars_decl) ast->inst_vars_decl = inst_vars_decl->clone(pool);
+    if (declarations) ast->declarations = declarations->clone(pool);
+    ast->end_token = end_token;
+    return ast;
+}
+
+ObjCCategoryImplementationAST *ObjCCategoryImplementationAST::clone(MemoryPool *pool) const
+{
+    ObjCCategoryImplementationAST *ast = new (pool) ObjCCategoryImplementationAST;
+    ast->implementation_token = implementation_token;
+    ast->class_identifier = class_identifier;
+    ast->lparen_token = lparen_token;
+    ast->category_name_token = category_name_token;
+    ast->rparen_token = rparen_token;
+    if (declarations) ast->declarations = declarations->clone(pool);
+    ast->end_token = end_token;
+    return ast;
+}
+
+ObjCSynthesizedPropertyAST *ObjCSynthesizedPropertyAST::clone(MemoryPool *pool) const
+{
+    ObjCSynthesizedPropertyAST *ast = new (pool) ObjCSynthesizedPropertyAST;
+    ast->property_identifier = property_identifier;
+    ast->equals_token = equals_token;
+    ast->property_alias_identifier = property_alias_identifier;
+    return ast;
+}
+
+ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool *pool) const
+{
+    ObjCSynthesizedPropertyListAST *ast = new (pool) ObjCSynthesizedPropertyListAST;
+    if (synthesized_property) ast->synthesized_property = synthesized_property->clone(pool);
+    ast->comma_token = comma_token;
+    if (next) ast->next = next->clone(pool);
+    return ast;
+}
+
+ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCSynthesizedPropertiesDeclarationAST *ast = new (pool) ObjCSynthesizedPropertiesDeclarationAST;
+    ast->synthesized_token = synthesized_token;
+    if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCDynamicPropertiesDeclarationAST *ast = new (pool) ObjCDynamicPropertiesDeclarationAST;
+    ast->dynamic_token = dynamic_token;
+    if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
+{
+    ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST;
+    ast->for_token = for_token;
+    ast->lparen_token = lparen_token;
+    if (initializer)
+        ast->initializer = initializer->clone(pool);
+    ast->in_token = in_token;
+    if (fast_enumeratable_expression)
+        ast->fast_enumeratable_expression = fast_enumeratable_expression->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (body_statement)
+        ast->body_statement = body_statement->clone(pool);
+    return ast;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index b6b21ad357191a57f5a69fad1a5523b3cf8c67f5..98fe8a84adb4184788ad742edc701d58fa42c62a 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1318,6 +1318,8 @@ void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCPropertyDeclarationAST:
+        for (SpecifierAST *it = attributes; it; it = it->next)
+            accept(it, visitor);
         for (ObjcPropertyAttributeListAST *it = property_attributes; it; it = it->next)
             accept(it, visitor);
         if (simple_declaration)
@@ -1366,4 +1368,85 @@ void ObjCMethodPrototypeAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void ObjCClassImplementationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCClassImplementationAST
+        if (inst_vars_decl)
+            accept(inst_vars_decl, visitor);
+        for (DeclarationListAST *it = declarations; it; it = it->next)
+            accept(it, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCCategoryImplementationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCCategoryImplementationAST
+        for (DeclarationListAST *it = declarations; it; it = it->next)
+            accept(it, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynthesizedPropertyAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCSynthesizedPropertyAST
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynthesizedPropertyListAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCSynthesizedPropertyListAST
+        if (synthesized_property)
+            accept(synthesized_property, visitor);
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCSynthesizedPropertiesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCSynthesizedPropertiesDeclarationAST
+        for (ObjCSynthesizedPropertyListAST *it = property_identifiers; it; it = it->next)
+            accept(it, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCDynamicPropertiesDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCDynamicPropertiesDeclarationAST
+        for (IdentifierListAST *it = property_identifiers; it; it = it->next)
+            accept(it, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCFastEnumerationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCFastEnumerationAST
+        if (initializer)
+            accept(initializer, visitor);
+        if (fast_enumeratable_expression)
+            accept(fast_enumeratable_expression, visitor);
+        if (body_statement)
+            accept(body_statement, visitor);
+        // visit StatementAST
+    }
+    visitor->endVisit(this);
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index b272c7077a9bc15ce275cf39ad9ba0befcc9eeba..5279d290f502916a4816eb484bf222b0a1b0e454 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -217,6 +217,13 @@ public:
     virtual bool visit(ObjCMethodPrototypeAST *) { return true; }
     virtual bool visit(ObjCMessageArgumentDeclarationListAST *) { return true; }
     virtual bool visit(ObjCMessageArgumentDeclarationAST *) { return true; }
+    virtual bool visit(ObjCClassImplementationAST *) { return true; }
+    virtual bool visit(ObjCCategoryImplementationAST *) { return true; }
+    virtual bool visit(ObjCSynthesizedPropertyAST *) { return true; }
+    virtual bool visit(ObjCSynthesizedPropertyListAST *) { return true; }
+    virtual bool visit(ObjCSynthesizedPropertiesDeclarationAST *) { return true; }
+    virtual bool visit(ObjCDynamicPropertiesDeclarationAST *) { return true; }
+    virtual bool visit(ObjCFastEnumerationAST *) { return true; }
 
     virtual bool visit(DeclarationListAST *) { return true; }
     virtual void endVisit(DeclarationListAST *) { }
@@ -345,6 +352,13 @@ public:
     virtual void endVisit(ObjCMethodPrototypeAST *) { }
     virtual void endVisit(ObjCMessageArgumentDeclarationListAST *) { }
     virtual void endVisit(ObjCMessageArgumentDeclarationAST *) { }
+    virtual void endVisit(ObjCClassImplementationAST *) { }
+    virtual void endVisit(ObjCCategoryImplementationAST *) { }
+    virtual void endVisit(ObjCSynthesizedPropertyAST *) { }
+    virtual void endVisit(ObjCSynthesizedPropertyListAST *) { }
+    virtual void endVisit(ObjCSynthesizedPropertiesDeclarationAST *) { }
+    virtual void endVisit(ObjCDynamicPropertiesDeclarationAST *) { }
+    virtual void endVisit(ObjCFastEnumerationAST *) { }
 
 private:
     Control *_control;
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index f123e736897b5a170cb65b93200f31464780cbdf..5416856614c641251fa7b8681a45cd86de2e4788 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -190,6 +190,13 @@ class ObjcPropertyAttributeAST;
 class ObjCMethodPrototypeAST;
 class ObjCMessageArgumentDeclarationListAST;
 class ObjCMessageArgumentDeclarationAST;
+class ObjCCategoryImplementationAST;
+class ObjCClassImplementationAST;
+class ObjCSynthesizedPropertyAST;
+class ObjCSynthesizedPropertyListAST;
+class ObjCSynthesizedPropertiesDeclarationAST;
+class ObjCDynamicPropertiesDeclarationAST;
+class ObjCFastEnumerationAST;
 
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index b75c10d9ddca4e63e769543d202dd80e5b04f813..2856e07622ad15cc683747676cd7dc8a32a8221c 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -63,6 +63,7 @@ Parser::Parser(TranslationUnit *unit)
     : _translationUnit(unit),
       _control(_translationUnit->control()),
       _pool(_translationUnit->memoryPool()),
+      _objcInContextKeyword(_control->findOrInsertIdentifier("in")),
       _tokenIndex(1),
       _templateArguments(0),
       _qtMocRunEnabled(false),
@@ -422,7 +423,10 @@ bool Parser::parseDeclaration(DeclarationAST *&node)
         return parseObjCImplementation(node);
 
     case T_AT_END:
-        return parseObjCEnd(node);
+        // TODO: should this be done here, or higher-up?
+        _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell());
+        consumeToken();
+        break;
 
     default: {
         if (_objCEnabled && LA() == T___ATTRIBUTE__) {
@@ -2168,20 +2172,43 @@ bool Parser::parseForeachStatement(StatementAST *&node)
 
 bool Parser::parseForStatement(StatementAST *&node)
 {
-    if (LA() == T_FOR) {
+    if (LA() != T_FOR)
+        return false;
+
+    unsigned for_token = consumeToken();
+    unsigned lparen_token = 0;
+    match(T_LPAREN, &lparen_token);
+    StatementAST *initializer = 0;
+    parseForInitStatement(initializer);
+
+    if (LA() == T_IDENTIFIER && tok().identifier == _objcInContextKeyword) {
+        ObjCFastEnumerationAST *ast = new (_pool) ObjCFastEnumerationAST;
+
+        ast->for_token = for_token;
+        ast->lparen_token = lparen_token;
+        ast->initializer = initializer;
+        ast->in_token = consumeToken();
+        parseExpression(ast->fast_enumeratable_expression);
+        match(T_RPAREN, &ast->rparen_token);
+        parseStatement(ast->body_statement);
+
+        node = ast;
+    } else {
         ForStatementAST *ast = new (_pool) ForStatementAST;
-        ast->for_token = consumeToken();
-        match(T_LPAREN, &ast->lparen_token);
-        parseForInitStatement(ast->initializer);
+
+        ast->for_token = for_token;
+        ast->lparen_token = lparen_token;
+        ast->initializer = initializer;
         parseExpression(ast->condition);
         match(T_SEMICOLON, &ast->semicolon_token);
         parseExpression(ast->expression);
         match(T_RPAREN, &ast->rparen_token);
         parseStatement(ast->statement);
+
         node = ast;
-        return true;
     }
-    return false;
+
+    return true;
 }
 
 bool Parser::parseForInitStatement(StatementAST *&node)
@@ -3951,7 +3978,7 @@ bool Parser::parseObjCInterface(DeclarationAST *&node,
                                     "invalid attributes for category interface declaration");
 
         ObjCCategoryInterfaceDeclarationAST *ast = new (_pool) ObjCCategoryInterfaceDeclarationAST;
-        // XXX: Should the attributes get stored anyway? (for fixing/refactoring purposes maybe...)
+        // TODO: Should the attributes get stored anyway? (for fixing/refactoring purposes maybe...)
         ast->interface_token = objc_interface_token;
         ast->class_identifier_token = identifier_token;
 
@@ -4074,48 +4101,62 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node,
 //                         objc-class-instance-variables-opt
 // objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER T_LPAREN T_IDENTIFIER T_RPAREN
 //
-bool Parser::parseObjCImplementation(DeclarationAST *&)
+bool Parser::parseObjCImplementation(DeclarationAST *&node)
 {
     if (LA() != T_AT_IMPLEMENTATION)
         return false;
 
-    consumeToken();
-
+    unsigned implementation_token = consumeToken();
     unsigned identifier_token = 0;
     match(T_IDENTIFIER, &identifier_token);
 
     if (LA() == T_LPAREN) {
         // a category implementation
-        unsigned lparen_token = 0, rparen_token = 0;
-        unsigned category_name_token = 0;
-        match(T_LPAREN, &lparen_token);
-        match(T_IDENTIFIER, &category_name_token);
-        match(T_RPAREN, &rparen_token);
-        return true;
-    }
+        ObjCCategoryImplementationAST *ast = new (_pool) ObjCCategoryImplementationAST;
+        ast->implementation_token = implementation_token;
+        ast->class_identifier = identifier_token;
 
-    // a class implementation
-    if (LA() == T_COLON) {
-        consumeToken();
-        unsigned super_class_name_token = 0;
-        match(T_IDENTIFIER, &super_class_name_token);
+        match(T_LPAREN, &(ast->lparen_token));
+        match(T_IDENTIFIER, &(ast->category_name_token));
+        match(T_RPAREN, &(ast->rparen_token));
+
+        parseObjCMethodDefinitionList(ast->declarations);
+        match(T_AT_END, &(ast->end_token));
+
+        node = ast;
+    } else {
+        // a class implementation
+        ObjCClassImplementationAST *ast = new (_pool) ObjCClassImplementationAST;
+        ast->implementation_token = implementation_token;
+        ast->class_identifier = identifier_token;
+
+        if (LA() == T_COLON) {
+            ast->colon_token = consumeToken();
+            match(T_IDENTIFIER, &(ast->super_class_identifier));
+        }
+
+        parseObjClassInstanceVariables(ast->inst_vars_decl);
+        parseObjCMethodDefinitionList(ast->declarations);
+        match(T_AT_END, &(ast->end_token));
+
+        node = ast;
     }
 
-    ObjCInstanceVariablesDeclarationAST *inst_vars_decl;
-    parseObjClassInstanceVariables(inst_vars_decl);
-    parseObjCMethodDefinitionList();
     return true;
 }
 
-bool Parser::parseObjCMethodDefinitionList()
+bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node)
 {
+    DeclarationListAST **next = &node;
+
     while (LA() && LA() != T_AT_END) {
         unsigned start = cursor();
+        DeclarationAST *declaration = 0;
 
         switch (LA()) {
         case T_PLUS:
         case T_MINUS:
-            parseObjCMethodDefinition();
+            parseObjCMethodDefinition(declaration);
 
             if (start == cursor())
                 consumeToken();
@@ -4126,7 +4167,9 @@ bool Parser::parseObjCMethodDefinitionList()
             break;
 
         case T_AT_SYNTHESIZE: {
-            consumeToken();
+            ObjCSynthesizedPropertiesDeclarationAST *ast = new (_pool) ObjCSynthesizedPropertiesDeclarationAST;
+            ast->synthesized_token = consumeToken();
+            // TODO EV
             unsigned identifier_token = 0;
             match(T_IDENTIFIER, &identifier_token);
 
@@ -4150,34 +4193,36 @@ bool Parser::parseObjCMethodDefinitionList()
                 }
             }
 
-            unsigned semicolon_token = 0;
-            match(T_SEMICOLON, &semicolon_token);
+            match(T_SEMICOLON, &(ast->semicolon_token));
 
+            declaration = ast;
             break;
         }
 
         case T_AT_DYNAMIC: {
-            consumeToken();
-            unsigned identifier_token = 0;
-            match(T_IDENTIFIER, &identifier_token);
+            ObjCDynamicPropertiesDeclarationAST *ast = new (_pool) ObjCDynamicPropertiesDeclarationAST;
+            ast->dynamic_token = consumeToken();
+            ast->property_identifiers = new (_pool) IdentifierListAST;
+            match(T_IDENTIFIER, &(ast->property_identifiers->identifier_token));
 
+            IdentifierListAST *last = ast->property_identifiers;
             while (LA() == T_COMMA) {
-                consumeToken();
-                match(T_IDENTIFIER, &identifier_token);
+                last->comma_token = consumeToken();
+                last->next = new (_pool) IdentifierListAST;
+                last = last->next;
+                match(T_IDENTIFIER, &(last->identifier_token));
             }
 
-            unsigned semicolon_token = 0;
-            match(T_SEMICOLON, &semicolon_token);
+            match(T_SEMICOLON, &(ast->semicolon_token));
 
+            declaration = ast;
             break;
         }
 
         default:
             if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) {
-                DeclarationAST *declaration = 0;
                 parseDeclaration(declaration);
             } else {
-                DeclarationAST *declaration = 0;
                 if (! parseBlockDeclaration(declaration)) {
                     rewind(start);
                     _translationUnit->error(cursor(),
@@ -4188,13 +4233,20 @@ bool Parser::parseObjCMethodDefinitionList()
             }
             break;
         } // switch
+
+        if (declaration) {
+            *next = new (_pool) DeclarationListAST;
+            (*next)->declaration = declaration;
+            next = &((*next)->next);
+        }
     }
 
     return true;
 }
 
-bool Parser::parseObjCMethodDefinition()
+bool Parser::parseObjCMethodDefinition(DeclarationAST *&node)
 {
+    // TODO EV:
     DeclarationAST *ast = 0;
     if (! parseObjCMethodPrototype(ast))
         return false;
@@ -4339,12 +4391,13 @@ bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node)
 // objc-property-declaration ::=
 //    T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration
 //
-bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *)
+bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *attributes)
 {
     if (LA() != T_AT_PROPERTY)
         return false;
 
     ObjCPropertyDeclarationAST *ast = new (_pool) ObjCPropertyDeclarationAST;
+    ast->attributes = attributes;
     ast->property_token = consumeToken();
 
     if (LA() == T_LPAREN) {
@@ -4518,15 +4571,4 @@ bool Parser::parseObjCTypeQualifiers(unsigned &type_qualifier)
     return true;
 }
 
-// objc-end: T_AT_END
-bool Parser::parseObjCEnd(DeclarationAST *&)
-{
-    if (LA() != T_AT_END)
-        return false;
-
-    consumeToken();
-    return true;
-}
-
-
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index d29749834442873802825806d6d115c7a8e8c3bc..df017209e158c574b2913a38056bcd3a31dd1b6e 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -228,8 +228,8 @@ public:
     bool parseObjCMessageReceiver(ExpressionAST *&node);
     bool parseObjCMessageArguments(ObjCMessageArgumentListAST *&node);
     bool parseObjCSelectorArg(ObjCMessageArgumentAST *&node);
-    bool parseObjCMethodDefinitionList();
-    bool parseObjCMethodDefinition();
+    bool parseObjCMethodDefinitionList(DeclarationListAST *&node);
+    bool parseObjCMethodDefinition(DeclarationAST *&node);
 
     bool parseObjCProtocolRefs(ObjCProtocolRefsAST *&node);
     bool parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST *&node);
@@ -244,7 +244,6 @@ public:
     bool parseObjCSelector(unsigned &selector_token);
     bool parseObjCKeywordDeclaration(ObjCMessageArgumentDeclarationAST *&node);
     bool parseObjCTypeQualifiers(unsigned &type_qualifier);
-    bool parseObjCEnd(DeclarationAST *&node);
 
     bool lookAtObjCSelector() const;
 
@@ -288,6 +287,7 @@ private:
     TranslationUnit *_translationUnit;
     Control *_control;
     MemoryPool *_pool;
+    Identifier *_objcInContextKeyword;
     unsigned _tokenIndex;
     bool _templateArguments: 1;
     bool _qtMocRunEnabled: 1;