From 7fbec4f28ed0093e87b2dfd1fc57a9ff224f0b3f Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Thu, 16 Jul 2009 15:50:42 +0200
Subject: [PATCH] Added ObjC properties to the AST.

---
 src/shared/cplusplus/AST.cpp      | 99 ++++++++++++++++++++++++-------
 src/shared/cplusplus/AST.h        | 78 +++++++++++++++++++-----
 src/shared/cplusplus/ASTClone.cpp | 42 ++++++++++---
 src/shared/cplusplus/ASTVisit.cpp | 55 ++++++++++++-----
 src/shared/cplusplus/ASTVisitor.h |  8 ++-
 src/shared/cplusplus/ASTfwd.h     |  4 +-
 src/shared/cplusplus/Parser.cpp   | 83 +++++++++++++++++---------
 src/shared/cplusplus/Parser.h     |  4 +-
 8 files changed, 280 insertions(+), 93 deletions(-)

diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 07e68a74dbc..08fcb2fa9d0 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -1981,6 +1981,7 @@ unsigned ObjCClassInterfaceDeclarationAST::firstToken() const
 unsigned ObjCClassInterfaceDeclarationAST::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;
@@ -2004,6 +2005,9 @@ unsigned ObjCCategoryInterfaceDeclarationAST::lastToken() const
     if (end_token)
         return end_token + 1;
 
+    if (member_declarations)
+        return member_declarations->lastToken();
+
     if (rparen_token)              return rparen_token + 1;
     if (category_identifier_token) return category_identifier_token + 1;
     if (lparen_token)              return lparen_token + 1;
@@ -2023,6 +2027,12 @@ unsigned ObjCProtocolDefinitionAST::lastToken() const
     if (end_token)
         return end_token + 1;
 
+    if (member_declarations)
+        return member_declarations->lastToken();
+
+    if (protocol_refs)
+        return protocol_refs->lastToken();
+
     if (identifier_token)
         return identifier_token + 1;
 
@@ -2156,29 +2166,6 @@ unsigned ObjCEncodeExpressionAST::lastToken() const
     return encode_token + 1;
 }
 
-unsigned ObjCInstanceVariableListAST::firstToken() const
-{
-    if (declaration)
-        return declaration->firstToken();
-
-    if (next)
-        return next->firstToken();
-
-    // ### assert?
-    return 0;
-}
-
-unsigned ObjCInstanceVariableListAST::lastToken() const
-{
-    for (const ObjCInstanceVariableListAST *it = this; it; it = it->next) {
-        if (! it->next && it->declaration) {
-            return it->declaration->lastToken();
-        }
-    }
-    // ### assert?
-    return 0;
-}
-
 unsigned ObjCInstanceVariablesDeclarationAST::firstToken() const
 {
     return lbrace_token;
@@ -2189,6 +2176,9 @@ 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();
 
@@ -2205,4 +2195,67 @@ unsigned ObjCVisibilityDeclarationAST::lastToken() const
     return visibility_token + 1;
 }
 
