From 1d894bcf47c398d81f7ea42eff8a5da823799bf7 Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 27 Oct 2010 04:37:47 +0000 Subject: In gcc/: 2010-10-27 Nicola Pero * c-parser.c (c_parser_objc_at_property): Renamed to c_parser_objc_at_property_declaration. Updated calls to objc_add_property_variable, now objc_add_property_declaration. Code rewritten to be much more robust in recovering from syntax errors. Added comments. (c_parser_objc_property_attrlist): Removed. (c_parser_external_declaration): Updated calls to c_parser_objc_at_property, now c_parser_objc_at_property_declaration. (c_parser_objc_methodprotolist): Same change. In gcc/c-family/: 2010-10-27 Nicola Pero * c-common.h (objc_add_property_variable): Renamed to objc_add_property_declaration. Added location argument. * stub-objc.c (objc_add_property_variable): Same change. In gcc/cp/: 2010-10-27 Nicola Pero * parser.c (cp_parser_objc_property_decl): Renamed to cp_parser_objc_struct_declaration. Return the parsed trees instead of calling objc_add_property_variable directly. Detect missing or invalid declspecs. Implemented attributes. Do not eat the ';' at the end. Exit loop whenever a non-comma is parsed, not just EOF. (cp_parser_objc_at_property): Renamed to cp_parser_objc_at_property_declaration. Updated calls to objc_add_property_variable, now objc_add_property_declaration, and to cp_parser_objc_property_decl, now cp_parser_objc_struct_declaration. Rewritten all code to be more robust in dealing with syntax errors, and almost identical to the one in c_parser_objc_at_property_declaration. (cp_parser_objc_property_attrlist): Removed. (cp_parser_objc_method_prototype_list): Updated call to cp_parser_objc_at_property. (cp_parser_objc_method_definition_list): Same change. (cp_parser_objc_class_ivars): Detect a number of invalid declarations of instance variables and produce errors when they are found. In gcc/objc/: 2010-10-27 Nicola Pero * objc-act.c (objc_add_property_variable): Renamed to objc_add_property_declaration. Added location argument. Updated warnings and errors to use it. Use error, not fatal_error, if a property declaration is found outside an interface or implementation context. In gcc/testsuite/: 2010-10-27 Nicola Pero * objc.dg/property/at-property-1.m: New. * objc.dg/property/at-property-2.m: New. * objc.dg/property/at-property-3.m: New. * objc.dg/ivar-invalid-type-1.m: New. * obj-c++.dg/property/at-property-1.mm: New. * obj-c++.dg/property/at-property-2.mm: New. * obj-c++.dg/property/at-property-3.mm: New. * obj-c++.dg/ivar-invalid-type-1.mm: New. * objc.dg/property/property-neg-6.m: Updated testcase for updates in error reporting. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165996 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/c-parser.c | 272 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 159 insertions(+), 113 deletions(-) (limited to 'gcc/c-parser.c') diff --git a/gcc/c-parser.c b/gcc/c-parser.c index e4efd38cac6..c885c8a9610 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -1081,7 +1081,7 @@ static tree c_parser_objc_selector_arg (c_parser *); 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_property_declaration (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 @@ -1185,7 +1185,7 @@ c_parser_external_declaration (c_parser *parser) break; case RID_AT_PROPERTY: gcc_assert (c_dialect_objc ()); - c_parser_objc_at_property (parser); + c_parser_objc_at_property_declaration (parser); break; case RID_AT_SYNTHESIZE: gcc_assert (c_dialect_objc ()); @@ -6997,7 +6997,7 @@ c_parser_objc_methodprotolist (c_parser *parser) if (c_parser_next_token_is_keyword (parser, RID_AT_END)) return; else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY)) - c_parser_objc_at_property (parser); + c_parser_objc_at_property_declaration (parser); else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL)) { objc_set_method_opt (true); @@ -7574,132 +7574,178 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, return false; } -/* ObjC @property. */ +/* Parse an Objective-C @property declaration. The syntax is: -/* Parse a comma-separated list of property attributes. */ + objc-property-declaration: + '@property' objc-property-attributes[opt] struct-declaration ; + objc-property-attributes: + '(' objc-property-attribute-list ')' + + objc-property-attribute-list: + objc-property-attribute + objc-property-attribute-list, objc-property-attribute + + objc-property-attribute + 'getter' = identifier + 'setter' = identifier + 'readonly' + 'readwrite' + 'assign' + 'retain' + 'copy' + 'nonatomic' + + For example: + @property NSString *name; + @property (readonly) id object; + @property (retain, nonatomic, getter=getTheName) id name; + @property int a, b, c; + + PS: This function is identical to cp_parser_objc_at_propery_declaration + for C++. Keep them in sync. + + WORK IN PROGRESS: At the moment, the list of attributes that are + parsed is different from the above list. It will be updated to use + the above list at the same time as @synthesize is implemented. */ static void -c_parser_objc_property_attrlist (c_parser *parser) +c_parser_objc_at_property_declaration (c_parser *parser) { - bool err = false; - /* Initialize to an empty list. */ - objc_set_property_attr (c_parser_peek_token (parser)->location, - OBJC_PATTR_INIT, NULL_TREE); + tree properties; + location_t loc; + loc = c_parser_peek_token (parser)->location; + gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY)); - if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) - return; + c_parser_consume_token (parser); /* Eat '@property'. */ - /* Eat the '(' */ - c_parser_consume_token (parser); - - /* Property attribute keywords are valid now. */ - parser->objc_property_attr_context = true; - while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) - && c_parser_next_token_is_not (parser, CPP_EOF) - && !err) + /* Initialize attributes to an empty list. */ + objc_set_property_attr (loc, OBJC_PATTR_INIT, NULL_TREE); + + /* Parse the optional attribute list... */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { - enum rid keywd; - location_t loc; - if (c_parser_peek_token (parser)->type != CPP_KEYWORD) - { - c_parser_error (parser, "expected a property attribute"); - c_parser_consume_token (parser); - err = true; - break; - } - keywd = c_parser_peek_token (parser)->keyword; - /* Initially, make diagnostics point to the attribute. */ - loc = c_parser_peek_token (parser)->location; - switch (keywd) + /* Eat the '(' */ + c_parser_consume_token (parser); + + /* Property attribute keywords are valid now. */ + parser->objc_property_attr_context = true; + + while (true) { - tree ident; - objc_property_attribute_kind pkind; - case RID_READONLY: - objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE); + bool syntax_error = false; + c_token *token = c_parser_peek_token (parser); + enum rid keyword; + + if (token->type != CPP_KEYWORD) + { + if (token->type == CPP_CLOSE_PAREN) + c_parser_error (parser, "expected identifier"); + else + { + c_parser_consume_token (parser); + c_parser_error (parser, "unknown property attribute"); + } + break; + } + keyword = token->keyword; + switch (keyword) + { + tree ident; + objc_property_attribute_kind pkind; + case RID_READONLY: + c_parser_consume_token (parser); + objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE); + break; + case RID_GETTER: + case RID_SETTER: + case RID_IVAR: + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_EQ)) + { + c_parser_error (parser, + "getter/setter/ivar attribute must be followed by %<=%>"); + syntax_error = true; + break; + } + c_parser_consume_token (parser); /* eat the = */ + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + syntax_error = true; + break; + } + ident = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + if (keyword == RID_SETTER) + { + pkind = OBJC_PATTR_SETTER; + /* Eat the identifier, and look for the following : */ + if (c_parser_next_token_is_not (parser, CPP_COLON)) + { + c_parser_error (parser, + "setter name must be followed by %<:%>"); + syntax_error = true; + break; + } + c_parser_consume_token (parser); + } + else if (keyword == RID_GETTER) + pkind = OBJC_PATTR_GETTER; + else + pkind = OBJC_PATTR_IVAR; + objc_set_property_attr (loc, pkind, ident); + break; + case RID_COPIES: + c_parser_consume_token (parser); + objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE); + break; + default: + if (token->type == CPP_CLOSE_PAREN) + c_parser_error (parser, "expected identifier"); + else + { + c_parser_consume_token (parser); + c_parser_error (parser, "unknown property attribute"); + } + syntax_error = true; + break; + } + + if (syntax_error) break; - case RID_GETTER: - case RID_SETTER: - case RID_IVAR: + + if (c_parser_next_token_is (parser, CPP_COMMA)) c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_EQ)) - { - c_parser_error (parser, - "getter/setter/ivar attribute must be followed by %<=%>"); - err = true; - break; - } - c_parser_consume_token (parser); /* eat the = */ - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected an identifier"); - err = true; - break; - } - ident = c_parser_peek_token (parser)->value; - if (keywd == RID_SETTER) - { - pkind = OBJC_PATTR_SETTER; - /* Eat the identifier, and look for the following : */ - c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_COLON)) - { - c_parser_error (parser, - "setter name must be followed by %<:%>"); - err = true; - } - } - else if (keywd == RID_GETTER) - pkind = OBJC_PATTR_GETTER; - else - pkind = OBJC_PATTR_IVAR; - - objc_set_property_attr (loc, pkind, ident); - break; - case RID_COPIES: - objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE); - break; - default: - c_parser_error (parser, "unknown property attribute"); - err = true; + else break; } - /* Eat the attribute,identifier or colon that's been used. */ - c_parser_consume_token (parser); - if (err) - break; - - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - warning_at (c_parser_peek_token (parser)->location, 0, - "property attributes should be separated by a %<,%>"); - } - parser->objc_property_attr_context = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); -} - -/* Parse property attributes and then the definition. */ - -static void -c_parser_objc_at_property (c_parser *parser) -{ - tree props; - /* We should only arrive here with the property keyword. */ - c_parser_require_keyword (parser, RID_AT_PROPERTY, "expected %<@property%>"); - - /* Process the optional attribute list... */ - c_parser_objc_property_attrlist (parser) ; - /* ... and the property var decls. */ - props = c_parser_struct_declaration (parser); + parser->objc_property_attr_context = false; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + } + /* ... and the property declaration(s). */ + properties = c_parser_struct_declaration (parser); - /* Comma-separated properties are chained together in - reverse order; add them one by one. */ - props = nreverse (props); + if (properties == error_mark_node) + { + c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); + parser->error = false; + return; + } - for (; props; props = TREE_CHAIN (props)) - objc_add_property_variable (copy_node (props)); + if (properties == NULL_TREE) + c_parser_error (parser, "expected identifier"); + else + { + /* Comma-separated properties are chained together in + reverse order; add them one by one. */ + properties = nreverse (properties); + + for (; properties; properties = TREE_CHAIN (properties)) + objc_add_property_declaration (loc, copy_node (properties)); + } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + parser->error = false; } /* Parse an Objective-C @synthesize declaration. The syntax is: -- cgit v1.2.1