diff mbox

ObjC/ObjC++ - parse @synthesize and @dynamic

Message ID 1287442153.23494018@192.168.2.229
State New
Headers show

Commit Message

Nicola Pero Oct. 18, 2010, 10:49 p.m. UTC
This patch implements parsing of @synthesize and @dynamic declarations in Objective-C 
and Objective-C++.  It also fixes some minor error messages when parsing invalid @class 
declarations.

The patch only deals with the parsing; it detects the declarations, parses them,
emits the appropriate syntax errors if needed, and checks that they are in the right 
@implementation context.  The actual functionality is missing (will be implemented in 
another patch); for now, after checking that the declarations are syntactically correct, 
we print an error saying that the current compiler does not support @synthesize/@dynamic.
Testcases for the syntax parsing are included.

I started the parsing code by copying from c_parser_objc_class_declaration(), which parses
the very similar @class <identifier-list>;.  I tweaked the code to adapt it to @synthesize
and @dynamic (and in the process fixed a bug I found in c_parser_objc_class_declaration() 
itself :-), testcase included with the patch), then wrote the parsing code for C++ to be almost 
identical to simplify future maintenance and changes.  I added clear comments in the code 
recommending that any change to one is mirrored into the other.  Finally, incidentally a testcase 
showed that Objective-C++ had bugs in its parsing of invalid @class declarations too, so I fixed that 
problem as well.

Ok to commit to trunk ? :-)

Thanks

PS: It's new code; we can't merge @synthesize/@dynamic from the FSF apple/trunk branch 
because they are not there.

In gcc/:
2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented parsing @synthesize and @dynamic for Objective-C.
        * c-parser.c (c_parser_external_declaration): Recognize
        RID_AT_SYNTHESIZE and RID_AT_DYNAMIC.
        (c_parser_objc_at_synthesize_declaration): New.
        (c_parser_objc_at_dynamic_declaration): New.

2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-parser.c (c_parser_objc_class_declaration): After finding an
        error, parse the whole declaration then reset parser->error.

In gcc/cp/:
2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented parsing @synthesize and @dynamic for Objective-C++.
        * parser.c (cp_parser_objc_method_definition_list): Recognize
        RID_AT_SYNTHESIZE and RID_AT_DYNAMIC.
        (cp_parser_objc_at_dynamic_declaration): New.
        (cp_parser_objc_at_synthesize_declaration): New.

2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * parser.c (cp_parser_objc_identifier_list): Check the return
        value of cp_parser_identifier and react if it is error_mark_node.

In gcc/objc/:
2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented parsing @synthesize and @dynamic for
        Objective-C/Objective-C++.
        * objc-act.c (objc_add_synthesize_declaration): New.
        (objc_add_dynamic_declaration): New.

2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc-act.c (lookup_and_install_protocols): Return NULL if passed
        error_mark_node.

In gcc/testsuite/:
2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        Implemented parsing @synthesize and @dynamic for
        Objective-C/Objective-C++.
        * objc.dg/property/dynamic-1.m: New.
        * objc.dg/property/synthesize-1.m: New.
        * obj-c++.dg/property/dynamic-1.mm: New.
        * obj-c++.dg/property/synthesize-1.mm: New.

2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc.dg/at-class-1.m: New.
        * objc.dg/at-class-1.mm: New.

Comments

Mike Stump Oct. 18, 2010, 11:20 p.m. UTC | #1
On Oct 18, 2010, at 3:49 PM, Nicola Pero wrote:
> Ok to commit to trunk ? :-)

Ok.
diff mbox

Patch

Index: gcc/c-family/ChangeLog
===================================================================
--- gcc/c-family/ChangeLog	(revision 165665)
+++ gcc/c-family/ChangeLog	(working copy)
@@ -1,5 +1,16 @@ 
 2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	Implemented parsing @synthesize and @dynamic for
