summaryrefslogtreecommitdiff
path: root/gcc/c-parser.c
diff options
context:
space:
mode:
authoriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-14 20:09:41 +0000
committeriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-14 20:09:41 +0000
commit86c110acf8328aba9f0f4ed0316be3e1972b1b9e (patch)
tree2460cc4b29d1b167cadadbf17f50074e1a75ef92 /gcc/c-parser.c
parentbc2d6e846ba5988aa6a0527cfe5c55d4afa822a0 (diff)
downloadgcc-86c110acf8328aba9f0f4ed0316be3e1972b1b9e.tar.gz
add @property to ObjC*
merge from FSF apple 'trunk' branch. 2006 Fariborz Jahanian <fjahanian@apple.com> Radars 4436866, 4505126, 4506903, 4517826 gcc/c-family: * c-common.c (c_common_resword): Define @property and its attributes. * c-common.h: Define property attribute enum entries. (OBJC_IS_PATTR_KEYWORD): New. (objc_property_attribute_kind): New enum. Declare objc_set_property_attr (), objc_add_property_variable (), objc_build_getter_call () and objc_build_setter_call (). * stub-objc.c (objc_set_property_attr): New stub. (objc_add_property_variable): Likewise. (objc_build_getter_call): Likewise. (objc_build_setter_call) Likewise. gcc: * c-parser.c (c_parser, objc_property_attr_context) New flag. (c_lex_one_token): Handle property attributes. (c_parser_external_declaration): Handle @property. (c_parser_declaration_or_fndef): Warn on invalid attributes before @alias, @class, @end and @property objc keywords. (c_parser_objc_methodprotolist): Handle @property. (c_parser_objc_property_attrlist): New. (c_parser_objc_at_property): New. * c-typeck.c (build_component_ref): Handle CLASS.property syntax. (build_modify_expr): Likewise. gcc/cp: * typeck.c (finish_class_member_access_expr): Handle CLASS.property syntax. (cp_build_modify_expr): Likewise. * parser.c (cp_parser_objc_method_prototype_list): Handle @property. (cp_parser_objc_method_definition_list): Likewise. (cp_parser_objc_property_decl): New. (cp_parser_objc_property_attrlist): New. (cp_parser_objc_at_property): New. gcc/objc: * objc-act.c (CALL_EXPR_OBJC_PROPERTY_GETTER): New. property_readonly, property_getter, property_setter, property_ivar, property_copies, in_objc_property_setter_name_context: New vars. (objc_set_property_attr): New. (objc_add_property_variable): New. (lookup_property_in_list): New. (lookup_property): New. (objc_build_getter_call): New. (objc_setter_func_call): New. (get_selector_from_reference): New. (objc_build_setter_call): New. (is_property): New. (build_property_reference): New. (objc_finish_message_expr): Detect readonly property and warn. (objc_build_property_ivar_name): New. (objc_build_property_setter_name): New. (objc_gen_one_property_datum): New. (objc_process_getter_setter): New. (objc_synthesize_getter): New. (objc_synthesize_setter): New. (objc_gen_property_data): New. (finish_class): Generate property data. (comp_proto_with_proto): Separated from ... (match_proto_with_proto): ... New. (objc_lookup_ivar): Handle properties. * objc-tree.def (PROPERTY_DECL): New tree code. * objc-act.h: CLASS_LANG_SLOT_ELTS, PROTOCOL_LANG_SLOT_ELTS update size. (METHOD_PROPERTY_CONTEXT): New. (PROPERTY_NAME): New. (PROPERTY_GETTER_NAME): New. (PROPERTY_SETTER_NAME): New. (PROPERTY_IVAR_NAME): New. (PROPERTY_READONLY): New. (PROPERTY_COPIES): New. (TOTAL_CLASS_RAW_IVARS): New. (CLASS_PROPERTY_DECL): New. (IMPL_PROPERTY_DECL): New. * objc-lang.c (objc_init_ts): Update fields for property_decl. gcc/objcp: * objcp-lang.c (objcxx_init_ts): Update for property_decl. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165479 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-parser.c')
-rw-r--r--gcc/c-parser.c168
1 files changed, 167 insertions, 1 deletions
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 3953cc6943b..36ed95131f1 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -195,6 +195,9 @@ typedef struct GTY(()) c_parser {
undesirable to bind an identifier to an Objective-C class, even
if a class with that name exists. */
BOOL_BITFIELD objc_need_raw_identifier : 1;
+ /* True if we are in a context where the Objective-C "Property attribute"
+ keywords are valid. */
+ BOOL_BITFIELD objc_property_attr_context : 1;
} c_parser;
@@ -283,6 +286,20 @@ c_lex_one_token (c_parser *parser, c_token *token)
normal tokens.
*/
}
+ else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
+ {
+ /* We found an Objective-C "property attribute" keyword
+ (readonly, copies, getter, setter, ivar). These are
+ only valid in the property context. */
+ if (parser->objc_property_attr_context)
+ {
+ token->type = CPP_KEYWORD;
+ token->keyword = rid_code;
+ break;
+ }
+ /* Else they are not special keywords.
+ */
+ }
else if (c_dialect_objc ()
&& (OBJC_IS_AT_KEYWORD (rid_code)
|| OBJC_IS_CXX_KEYWORD (rid_code)))
@@ -573,6 +590,8 @@ c_token_starts_declaration (c_token *token)
return false;
}
+static c_token *c_parser_peek_2nd_token (c_parser *parser);
+
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
static inline bool
@@ -1062,7 +1081,8 @@ 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 bool c_parser_objc_diagnose_bad_element_prefix
+static void c_parser_objc_at_property (c_parser *) ;
+static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
/* Parse a translation unit (C90 6.7, C99 6.9).
@@ -1161,6 +1181,10 @@ c_parser_external_declaration (c_parser *parser)
gcc_assert (c_dialect_objc ());
c_parser_objc_protocol_definition (parser, NULL_TREE);
break;
+ case RID_AT_PROPERTY:
+ gcc_assert (c_dialect_objc ());
+ c_parser_objc_at_property (parser);
+ break;
case RID_AT_END:
gcc_assert (c_dialect_objc ());
c_parser_consume_token (parser);
@@ -1378,6 +1402,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
return;
}
break;
+ case RID_AT_ALIAS:
+ case RID_AT_CLASS:
+ case RID_AT_END:
+ case RID_AT_PROPERTY:
+ if (specs->attrs)
+ {
+ c_parser_error (parser,
+ "attributes may not be specified before" );
+ specs->attrs = NULL;
+ }
+ break;
default:
break;
}
@@ -6942,6 +6977,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
default:
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);
else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
{
objc_set_method_opt (true);
@@ -7517,6 +7554,135 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
}
return false;
}
+
+/* ObjC @property. */
+
+/* Parse a comma-separated list of property attributes. */
+
+static void
+c_parser_objc_property_attrlist (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);
+
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ return;
+
+ /* 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)
+ {
+ 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)
+ {
+ tree ident;
+ objc_property_attribute_kind pkind;
+ case RID_READONLY:
+ 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 %<=%>");
+ 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;
+ 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);
+
+ /* Comma-separated properties are chained together in
+ reverse order; add them one by one. */
+ props = nreverse (props);
+
+ for (; props; props = TREE_CHAIN (props))
+ objc_add_property_variable (copy_node (props));
+
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
should be considered, statements. ALLOW_STMT is true if we're within