From patchwork Mon Oct 18 22:49:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 68248 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id E45DEB70E2 for ; Tue, 19 Oct 2010 09:49:29 +1100 (EST) Received: (qmail 21614 invoked by alias); 18 Oct 2010 22:49:28 -0000 Received: (qmail 21601 invoked by uid 22791); 18 Oct 2010 22:49:25 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL, BAYES_00, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 18 Oct 2010 22:49:18 +0000 Received: from eggs.gnu.org ([140.186.70.92]:53002) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P7yW4-0008MX-EI for gcc-patches@gnu.org; Mon, 18 Oct 2010 18:49:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P7yW2-0002el-4L for gcc-patches@gnu.org; Mon, 18 Oct 2010 18:49:16 -0400 Received: from smtp161.iad.emailsrvr.com ([207.97.245.161]:57018) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P7yW2-0002ef-0U for gcc-patches@gnu.org; Mon, 18 Oct 2010 18:49:14 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp46.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 5F6B7E8804 for ; Mon, 18 Oct 2010 18:49:13 -0400 (EDT) X-Orig-To: gcc-patches@gnu.org Received: from dynamic4.wm-web.iad.mlsrvr.com (dynamic4.wm-web.iad1a.rsapps.net [192.168.2.153]) by smtp46.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 4B46CE86E6 for ; Mon, 18 Oct 2010 18:49:13 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic4.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 3A5FA1D4A24C for ; Mon, 18 Oct 2010 18:49:13 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Tue, 19 Oct 2010 00:49:13 +0200 (CEST) Date: Tue, 19 Oct 2010 00:49:13 +0200 (CEST) Subject: ObjC/ObjC++ - parse @synthesize and @dynamic From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1287442153.23494018@192.168.2.229> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 ;. 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 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 * 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 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 * 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 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 * objc-act.c (lookup_and_install_protocols): Return NULL if passed error_mark_node. In gcc/testsuite/: 2010-10-18 Nicola Pero 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 * objc.dg/at-class-1.m: New. * objc.dg/at-class-1.mm: New. 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 + 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 + Merge from 'apple/trunk' branch on FSF servers. 2005-11-08 Fariborz Jahanian 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 + 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 + + * objc-act.c (lookup_and_install_protocols): Return NULL if passed + error_mark_node. + +2010-10-18 Nicola Pero + Merge from 'apple/trunk' branch on FSF servers. 2006-03-10 Fariborz Jahanian Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 165665) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,16 @@ +2010-10-18 Nicola Pero + + 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 + + * 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 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 + + 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 + + * objc.dg/at-class-1.m: New. + * objc.dg/at-class-1.mm: New. + 2010-10-18 Steve Ellcey * 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 + +@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 + +@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 + +@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 + +@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 + + 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 + + * 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 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