+	Objective-C/Objective-C++.
+	* c-common.h (enum rid): Add RID_AT_SYNTHESIZE and RID_AT_DYNAMIC.
+	(objc_add_synthesize_declaration): New.
+	(objc_add_dynamic_declaration): New.
+	* c-common.c (c_common_reswords): Add synthesize and dynamic.
+	* stub-objc.c (objc_add_synthesize_declaration): New.
+	(objc_add_dynamic_declaration): New.
+	
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	Merge from 'apple/trunk' branch on FSF servers.
 	
 	2005-11-08  Fariborz Jahanian <fjahanian@apple.com>
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 165665)
+++ gcc/c-family/c-common.c	(working copy)
@@ -545,6 +545,8 @@  const struct c_common_resword c_common_reswords[]
   { "required",		RID_AT_REQUIRED,	D_OBJC },
   { "property",		RID_AT_PROPERTY,	D_OBJC },
   { "package",		RID_AT_PACKAGE,		D_OBJC },
+  { "synthesize",	RID_AT_SYNTHESIZE,	D_OBJC },
+  { "dynamic",		RID_AT_DYNAMIC,		D_OBJC },
   /* These are recognized only in protocol-qualifier context
      (see above) */
   { "bycopy",		RID_BYCOPY,		D_OBJC },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 165665)
+++ gcc/c-family/c-common.h	(working copy)
@@ -148,6 +148,7 @@  enum rid
   RID_AT_THROW,	   RID_AT_TRY,       RID_AT_CATCH,
   RID_AT_FINALLY,  RID_AT_SYNCHRONIZED, 
   RID_AT_OPTIONAL, RID_AT_REQUIRED, RID_AT_PROPERTY,
+  RID_AT_SYNTHESIZE, RID_AT_DYNAMIC,
   RID_AT_INTERFACE,
   RID_AT_IMPLEMENTATION,
 
@@ -1045,6 +1046,8 @@  extern bool  objc_method_decl (enum tree_code);
 extern void objc_add_property_variable (tree);
 extern tree objc_build_getter_call (tree, tree);
 extern tree objc_build_setter_call (tree, tree);
+extern void objc_add_synthesize_declaration (location_t, tree);
+extern void objc_add_dynamic_declaration (location_t, tree);
 
 /* The following are provided by the C and C++ front-ends, and called by
    ObjC/ObjC++.  */
Index: gcc/c-family/stub-objc.c
===================================================================
--- gcc/c-family/stub-objc.c	(revision 165665)
+++ gcc/c-family/stub-objc.c	(working copy)
@@ -349,6 +349,18 @@  objc_build_setter_call (tree ARG_UNUSED (lhs), tre
   return 0;
 }
 