+unsigned ObjcPropertyAttributeAST::firstToken() const
+{
+    return attribute_identifier_token;
+}
+
+unsigned ObjcPropertyAttributeAST::lastToken() const
+{
+    if (colon_token)
+        return colon_token + 1;
+    if (method_selector_identifier_token)
+        return method_selector_identifier_token + 1;
+    if (equals_token)
+        return equals_token + 1;
+
+    return attribute_identifier_token + 1;
+}
+
+unsigned ObjcPropertyAttributeListAST::firstToken() const
+{
+    if (attr)
+        return attr->firstToken();
+    else if (comma_token)
+        return comma_token;
+    else if (next)
+        return next->lastToken();
+    else
+        // ### Assert?
+        return 0;
+}
+
+unsigned ObjcPropertyAttributeListAST::lastToken() const
+{
+    for (const ObjcPropertyAttributeListAST *it = this; it; it = it->next) {
+        if (! it->next && (comma_token || it->attr)) {
+            if (comma_token)
+                return comma_token + 1;
+            else
+                return it->attr->lastToken();
+        }
+    }
+    // ### assert?
+    return 0;
+}
+
+unsigned ObjCPropertyDeclarationAST::firstToken() const
+{
+    return property_token;
+}
+
+unsigned ObjCPropertyDeclarationAST::lastToken() const
+{
+    if (simple_declaration)
+        return simple_declaration->lastToken();
+    else if (rparen_token)
+        return rparen_token + 1;
+    else if (property_attributes)
+        return property_attributes->lastToken();
+    else if (lparen_token)
+        return lparen_token + 1;
+    else
+        return property_token + 1;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 4a111192602..6fef4cafef4 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2492,6 +2492,7 @@ public:
     unsigned superclass_identifier_token;
     ObjCProtocolRefsAST *protocol_refs;
     ObjCInstanceVariablesDeclarationAST *inst_vars_decl;
+    DeclarationListAST *member_declarations;
     unsigned end_token;
 
 public:
@@ -2516,6 +2517,7 @@ public:
     unsigned category_identifier_token;
     unsigned rparen_token;
     ObjCProtocolRefsAST *protocol_refs;
+    DeclarationListAST *member_declarations;
     unsigned end_token;
 
 public:
@@ -2559,6 +2561,7 @@ public:
     unsigned protocol_token;
     unsigned identifier_token;
     ObjCProtocolRefsAST *protocol_refs;
+    DeclarationListAST *member_declarations;
     unsigned end_token;
 
 public:
@@ -2715,58 +2718,103 @@ protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjCInstanceVariableListAST: public AST
+class CPLUSPLUS_EXPORT ObjCInstanceVariablesDeclarationAST: public AST
 {
 public:
-    DeclarationAST *declaration;
-    ObjCInstanceVariableListAST *next;
+    unsigned lbrace_token;
+    DeclarationListAST *instance_variables;
+    DeclarationListAST *member_declarations;
+    unsigned rbrace_token;
 
 public:
-    virtual ObjCInstanceVariableListAST *asObjCInstanceVariableList()
+    virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjCInstanceVariableListAST *clone(MemoryPool *pool) const;
+    virtual ObjCInstanceVariablesDeclarationAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjCInstanceVariablesDeclarationAST: public AST
+class CPLUSPLUS_EXPORT ObjCVisibilityDeclarationAST: public DeclarationAST
 {
 public:
-    unsigned lbrace_token;
-    ObjCInstanceVariableListAST *instance_variables;
-    unsigned rbrace_token;
+    unsigned visibility_token;
 
 public:
-    virtual ObjCInstanceVariablesDeclarationAST *asObjCInstanceVariablesDeclaration()
+    virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjCInstanceVariablesDeclarationAST *clone(MemoryPool *pool) const;
+    virtual ObjCVisibilityDeclarationAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
 };
 
-class CPLUSPLUS_EXPORT ObjCVisibilityDeclarationAST: public DeclarationAST
+class CPLUSPLUS_EXPORT ObjcPropertyAttributeAST: public AST
 {
 public:
-    unsigned visibility_token;
+    unsigned attribute_identifier_token;
+    unsigned equals_token;
+    unsigned method_selector_identifier_token;
+    unsigned colon_token;
 
 public:
-    virtual ObjCVisibilityDeclarationAST *asObjCVisibilityDeclaration()
+    virtual ObjcPropertyAttributeAST *asObjcPropertyAttribute()
     { return this; }
 
     virtual unsigned firstToken() const;
     virtual unsigned lastToken() const;
 
-    virtual ObjCVisibilityDeclarationAST *clone(MemoryPool *pool) const;
+    virtual ObjcPropertyAttributeAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjcPropertyAttributeListAST: public AST
+{
+public:
+    ObjcPropertyAttributeAST *attr;
+    unsigned comma_token;
+    ObjcPropertyAttributeListAST *next;
+
+public:
+    virtual ObjcPropertyAttributeListAST *asObjcPropertyAttributeList()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjcPropertyAttributeListAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+};
+
+class CPLUSPLUS_EXPORT ObjCPropertyDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned property_token;
+    unsigned lparen_token;
+    ObjcPropertyAttributeListAST *property_attributes;
+    unsigned rparen_token;
+    DeclarationAST *simple_declaration;
+
+public:
+    virtual ObjCPropertyDeclarationAST *asObjCPropertyDeclaration()
+    { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual ObjCPropertyDeclarationAST *clone(MemoryPool *pool) const;
 
 protected:
     virtual void accept0(ASTVisitor *visitor);
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 0f3e99b7fa8..2a95a1c0f34 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -1236,6 +1236,7 @@ ObjCClassInterfaceDeclarationAST *ObjCClassInterfaceDeclarationAST::clone(Memory
     ast->superclass_identifier_token = superclass_identifier_token;
     if (protocol_refs) ast->protocol_refs = protocol_refs->clone(pool);
     if (inst_vars_decl) ast->inst_vars_decl = inst_vars_decl->clone(pool);
+    if (member_declarations) ast->member_declarations = member_declarations->clone(pool);
     ast->end_token = end_token;
     return ast;
 }
@@ -1251,6 +1252,7 @@ ObjCCategoryInterfaceDeclarationAST *ObjCCategoryInterfaceDeclarationAST::clone(
     ast->lparen_token = lparen_token;
     ast->category_identifier_token = category_identifier_token;
     ast->rparen_token = rparen_token;
+    if (member_declarations) ast->member_declarations = member_declarations->clone(pool);
     ast->end_token = end_token;
     return ast;
 }
@@ -1272,6 +1274,7 @@ ObjCProtocolDefinitionAST *ObjCProtocolDefinitionAST::clone(MemoryPool *pool) co
     ast->protocol_token = protocol_token;
     ast->identifier_token = identifier_token;
     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;
     return ast;
 }
@@ -1340,19 +1343,12 @@ ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
     return ast;
 }
 
-ObjCInstanceVariableListAST *ObjCInstanceVariableListAST::clone(MemoryPool *pool) const
-{
-    ObjCInstanceVariableListAST *ast = new (pool) ObjCInstanceVariableListAST;
-    if (declaration) ast->declaration = declaration->clone(pool);
-    if (next) ast->next = next->clone(pool);
-    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;
 }
@@ -1364,4 +1360,34 @@ ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *po
     return ast;
 }
 
+ObjcPropertyAttributeAST *ObjcPropertyAttributeAST::clone(MemoryPool *pool) const
+{
+    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;
+    return ast;
+}
+
+ObjcPropertyAttributeListAST *ObjcPropertyAttributeListAST::clone(MemoryPool *pool) const
+{
+    ObjcPropertyAttributeListAST *ast = new (pool) ObjcPropertyAttributeListAST;
+    if (attr) ast->attr = attr->clone(pool);
+    ast->comma_token = comma_token;
+    if (next) ast->next = next->clone(pool);
+    return ast;
+}
+
+ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const
+{
+    ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST;
+    ast->property_token = property_token;
+    ast->lparen_token = lparen_token;
+    if (property_attributes) ast->property_attributes = property_attributes->clone(pool);
+    ast->rparen_token = rparen_token;
+    if (simple_declaration) ast->simple_declaration = simple_declaration->clone(pool);
+    return ast;
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index ec00c8573ac..5caaa444a23 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -1148,6 +1148,8 @@ void ObjCClassInterfaceDeclarationAST::accept0(ASTVisitor *visitor)
         accept(protocol_refs, visitor);
         if (inst_vars_decl)
             accept(inst_vars_decl, visitor);
+        if (member_declarations)
+            accept(member_declarations, visitor);
         // visit DeclarationAST
     }
     visitor->endVisit(this);
@@ -1182,7 +1184,10 @@ void ObjCProtocolDefinitionAST::accept0(ASTVisitor *visitor)
         // visit ObjCProtocolDefinitionAST
         for (SpecifierAST *it = attributes; it; it = it->next)
             accept(it, visitor);
-        accept(protocol_refs, visitor);
+        if (protocol_refs)
+            accept(protocol_refs, visitor);
+        if (member_declarations)
+            accept(member_declarations, visitor);
         // visit DeclarationAST
     }
     visitor->endVisit(this);
