diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index e8ecfa07cdba7fbcd5948c1d94ee04d05ed4d0c2..0eae1bd0fed9e8369a0386251e108964d02bc30c 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -1997,7 +1997,10 @@ unsigned ObjCClassInterfaceDeclarationAST::lastToken() const
 
 unsigned ObjCCategoryInterfaceDeclarationAST::firstToken() const
 {
-    return interface_token;
+    if (attributes)
+        return attributes->firstToken();
+    else
+        return interface_token;
 }
 
 unsigned ObjCCategoryInterfaceDeclarationAST::lastToken() const
@@ -2319,6 +2322,32 @@ unsigned ObjCMethodPrototypeAST::lastToken() const
         return method_type_token + 1;
 }
 
+unsigned ObjCMethodDeclarationAST::firstToken() const
+{
+    return method_prototype->firstToken();
+}
+
+unsigned ObjCMethodDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    else
+        return method_prototype->lastToken();
+}
+
+unsigned ObjCMethodDefinitionAST::firstToken() const
+{
+    return method_prototype->firstToken();
+}
+
+unsigned ObjCMethodDefinitionAST::lastToken() const
+{
+    if (function_body)
+        return function_body->lastToken();
+    else
+        return method_prototype->lastToken();
+}
+
 unsigned ObjCClassImplementationAST::firstToken() const
 {
     return implementation_token;
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index f6ab2626eb6c6a3d8a24497f255541d7cbfdd694..cbbbc5da69f72ea1eb772a76ed2f6a4c63a3b737 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2511,6 +2511,7 @@ protected:
 class CPLUSPLUS_EXPORT ObjCCategoryInterfaceDeclarationAST: public DeclarationAST
 {
 public:
+    SpecifierAST *attributes;
     unsigned interface_token;
     unsigned class_identifier_token;
     unsigned lparen_token;
@@ -2862,7 +2863,7 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjCMethodPrototypeAST: public DeclarationAST
+class CPLUSPLUS_EXPORT ObjCMethodPrototypeAST: public AST
 {
 public:
     unsigned method_type_token;
@@ -2883,6 +2884,44 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
+class CPLUSPLUS_EXPORT ObjCMethodDeclarationAST: public DeclarationAST
+{
+public:
+    ObjCMethodPrototypeAST *method_prototype;
+    unsigned semicolon_token;
+
+public:
+    virtual ObjCMethodDeclarationAST *asObjCMethodDeclaration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMethodDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCMethodDefinitionAST: public DeclarationAST
+{
+public:
+    ObjCMethodPrototypeAST *method_prototype;
+    StatementAST *function_body;
+
+public:
+    virtual ObjCMethodDefinitionAST *asObjCMethodDefinition()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCMethodDefinitionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
 class CPLUSPLUS_EXPORT ObjCClassImplementationAST: public DeclarationAST
 {
 public:
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 1e160ae2747a583c0824fd92e6d39c7a036adda5..3340a39f25cf837e1d0f778e9caf059192e94010 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1246,6 +1246,7 @@ ObjCCategoryInterfaceDeclarationAST *ObjCCategoryInterfaceDeclarationAST::clone(
     ObjCCategoryInterfaceDeclarationAST *ast = new (pool) ObjCCategoryInterfaceDeclarationAST;
     // copy DeclarationAST
     // copy ObjCCategoryInterfaceDeclarationAST
+    if (attributes) ast->attributes = attributes->clone(pool);
     ast->interface_token = interface_token;
     ast->class_identifier_token = class_identifier_token;
     if (protocol_refs) ast->protocol_refs = protocol_refs->clone(pool);
@@ -1420,6 +1421,22 @@ ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCMethodDeclarationAST *ast = new (pool) ObjCMethodDeclarationAST;
+    if (method_prototype) ast->method_prototype = method_prototype->clone(pool);
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
+ObjCMethodDefinitionAST *ObjCMethodDefinitionAST::clone(MemoryPool *pool) const
+{
+    ObjCMethodDefinitionAST *ast = new (pool) ObjCMethodDefinitionAST;
+    if (method_prototype) ast->method_prototype = method_prototype->clone(pool);
+    if (function_body) ast->function_body = function_body->clone(pool);
+    return ast;
+}
+
 ObjCClassImplementationAST *ObjCClassImplementationAST::clone(MemoryPool *pool) const
 {
     ObjCClassImplementationAST *ast = new (pool) ObjCClassImplementationAST;
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 98fe8a84adb4184788ad742edc701d58fa42c62a..9b43a34bfd7a9a8a8fade1a619221aabfc299ac7 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1159,7 +1159,12 @@ void ObjCCategoryInterfaceDeclarationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
         // visit ObjCCategoryInterfaceDeclarationAST
-        accept(protocol_refs, visitor);
+        if (attributes)
+            accept(attributes, visitor);
+        if (protocol_refs)
+            accept(protocol_refs, visitor);
+        if (member_declarations)
+            accept(member_declarations, visitor);
         // visit DeclarationAST
     }
     visitor->endVisit(this);
@@ -1368,6 +1373,30 @@ void ObjCMethodPrototypeAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void ObjCMethodDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCMethodDeclarationAST
+        if (method_prototype)
+            accept(method_prototype, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCMethodDefinitionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCMethodDefinitionAST
+        if (method_prototype)
+            accept(method_prototype, visitor);
+        if (function_body)
+            accept(function_body, visitor);
+        // visit DeclarationAST
+    }
+    visitor->endVisit(this);
+}
+
 void ObjCClassImplementationAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index 5279d290f502916a4816eb484bf222b0a1b0e454..dc289fdcb5a5229ef11784962ba70755219239da 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -215,6 +215,8 @@ public:
     virtual bool visit(ObjcPropertyAttributeListAST *) { return true; }
     virtual bool visit(ObjCPropertyDeclarationAST *) { return true; }
     virtual bool visit(ObjCMethodPrototypeAST *) { return true; }
+    virtual bool visit(ObjCMethodDeclarationAST *) { return true; }
+    virtual bool visit(ObjCMethodDefinitionAST *) { return true; }
     virtual bool visit(ObjCMessageArgumentDeclarationListAST *) { return true; }
     virtual bool visit(ObjCMessageArgumentDeclarationAST *) { return true; }
     virtual bool visit(ObjCClassImplementationAST *) { return true; }
@@ -350,6 +352,8 @@ public:
     virtual void endVisit(ObjcPropertyAttributeListAST *) { }
     virtual void endVisit(ObjCPropertyDeclarationAST *) { }
     virtual void endVisit(ObjCMethodPrototypeAST *) { }
+    virtual void endVisit(ObjCMethodDeclarationAST *) { }
+    virtual void endVisit(ObjCMethodDefinitionAST *) { }
     virtual void endVisit(ObjCMessageArgumentDeclarationListAST *) { }
     virtual void endVisit(ObjCMessageArgumentDeclarationAST *) { }
     virtual void endVisit(ObjCClassImplementationAST *) { }
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index 5416856614c641251fa7b8681a45cd86de2e4788..a6ad8261756c015aee3cc116df0e7f638aa55ed5 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -188,6 +188,8 @@ class ObjCPropertyDeclarationAST;
 class ObjcPropertyAttributeListAST;
 class ObjcPropertyAttributeAST;
 class ObjCMethodPrototypeAST;
+class ObjCMethodDeclarationAST;
+class ObjCMethodDefinitionAST;
 class ObjCMessageArgumentDeclarationListAST;
 class ObjCMessageArgumentDeclarationAST;
 class ObjCCategoryImplementationAST;
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 2856e07622ad15cc683747676cd7dc8a32a8221c..616d2ed3e2ab985f265bc6d9d45795665ddba6cf 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -63,7 +63,6 @@ Parser::Parser(TranslationUnit *unit)
     : _translationUnit(unit),
       _control(_translationUnit->control()),
       _pool(_translationUnit->memoryPool()),
-      _objcInContextKeyword(_control->findOrInsertIdentifier("in")),
       _tokenIndex(1),
       _templateArguments(0),
       _qtMocRunEnabled(false),
@@ -2178,16 +2177,19 @@ bool Parser::parseForStatement(StatementAST *&node)
     unsigned for_token = consumeToken();
     unsigned lparen_token = 0;
     match(T_LPAREN, &lparen_token);
+
+    // FIXME: for ObjC fast enumeration, this needs a semicolon before the "in" token, which is obviously wrong.
     StatementAST *initializer = 0;
     parseForInitStatement(initializer);
+    unsigned in_token = 0;
 
-    if (LA() == T_IDENTIFIER && tok().identifier == _objcInContextKeyword) {
+    if (parseObjCContextKeyword(Token_in, in_token)) {
         ObjCFastEnumerationAST *ast = new (_pool) ObjCFastEnumerationAST;
 
         ast->for_token = for_token;
         ast->lparen_token = lparen_token;
         ast->initializer = initializer;
-        ast->in_token = consumeToken();
+        ast->in_token = in_token;
         parseExpression(ast->fast_enumeratable_expression);
         match(T_RPAREN, &ast->rparen_token);
         parseStatement(ast->body_statement);
@@ -3978,7 +3980,7 @@ bool Parser::parseObjCInterface(DeclarationAST *&node,
                                     "invalid attributes for category interface declaration");
 
         ObjCCategoryInterfaceDeclarationAST *ast = new (_pool) ObjCCategoryInterfaceDeclarationAST;
-        // TODO: Should the attributes get stored anyway? (for fixing/refactoring purposes maybe...)
+        ast->attributes = attributes;
         ast->interface_token = objc_interface_token;
         ast->class_identifier_token = identifier_token;
 
@@ -4169,27 +4171,28 @@ bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node)
         case T_AT_SYNTHESIZE: {
             ObjCSynthesizedPropertiesDeclarationAST *ast = new (_pool) ObjCSynthesizedPropertiesDeclarationAST;
             ast->synthesized_token = consumeToken();
-            // TODO EV
-            unsigned identifier_token = 0;
-            match(T_IDENTIFIER, &identifier_token);
+            ObjCSynthesizedPropertyListAST *last = new (_pool) ObjCSynthesizedPropertyListAST;
+            ast->property_identifiers = last;
+            last->synthesized_property = new (_pool) ObjCSynthesizedPropertyAST;
+            match(T_IDENTIFIER, &(last->synthesized_property->property_identifier));
 
             if (LA() == T_EQUAL) {
-                consumeToken();
+                last->synthesized_property->equals_token = consumeToken();
 
-                unsigned aliassed_identifier_token = 0;
-                match(T_IDENTIFIER, &aliassed_identifier_token);
+                match(T_IDENTIFIER, &(last->synthesized_property->property_alias_identifier));
             }
 
             while (LA() == T_COMMA) {
-                consumeToken();
+                last->comma_token = consumeToken();
+                last->next = new (_pool) ObjCSynthesizedPropertyListAST;
+                last = last->next;
 
-                match(T_IDENTIFIER, &identifier_token);
+                match(T_IDENTIFIER, &(last->synthesized_property->property_identifier));
 
                 if (LA() == T_EQUAL) {
-                    consumeToken();
+                    last->synthesized_property->equals_token = consumeToken();
 
-                    unsigned aliassed_identifier_token = 0;
-                    match(T_IDENTIFIER, &aliassed_identifier_token);
+                    match(T_IDENTIFIER, &(last->synthesized_property->property_alias_identifier));
                 }
             }
 
@@ -4246,16 +4249,24 @@ bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node)
 
 bool Parser::parseObjCMethodDefinition(DeclarationAST *&node)
 {
-    // TODO EV:
-    DeclarationAST *ast = 0;
-    if (! parseObjCMethodPrototype(ast))
+    ObjCMethodPrototypeAST *method_prototype;
+    if (! parseObjCMethodPrototype(method_prototype))
         return false;
 
-    if (LA() == T_SEMICOLON)
-        consumeToken();
+    if (LA() == T_SEMICOLON) {
+        // method declaration:
+        ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST;
+        ast->method_prototype = method_prototype;
+        ast->semicolon_token = consumeToken();
+        node = ast;
+    } else {
+        // method definition:
+        ObjCMethodDefinitionAST *ast = new (_pool) ObjCMethodDefinitionAST;
+        ast->method_prototype = method_prototype;
+        parseFunctionBody(ast->function_body);
+        node = ast;
+    }
 
-    StatementAST *function_body = 0;
-    parseFunctionBody(function_body);
     return true;
 }
 
@@ -4350,8 +4361,16 @@ bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node)
     }
 
     case T_PLUS:
-    case T_MINUS:
-        return parseObjCMethodPrototype(node);
+    case T_MINUS: {
+        ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST;
+        if (parseObjCMethodPrototype(ast->method_prototype)) {
+            match(T_SEMICOLON, &(ast->semicolon_token));
+            node = ast;
+            return true;
+        } else {
+            return false;
+        }
+    }
 
     case T_ENUM:
     case T_CLASS:
@@ -4431,7 +4450,7 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *a
 // objc-method-decl ::= objc-type-name? objc-selector
 // objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt
 //
-bool Parser::parseObjCMethodPrototype(DeclarationAST *&node)
+bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node)
 {
     if (LA() != T_PLUS && LA() != T_MINUS)
         return false;
@@ -4455,7 +4474,7 @@ bool Parser::parseObjCMethodPrototype(DeclarationAST *&node)
             (*last)->argument_declaration = declaration;
         }
 
-        // TODO: err, what does this parse?
+        // TODO EV: get this in the ast
         while (LA() == T_COMMA) {
             consumeToken();
 
@@ -4571,4 +4590,17 @@ bool Parser::parseObjCTypeQualifiers(unsigned &type_qualifier)
     return true;
 }
 
+bool Parser::parseObjCContextKeyword(int kind, unsigned &in_token)
+{
+    if (LA() != T_IDENTIFIER)
+        return false;
+
+    Identifier *id = tok().identifier;
+    const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size());
+    if (k != kind)
+        return false;
+    in_token = consumeToken();
+    return true;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index df017209e158c574b2913a38056bcd3a31dd1b6e..5fd5253e34804ea86b6da4a73a6144b5c1c9367b 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -238,12 +238,13 @@ public:
     bool parseObjCPropertyDeclaration(DeclarationAST *&node,
                                       SpecifierAST *attributes = 0);
     bool parseObjCImplementation(DeclarationAST *&node);
-    bool parseObjCMethodPrototype(DeclarationAST *&node);
+    bool parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node);
     bool parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node);
     bool parseObjCTypeName(ObjCTypeNameAST *&node);
     bool parseObjCSelector(unsigned &selector_token);
     bool parseObjCKeywordDeclaration(ObjCMessageArgumentDeclarationAST *&node);
     bool parseObjCTypeQualifiers(unsigned &type_qualifier);
+    bool parseObjCContextKeyword(int kind, unsigned &in_token);
 
     bool lookAtObjCSelector() const;
 
@@ -287,7 +288,6 @@ private:
     TranslationUnit *_translationUnit;
     Control *_control;
     MemoryPool *_pool;
-    Identifier *_objcInContextKeyword;
     unsigned _tokenIndex;
     bool _templateArguments: 1;
     bool _qtMocRunEnabled: 1;