+void
+objc_add_synthesize_declaration (location_t ARG_UNUSED (start_locus), 
+				 tree ARG_UNUSED (property_and_ivar_list))
+{
+}
+
+void
+objc_add_dynamic_declaration (location_t ARG_UNUSED (start_locus), 
+			      tree ARG_UNUSED (property_list))
+{
+}
+
 tree
 objc_build_throw_stmt (location_t ARG_UNUSED (loc), tree ARG_UNUSED (expr))
 {
Index: gcc/objc/objc-act.c
===================================================================
--- gcc/objc/objc-act.c	(revision 165665)
+++ gcc/objc/objc-act.c	(working copy)
@@ -2114,6 +2114,9 @@  lookup_and_install_protocols (tree protocols)
   tree proto;
   tree return_value = NULL_TREE;
 
+  if (protocols == error_mark_node)
+    return NULL;
+
   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
     {
       tree ident = TREE_VALUE (proto);
@@ -8701,6 +8704,55 @@  objc_synthesize_setter (tree klass, tree class_met
   objc_finish_method_definition (fn);
 }
 
+/* This function is called by the parser after a @synthesize
+   expression is parsed.  'start_locus' is the location of the
+   @synthesize expression, and 'property_and_ivar_list' is a chained
+   list of the property and ivar names.
+ */
+void
+objc_add_synthesize_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_and_ivar_list ATTRIBUTE_UNUSED)
+{
+  if (property_and_ivar_list == error_mark_node)
+    return;
+
+  if (!objc_implementation_context)
+    {
+      /* We can get here only in Objective-C; the Objective-C++ parser
+	 detects the problem while parsing, outputs the error
+	 "misplaced '@synthesize' Objective-C++ construct" and skips
+	 the declaration.  */
+      error ("%<@synthesize%> not in @implementation context");
+      return;
+    }
+
+  /* TODO */
+  error ("%<@synthesize%> is not supported in this version of the compiler");
+}
+
+/* This function is called by the parser after a @dynamic expression
+   is parsed.  'start_locus' is the location of the @dynamic
+   expression, and 'property_list' is a chained list of all the
+   property names.  */
+void
+objc_add_dynamic_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_list ATTRIBUTE_UNUSED)
+{
+  if (property_list == error_mark_node)
+    return;
+
+  if (!objc_implementation_context)
+    {
+      /* We can get here only in Objective-C; the Objective-C++ parser
+	 detects the problem while parsing, outputs the error
+	 "misplaced '@dynamic' Objective-C++ construct" and skips the
+	 declaration.  */
+      error ("%<@dynamic%> not in @implementation context");
+      return;
+    }
+
+  /* TODO */
+  error ("%<@dynamic%> is not supported in this version of the compiler");
+}
+
 /* Main routine to generate code/data for all the property information for 
    current implementation (class or category). CLASS is the interface where
    ivars are declared.  CLASS_METHODS is where methods are found which
Index: gcc/objc/ChangeLog
===================================================================
--- gcc/objc/ChangeLog	(revision 165665)
+++ gcc/objc/ChangeLog	(working copy)
@@ -1,5 +1,17 @@ 
 2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	Implemented parsing @synthesize and @dynamic for
+	Objective-C/Objective-C++.
+	* objc-act.c (objc_add_synthesize_declaration): New.
+	(objc_add_dynamic_declaration): New.
+
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>	
+
+	* objc-act.c (lookup_and_install_protocols): Return NULL if passed
+	error_mark_node.
+	
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	Merge from 'apple/trunk' branch on FSF servers.
 
 	2006-03-10  Fariborz Jahanian <fjahanian@apple.com>
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 165665)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,16 @@ 
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented parsing @synthesize and @dynamic for Objective-C.
+	* c-parser.c (c_parser_external_declaration): Recognize
+	RID_AT_SYNTHESIZE and RID_AT_DYNAMIC.
+	(c_parser_objc_at_synthesize_declaration): New.
+	(c_parser_objc_at_dynamic_declaration): New.
+
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+	
+	* c-parser.c (c_parser_objc_class_declaration): After finding an
+	error, parse the whole declaration then reset parser->error.
+	
 2010-10-18  Steve Ellcey  <sje@cup.hp.com>
 
 	PR target/36898
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(revision 165665)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,17 @@ 
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented parsing @synthesize and @dynamic for
+	Objective-C/Objective-C++.
+	* objc.dg/property/dynamic-1.m: New.
+	* objc.dg/property/synthesize-1.m: New.
+	* obj-c++.dg/property/dynamic-1.mm: New.
+	* obj-c++.dg/property/synthesize-1.mm: New.
+
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>	
+
+	* objc.dg/at-class-1.m: New.
+	* objc.dg/at-class-1.mm: New.	
+	
 2010-10-18  Steve Ellcey  <sje@cup.hp.com>
 
 	* gcc.c-torture/compile/920625-1.c: Remove dg-prune-output lines.
Index: gcc/testsuite/objc.dg/property/synthesize-1.m
===================================================================
--- gcc/testsuite/objc.dg/property/synthesize-1.m	(revision 0)
+++ gcc/testsuite/objc.dg/property/synthesize-1.m	(revision 0)
@@ -0,0 +1,31 @@ 
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@synthesize isa;                    /* { dg-error ".@synthesize. not in @implementation context" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+  int v2;
+  int v3;
+  int v4;
+}
+@end
+
+@implementation Test
+@synthesize;                        /* { dg-error "expected identifier" } */
+@synthesize v1, ;                   /* { dg-error "expected identifier" } */
+@synthesize v1, v2 = ;              /* { dg-error "expected identifier" } */
+@synthesize v1, v2=v2, v3 = v3,v4;  /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v4;                     /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@end
Index: gcc/testsuite/objc.dg/property/dynamic-1.m
===================================================================
--- gcc/testsuite/objc.dg/property/dynamic-1.m	(revision 0)
+++ gcc/testsuite/objc.dg/property/dynamic-1.m	(revision 0)
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa;           /* { dg-error ".@dynamic. not in @implementation context" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+  int v2;
+  int v3;
+  int v4;
+}
+@end
+
+@implementation Test
+@dynamic;            /* { dg-error "expected identifier" } */
+@dynamic v1, ;       /* { dg-error "expected identifier" } */
+@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v4;         /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@end
Index: gcc/testsuite/objc.dg/at-class-1.m
===================================================================
--- gcc/testsuite/objc.dg/at-class-1.m	(revision 0)
+++ gcc/testsuite/objc.dg/at-class-1.m	(revision 0)
@@ -0,0 +1,11 @@ 
+/* Test @class.  */
+/* { dg-do compile } */
+
+@class Object; /* Ok */
+
+@class Object, ;                            /* { dg-error "expected identifier" } */
+@class Object, ;                            /* { dg-error "expected identifier" } */
+@class Object, AnotherObject, ;             /* { dg-error "expected identifier" } */
+@class Object, AnotherObject, TestObject ;  /* Ok */
+
+@class Object                               /* { dg-error "expected .;." } */
Index: gcc/testsuite/obj-c++.dg/at-class-1.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/at-class-1.mm	(revision 0)
+++ gcc/testsuite/obj-c++.dg/at-class-1.mm	(revision 0)
@@ -0,0 +1,11 @@ 
+/* Test @class.  */
+/* { dg-do compile } */
+
+@class Object; /* Ok */
+
+@class Object, ;                            /* { dg-error "expected identifier" } */
+@class Object, ;                            /* { dg-error "expected identifier" } */
+@class Object, AnotherObject, ;             /* { dg-error "expected identifier" } */
+@class Object, AnotherObject, TestObject ;  /* Ok */
+
+@class Object                               /* { dg-error "expected .;." } */
Index: gcc/testsuite/obj-c++.dg/property/dynamic-1.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/property/dynamic-1.mm	(revision 0)
+++ gcc/testsuite/obj-c++.dg/property/dynamic-1.mm	(revision 0)
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa;           /* { dg-error "misplaced .@dynamic. Objective-C.. construct" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+  int v2;
+  int v3;
+  int v4;
+}
+@end
+
+@implementation Test
+@dynamic;            /* { dg-error "expected identifier" } */
+@dynamic v1, ;       /* { dg-error "expected identifier" } */
+@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v4;         /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@end
Index: gcc/testsuite/obj-c++.dg/property/synthesize-1.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/property/synthesize-1.mm	(revision 0)
+++ gcc/testsuite/obj-c++.dg/property/synthesize-1.mm	(revision 0)
@@ -0,0 +1,31 @@ 
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@synthesize isa;                    /* { dg-error "misplaced .@synthesize. Objective-C.. construct" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+  int v2;
+  int v3;
+  int v4;
+}
+@end
+
+@implementation Test
+@synthesize;                        /* { dg-error "expected identifier" } */
+@synthesize v1, ;                   /* { dg-error "expected identifier" } */
+@synthesize v1, v2 = ;              /* { dg-error "expected identifier" } */
+@synthesize v1, v2=v2, v3 = v3,v4;  /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v4;                     /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@end
Index: gcc/cp/ChangeLog
===================================================================
--- gcc/cp/ChangeLog	(revision 165665)
+++ gcc/cp/ChangeLog	(working copy)
@@ -1,4 +1,17 @@ 
 2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented parsing @synthesize and @dynamic for Objective-C++.