@@ -1267,25 +1272,14 @@ void ObjCEncodeExpressionAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
-void ObjCInstanceVariableListAST::accept0(ASTVisitor *visitor)
-{
-    if (visitor->visit(this)) {
-        // visit ObjCInstanceVariableListAST
-        if (declaration)
-            accept(declaration, visitor);
-        if (next)
-            accept(next, visitor);
-        // visit AST
-    }
-    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);
@@ -1300,4 +1294,37 @@ void ObjCVisibilityDeclarationAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void ObjcPropertyAttributeAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjcPropertyAttributeAST
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjcPropertyAttributeListAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjcPropertyAttributeListAST
+        for (ObjcPropertyAttributeListAST *it = this; it; it = it->next)
+            accept(it, visitor);
+        // visit AST
+    }
+    visitor->endVisit(this);
+}
+
+void ObjCPropertyDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        // visit ObjCPropertyDeclarationAST:
+        if (property_attributes)
+            accept(property_attributes, visitor);
+        if (simple_declaration)
+            accept(simple_declaration, visitor);
+        // visit DeclarationAST:
+    }
+    visitor->endVisit(this);
+}
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index 7fad994a903..0e056324c22 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -209,9 +209,11 @@ public:
     virtual bool visit(ObjCProtocolExpressionAST *) { return true; }
     virtual bool visit(ObjCTypeNameAST *) { return true; }
     virtual bool visit(ObjCEncodeExpressionAST *) { return true; }
-    virtual bool visit(ObjCInstanceVariableListAST *) { 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(ObjCPropertyDeclarationAST *) { return true; }
 
     virtual bool visit(DeclarationListAST *) { return true; }
     virtual void endVisit(DeclarationListAST *) { }
@@ -332,9 +334,11 @@ public:
     virtual void endVisit(ObjCProtocolExpressionAST *) { }
     virtual void endVisit(ObjCTypeNameAST *) { }
     virtual void endVisit(ObjCEncodeExpressionAST *) { }
-    virtual void endVisit(ObjCInstanceVariableListAST *) { }
     virtual void endVisit(ObjCInstanceVariablesDeclarationAST *) { }
     virtual void endVisit(ObjCVisibilityDeclarationAST *) { }
+    virtual void endVisit(ObjcPropertyAttributeAST *) { }
+    virtual void endVisit(ObjcPropertyAttributeListAST *) { }
+    virtual void endVisit(ObjCPropertyDeclarationAST *) { }
 
 private:
     Control *_control;
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index e9ded00d871..91564058e21 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -182,9 +182,11 @@ class ObjCMessageArgumentAST;
 class ObjCProtocolExpressionAST;
 class ObjCTypeNameAST;
 class ObjCEncodeExpressionAST;
-class ObjCInstanceVariableListAST;
 class ObjCInstanceVariablesDeclarationAST;
 class ObjCVisibilityDeclarationAST;
+class ObjCPropertyDeclarationAST;
+class ObjcPropertyAttributeListAST;
+class ObjcPropertyAttributeAST;
 
 CPLUSPLUS_END_NAMESPACE
 CPLUSPLUS_END_HEADER
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 723c99fb1e3..09271cc7736 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -3962,8 +3962,15 @@ bool Parser::parseObjCInterface(DeclarationAST *&node,
         match(T_RPAREN, &(ast->rparen_token));
 
         parseObjCProtocolRefs(ast->protocol_refs);
-        while (parseObjCInterfaceMemberDeclaration()) {
+        
+        DeclarationListAST **nextMembers = &(ast->member_declarations);
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->declaration = declaration;
+            nextMembers = &((*nextMembers)->next);
         }
+
         match(T_AT_END, &(ast->end_token));
 
         node = ast;
@@ -3982,9 +3989,17 @@ bool Parser::parseObjCInterface(DeclarationAST *&node,
 
         parseObjCProtocolRefs(ast->protocol_refs);
         parseObjClassInstanceVariables(ast->inst_vars_decl);
-        while (parseObjCInterfaceMemberDeclaration()) {
+
+        DeclarationListAST **nextMembers = &(ast->member_declarations);
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->declaration = declaration;
+            nextMembers = &((*nextMembers)->next);
         }
+
         match(T_AT_END, &(ast->end_token));
+
         node = ast;
         return true;
     }
@@ -4040,7 +4055,12 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node,
 
         parseObjCProtocolRefs(ast->protocol_refs);
 
-        while (parseObjCInterfaceMemberDeclaration()) {
+        DeclarationListAST **nextMembers = &(ast->member_declarations);
+        DeclarationAST *declaration = 0;
+        while (parseObjCInterfaceMemberDeclaration(declaration)) {
+            *nextMembers = new (_pool) DeclarationListAST;
+            (*nextMembers)->declaration = declaration;
+            nextMembers = &((*nextMembers)->next);
         }
 
         match(T_AT_END, &(ast->end_token));
@@ -4230,13 +4250,13 @@ bool Parser::parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST
     ObjCInstanceVariablesDeclarationAST *ast = new (_pool) ObjCInstanceVariablesDeclarationAST;
     match(T_LBRACE, &(ast->lbrace_token));
 
-    for (ObjCInstanceVariableListAST **next = &(ast->instance_variables); LA(); next = &((*next)->next)) {
+    for (DeclarationListAST **next = &(ast->instance_variables); LA(); next = &((*next)->next)) {
         if (LA() == T_RBRACE)
             break;
 
         const unsigned start = cursor();
 
-        *next = new (_pool) ObjCInstanceVariableListAST;
+        *next = new (_pool) DeclarationListAST;
         parseObjCInstanceVariableDeclaration((*next)->declaration);
 
         if (start == cursor()) {
@@ -4257,7 +4277,7 @@ bool Parser::parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST
 // objc-interface-declaration ::= T_SEMICOLON
 // objc-interface-declaration ::= objc-property-declaration
 // objc-interface-declaration ::= objc-method-prototype
-bool Parser::parseObjCInterfaceMemberDeclaration()
+bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node)
 {
     switch (LA()) {
     case T_AT_END:
@@ -4273,8 +4293,7 @@ bool Parser::parseObjCInterfaceMemberDeclaration()
         return true;
 
     case T_AT_PROPERTY: {
-        DeclarationAST *declaration = 0;
-        return parseObjCPropertyDeclaration(declaration);
+        return parseObjCPropertyDeclaration(node);
     }
 
     case T_PLUS:
@@ -4285,13 +4304,11 @@ bool Parser::parseObjCInterfaceMemberDeclaration()
     case T_CLASS:
     case T_STRUCT:
     case T_UNION: {
-        DeclarationAST *declaration = 0;
-        return parseSimpleDeclaration(declaration, /*accept struct declarators */ true);
+        return parseSimpleDeclaration(node, /*accept struct declarators */ true);
     }
 
     default: {
-        DeclarationAST *declaration = 0;
-        return parseSimpleDeclaration(declaration, /*accept struct declarators */ true);
+        return parseSimpleDeclaration(node, /*accept struct declarators */ true);
     } // default
 
     } // switch
@@ -4321,27 +4338,37 @@ 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 *&, SpecifierAST *)
+bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *)
 {
     if (LA() != T_AT_PROPERTY)
         return false;
 
-    /*unsigned objc_property_token = */ consumeToken();
+    ObjCPropertyDeclarationAST *ast = new (_pool) ObjCPropertyDeclarationAST;
+    ast->property_token = consumeToken();
 
     if (LA() == T_LPAREN) {
-        unsigned lparen_token = 0, rparen_token = 0;
-        match(T_LPAREN, &lparen_token);
-        if (parseObjCPropertyAttribute()) {
+        match(T_LPAREN, &(ast->lparen_token));
+
+        ObjcPropertyAttributeAST *property_attribute = 0;
+        if (parseObjCPropertyAttribute(property_attribute)) {
+            ast->property_attributes = new (_pool) ObjcPropertyAttributeListAST;
+            ast->property_attributes->attr = property_attribute;
+            ObjcPropertyAttributeListAST *last = ast->property_attributes;
+
             while (LA() == T_COMMA) {
-                consumeToken();
-                parseObjCPropertyAttribute();
+                last->comma_token = consumeToken();
+                last->next = new (_pool) ObjcPropertyAttributeListAST;
+                last = last->next;
+                parseObjCPropertyAttribute(last->attr);
             }
         }
-        match(T_RPAREN, &rparen_token);
+
+        match(T_RPAREN, &(ast->rparen_token));
     }
 
-    DeclarationAST *simple_declaration = 0;
-    parseSimpleDeclaration(simple_declaration, /*accept-struct-declarators = */ true);
+    parseSimpleDeclaration(ast->simple_declaration, /*accept-struct-declarators = */ true);
+
+    node = ast;
     return true;
 }
 
@@ -4398,18 +4425,18 @@ bool Parser::parseObjCMethodPrototype()
 // objc-property-attribute ::= retain
 // objc-property-attribute ::= copy
 // objc-property-attribute ::= nonatomic
-bool Parser::parseObjCPropertyAttribute()
+bool Parser::parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node)
 {
     if (LA() != T_IDENTIFIER)
         return false;
 
-    unsigned identifier_token = 0;
-    match(T_IDENTIFIER, &identifier_token);
+    node = new (_pool) ObjcPropertyAttributeAST;
+    match(T_IDENTIFIER, &(node->attribute_identifier_token));
     if (LA() == T_EQUAL) {
-        consumeToken();
-        match(T_IDENTIFIER, &identifier_token);
+        node->equals_token = consumeToken();
+        match(T_IDENTIFIER, &(node->method_selector_identifier_token));
         if (LA() == T_COLON)
-            consumeToken();
+            node->colon_token = consumeToken();
     }
 
     return true;
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 31f2383cf4e..d292c5b9351 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -233,13 +233,13 @@ public:
 
     bool parseObjCProtocolRefs(ObjCProtocolRefsAST *&node);
     bool parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST *&node);
-    bool parseObjCInterfaceMemberDeclaration();
+    bool parseObjCInterfaceMemberDeclaration(DeclarationAST *&node);
     bool parseObjCInstanceVariableDeclaration(DeclarationAST *&node);
     bool parseObjCPropertyDeclaration(DeclarationAST *&node,
                                       SpecifierAST *attributes = 0);
     bool parseObjCImplementation(DeclarationAST *&node);
     bool parseObjCMethodPrototype();
-    bool parseObjCPropertyAttribute();
+    bool parseObjCPropertyAttribute(ObjcPropertyAttributeAST *&node);
     bool parseObjCTypeName(ObjCTypeNameAST *&node);
     bool parseObjCSelector(unsigned &selector_token);
     bool parseObjCKeywordDeclaration();
-- 
GitLab