+	* parser.c (cp_parser_objc_method_definition_list): Recognize
+	RID_AT_SYNTHESIZE and RID_AT_DYNAMIC.
+	(cp_parser_objc_at_dynamic_declaration): New.
+	(cp_parser_objc_at_synthesize_declaration): New.
+
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>	
+
+	* parser.c (cp_parser_objc_identifier_list): Check the return
+	value of cp_parser_identifier and react if it is error_mark_node.
+
+2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
 	
 	Merge from apple/trunk branch on FSF servers.
 	
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 165665)
+++ gcc/cp/parser.c	(working copy)
@@ -2100,6 +2100,10 @@  static bool cp_parser_objc_valid_prefix_attributes
   (cp_parser *, tree *);
 static void cp_parser_objc_at_property 
   (cp_parser *) ;
+static void cp_parser_objc_at_synthesize_declaration 
+  (cp_parser *) ;
+static void cp_parser_objc_at_dynamic_declaration
+  (cp_parser *) ;
 static void cp_parser_objc_property_decl 
   (cp_parser *) ;
 
@@ -21270,18 +21274,29 @@  cp_parser_objc_selector_expression (cp_parser* par
 static tree
 cp_parser_objc_identifier_list (cp_parser* parser)
 {
-  tree list = build_tree_list (NULL_TREE, cp_parser_identifier (parser));
-  cp_token *sep = cp_lexer_peek_token (parser->lexer);
+  tree identifier;
+  tree list;
+  cp_token *sep;
 
+  identifier = cp_parser_identifier (parser);
+  if (identifier == error_mark_node)
+    return error_mark_node;      
+
+  list = build_tree_list (NULL_TREE, identifier);
+  sep = cp_lexer_peek_token (parser->lexer);
+
   while (sep->type == CPP_COMMA)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
-      list = chainon (list,
-		      build_tree_list (NULL_TREE,
-				       cp_parser_identifier (parser)));
+      identifier = cp_parser_identifier (parser);
+      if (identifier == error_mark_node)
+	return list;
+
+      list = chainon (list, build_tree_list (NULL_TREE,
+					     identifier));
       sep = cp_lexer_peek_token (parser->lexer);
     }
-
+  
   return list;
 }
 
@@ -21790,6 +21805,10 @@  cp_parser_objc_method_definition_list (cp_parser*
 	}
       else if (token->keyword == RID_AT_PROPERTY)
 	cp_parser_objc_at_property (parser);
+      else if (token->keyword == RID_AT_SYNTHESIZE)
+	cp_parser_objc_at_synthesize_declaration (parser);
+      else if (token->keyword == RID_AT_DYNAMIC)
+	cp_parser_objc_at_dynamic_declaration (parser);
       else if (token->keyword == RID_ATTRIBUTE 
       	       && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
 	warning_at (token->location, OPT_Wattributes,
@@ -22422,6 +22441,105 @@  cp_parser_objc_at_property (cp_parser *parser)
   /* ... and the property declaration(s).  */
   cp_parser_objc_property_decl (parser);
 }
+
+/* Parse an Objective-C++ @synthesize declaration.  The syntax is:
+
+   objc-synthesize-declaration:
+     @synthesize objc-synthesize-identifier-list ;
+
+   objc-synthesize-identifier-list:
+     objc-synthesize-identifier
+     objc-synthesize-identifier-list, objc-synthesize-identifier
+
+   objc-synthesize-identifier
+     identifier
+     identifier = identifier
+
+  For example:
+    @synthesize MyProperty;
+    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_synthesize_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@synthesize'.  */
+  while (true)
+    {
+      tree property, ivar;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+	{
+	  cp_parser_consume_semicolon_at_end_of_statement (parser);
+	  return;
+	}
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  ivar = cp_parser_identifier (parser);
+	  if (ivar == error_mark_node)
+	    {
+	      cp_parser_consume_semicolon_at_end_of_statement (parser);
+	      return;
+	    }
+	}
+      else
+	ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else
+	break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C++ @dynamic declaration.  The syntax is:
+
+   objc-dynamic-declaration:
+     @dynamic identifier-list ;
+
+   For example:
+     @dynamic MyProperty;
+     @dynamic MyProperty, AnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_dynamic_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@dynamic'.  */
+  while (true)
+    {
+      tree property;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+	{
+	  cp_parser_consume_semicolon_at_end_of_statement (parser);
+	  return;
+	}
+      list = chainon (list, build_tree_list (NULL, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else
+	break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_dynamic_declaration (loc, list);
+}
+
 
 /* OpenMP 2.5 parsing routines.  */
 
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 165665)
+++ gcc/c-parser.c	(working copy)
@@ -1082,6 +1082,8 @@  static tree c_parser_objc_receiver (c_parser *);
 static tree c_parser_objc_message_args (c_parser *);
 static tree c_parser_objc_keywordexpr (c_parser *);
 static void c_parser_objc_at_property (c_parser *) ;
+static void c_parser_objc_at_synthesize_declaration (c_parser *);
+static void c_parser_objc_at_dynamic_declaration (c_parser *);
 static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
@@ -1185,6 +1187,14 @@  c_parser_external_declaration (c_parser *parser)
 	  gcc_assert (c_dialect_objc ());
 	  c_parser_objc_at_property (parser);
 	  break;
+	case RID_AT_SYNTHESIZE:
+	  gcc_assert (c_dialect_objc ());
+	  c_parser_objc_at_synthesize_declaration (parser);
+	  break;
+	case RID_AT_DYNAMIC:
+	  gcc_assert (c_dialect_objc ());
+	  c_parser_objc_at_dynamic_declaration (parser);
+	  break;
 	case RID_AT_END:
 	  gcc_assert (c_dialect_objc ());
 	  c_parser_consume_token (parser);
@@ -6763,7 +6773,9 @@  c_parser_objc_class_declaration (c_parser *parser)
       if (c_parser_next_token_is_not (parser, CPP_NAME))
 	{
 	  c_parser_error (parser, "expected identifier");
-	  break;
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+	  parser->error = false;
+	  return;
 	}
       id = c_parser_peek_token (parser)->value;
       list = chainon (list, build_tree_list (NULL_TREE, id));
@@ -7689,6 +7701,119 @@  c_parser_objc_at_property (c_parser *parser)
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
+/* Parse an Objective-C @synthesize declaration.  The syntax is:
+
+   objc-synthesize-declaration:
+     @synthesize objc-synthesize-identifier-list ;
+
+   objc-synthesize-identifier-list:
+     objc-synthesize-identifier
+     objc-synthesize-identifier-list, objc-synthesize-identifier
+
+   objc-synthesize-identifier
+     identifier
+     identifier = identifier
+
+  For example:
+    @synthesize MyProperty;
+    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+  PS: This function is identical to cp_parser_objc_at_synthesize_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_synthesize_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property, ivar;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+	{
+	  c_parser_error (parser, "expected identifier");
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+	  /* Once we find the semicolon, we can resume normal parsing.
+	     We have to reset parser->error manually because
+	     c_parser_skip_until_found() won't reset it for us if the
+	     next token is precisely a semicolon.  */
+	  parser->error = false;
+	  return;
+	}
+      property = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_EQ))
+	{
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is_not (parser, CPP_NAME))
+	    {
+	      c_parser_error (parser, "expected identifier");
+	      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+	      parser->error = false;
+	      return;
+	    }
+	  ivar = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	}
+      else
+	ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C @dynamic declaration.  The syntax is:
+
+   objc-dynamic-declaration:
+     @dynamic identifier-list ;
+
+   For example:
+     @dynamic MyProperty;
+     @dynamic MyProperty, AnotherProperty;
+
+  PS: This function is identical to cp_parser_objc_at_dynamic_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_dynamic_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+	{
+	  c_parser_error (parser, "expected identifier");
+	  c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+	  parser->error = false;
+	  return;
+	}
+      property = c_parser_peek_token (parser)->value;
+      list = chainon (list, build_tree_list (NULL_TREE, property));
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_dynamic_declaration (loc, list);
+}
+
 
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within