diff options
author | Iain Sandoe <iains@gcc.gnu.org> | 2010-10-14 20:09:41 +0000 |
---|---|---|
committer | Iain Sandoe <iains@gcc.gnu.org> | 2010-10-14 20:09:41 +0000 |
commit | 668ea4b1106d1a28e07ed653874192696840829c (patch) | |
tree | 2460cc4b29d1b167cadadbf17f50074e1a75ef92 /gcc | |
parent | e05eee4908da6139ecdfe1be68af5b58418ceedf (diff) | |
download | gcc-668ea4b1106d1a28e07ed653874192696840829c.zip gcc-668ea4b1106d1a28e07ed653874192696840829c.tar.gz gcc-668ea4b1106d1a28e07ed653874192696840829c.tar.bz2 |
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.
From-SVN: r165479
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 7 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 29 | ||||
-rw-r--r-- | gcc/c-family/stub-objc.c | 24 | ||||
-rw-r--r-- | gcc/c-parser.c | 168 | ||||
-rw-r--r-- | gcc/c-typeck.c | 16 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/parser.c | 150 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 19 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 45 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 882 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 19 | ||||
-rw-r--r-- | gcc/objc/objc-lang.c | 5 | ||||
-rw-r--r-- | gcc/objc/objc-tree.def | 1 | ||||
-rw-r--r-- | gcc/objcp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/objcp/objcp-lang.c | 5 |
17 files changed, 1408 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 499efa5..262a377 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2010-10-14 Iain Sandoe <iains@gcc.gnu.org> + + merge from FSF apple 'trunk' branch. + 2006 Fariborz Jahanian <fjahanian@apple.com> + + Radars 4436866, 4505126, 4506903, 4517826 + * 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. + 2010-10-14 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/46008 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index dde5c45..5ba4659 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,20 @@ +2010-10-14 Iain Sandoe <iains@gcc.gnu.org> + + merge from FSF apple 'trunk' branch. + 2006 Fariborz Jahanian <fjahanian@apple.com> + + Radars 4436866, 4505126, 4506903, 4517826 + * 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. + 2010-10-13 Iain Sandoe <iains@gcc.gnu.org> merge from FSF apple 'trunk' branch. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 49eb510..5203c05 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -543,6 +543,7 @@ const struct c_common_resword c_common_reswords[] = { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC }, { "optional", RID_AT_OPTIONAL, D_OBJC }, { "required", RID_AT_REQUIRED, D_OBJC }, + { "property", RID_AT_PROPERTY, D_OBJC }, /* These are recognized only in protocol-qualifier context (see above) */ { "bycopy", RID_BYCOPY, D_OBJC }, @@ -551,6 +552,12 @@ const struct c_common_resword c_common_reswords[] = { "inout", RID_INOUT, D_OBJC }, { "oneway", RID_ONEWAY, D_OBJC }, { "out", RID_OUT, D_OBJC }, + /* These are recognized inside a property attribute list */ + { "readonly", RID_READONLY, D_OBJC }, + { "copies", RID_COPIES, D_OBJC }, + { "getter", RID_GETTER, D_OBJC }, + { "setter", RID_SETTER, D_OBJC }, + { "ivar", RID_IVAR, D_OBJC }, }; const unsigned int num_c_common_reswords = diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 71efaf9..8c79d27 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -80,6 +80,10 @@ enum rid are keywords only in specific contexts) */ RID_IN, RID_OUT, RID_INOUT, RID_BYCOPY, RID_BYREF, RID_ONEWAY, + /* ObjC ("PATTR" reserved words - they do not appear after a '@' + and are keywords only as property attributes) */ + RID_READONLY, RID_COPIES, RID_GETTER, RID_SETTER, RID_IVAR, + /* C (reserved and imaginary types not implemented, so any use is a syntax error) */ RID_IMAGINARY, @@ -143,7 +147,7 @@ enum rid RID_AT_PROTOCOL, RID_AT_SELECTOR, RID_AT_THROW, RID_AT_TRY, RID_AT_CATCH, RID_AT_FINALLY, RID_AT_SYNCHRONIZED, - RID_AT_OPTIONAL, RID_AT_REQUIRED, + RID_AT_OPTIONAL, RID_AT_REQUIRED, RID_AT_PROPERTY, RID_AT_INTERFACE, RID_AT_IMPLEMENTATION, @@ -181,7 +185,9 @@ enum rid RID_FIRST_AT = RID_AT_ENCODE, RID_LAST_AT = RID_AT_IMPLEMENTATION, RID_FIRST_PQ = RID_IN, - RID_LAST_PQ = RID_ONEWAY + RID_LAST_PQ = RID_ONEWAY, + RID_FIRST_PATTR = RID_READONLY, + RID_LAST_PATTR = RID_IVAR }; #define OBJC_IS_AT_KEYWORD(rid) \ @@ -192,6 +198,10 @@ enum rid ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PQ && \ (unsigned int) (rid) <= (unsigned int) RID_LAST_PQ) +#define OBJC_IS_PATTR_KEYWORD(rid) \ + ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \ + (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR) + /* OBJC_IS_CXX_KEYWORD recognizes the 'CXX_OBJC' keywords (such as 'class') which are shared in a subtle way between Objective-C and C++. When the lexer is lexing in Objective-C/Objective-C++, if it @@ -420,6 +430,16 @@ extern c_language_kind c_language; #define c_dialect_cxx() ((c_language & clk_cxx) != 0) #define c_dialect_objc() ((c_language & clk_objc) != 0) +/* ObjC Property Attribute types. */ +typedef enum objc_property_attribute_kind { + OBJC_PATTR_INIT = 0, + OBJC_PATTR_READONLY = 1, + OBJC_PATTR_GETTER = 2, + OBJC_PATTR_SETTER = 3, + OBJC_PATTR_IVAR = 4, + OBJC_PATTR_COPIES = 5 +} objc_property_attribute_kind; + /* The various name of operator that appears in error messages. */ typedef enum ref_operator { /* NULL */ @@ -1009,7 +1029,12 @@ extern tree objc_generate_static_init_call (tree); extern tree objc_generate_write_barrier (tree, enum tree_code, tree); extern void objc_set_method_opt (bool); extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree); +extern void objc_set_property_attr + (location_t, objc_property_attribute_kind, tree); 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); /* The following are provided by the C and C++ front-ends, and called by ObjC/ObjC++. */ diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c index 6b8c334..4a8a2b5 100644 --- a/gcc/c-family/stub-objc.c +++ b/gcc/c-family/stub-objc.c @@ -314,6 +314,30 @@ objc_get_class_ivars (tree ARG_UNUSED (name)) return 0; } +void +objc_set_property_attr (location_t ARG_UNUSED (loc), + objc_property_attribute_kind ARG_UNUSED (code), + tree ARG_UNUSED (identifier)) +{ +} + +void +objc_add_property_variable (tree ARG_UNUSED (prop)) +{ +} + +tree +objc_build_getter_call (tree ARG_UNUSED (datum), tree ARG_UNUSED (component)) +{ + return 0; +} + +tree +objc_build_setter_call (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs)) +{ + return 0; +} + tree objc_build_throw_stmt (location_t ARG_UNUSED (loc), tree ARG_UNUSED (expr)) { diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 3953cc6..36ed951 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 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index fe10e8b..9a7cdc5 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2130,6 +2130,10 @@ build_component_ref (location_t loc, tree datum, tree component) if (!objc_is_public (datum, component)) return error_mark_node; + if (c_dialect_objc () + && (ref = objc_build_getter_call (datum, component))) + return ref; + /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) @@ -4837,7 +4841,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - if (!lvalue_or_else (lhs, lv_assign)) + /* For ObjC, defer this check until we have assessed CLASS.property. */ + if (!c_dialect_objc () && !lvalue_or_else (lhs, lv_assign)) return error_mark_node; if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) @@ -4878,6 +4883,15 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, rhs_origtype = NULL_TREE; } + if (c_dialect_objc ()) + { + result = objc_build_setter_call (lhs, newrhs); + if (result) + return result; + if (!lvalue_or_else (lhs, lv_assign)) + return error_mark_node; + } + /* Give an error for storing in something that is 'const'. */ if (TYPE_READONLY (lhstype) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ea6f0f5..20ca6a6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2010-10-14 Iain Sandoe <iains@gcc.gnu.org> + + merge from FSF apple 'trunk' branch. + 2006 Fariborz Jahanian <fjahanian@apple.com> + + Radars 4436866, 4505126, 4506903, 4517826 + * 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. + 2010-10-14 Richard Guenther <rguenther@suse.de> PR lto/44561 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f5f4521..3e02cd5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2097,7 +2097,11 @@ static void cp_parser_objc_declaration static tree cp_parser_objc_statement (cp_parser *); static bool cp_parser_objc_valid_prefix_attributes - (cp_parser* parser, tree *attrib); + (cp_parser *, tree *); +static void cp_parser_objc_at_property + (cp_parser *) ; +static void cp_parser_objc_property_decl + (cp_parser *) ; /* Utility Routines */ @@ -21718,6 +21722,8 @@ cp_parser_objc_method_prototype_list (cp_parser* parser) objc_add_method_declaration (sig, attributes); cp_parser_consume_semicolon_at_end_of_statement (parser); } + else if (token->keyword == RID_AT_PROPERTY) + cp_parser_objc_at_property (parser); else if (token->keyword == RID_ATTRIBUTE && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) warning_at (cp_lexer_peek_token (parser->lexer)->location, @@ -21779,6 +21785,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser) objc_finish_method_definition (meth); } } + else if (token->keyword == RID_AT_PROPERTY) + cp_parser_objc_at_property (parser); else if (token->keyword == RID_ATTRIBUTE && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) warning_at (token->location, OPT_Wattributes, @@ -22271,6 +22279,146 @@ cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) cp_lexer_rollback_tokens (parser->lexer); return false; } + +/* This routine parses the propery declarations. */ + +static void +cp_parser_objc_property_decl (cp_parser *parser) +{ + int declares_class_or_enum; + cp_decl_specifier_seq declspecs; + + cp_parser_decl_specifier_seq (parser, + CP_PARSER_FLAGS_NONE, + &declspecs, + &declares_class_or_enum); + /* Keep going until we hit the `;' at the end of the declaration. */ + while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + { + tree property; + cp_token *token; + cp_declarator *declarator + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, + NULL, NULL, false); + property = grokdeclarator (declarator, &declspecs, NORMAL,0, NULL); + /* Recover from any kind of error in property declaration. */ + if (property == error_mark_node || property == NULL_TREE) + return; + + /* Add to property list. */ + objc_add_property_variable (copy_node (property)); + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); /* Eat ','. */ + continue; + } + else if (token->type == CPP_EOF) + break; + } + /* Eat ';' if present, or issue an error. */ + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); +} + +/* ObjC @property. */ +/* Parse a comma-separated list of property attributes. + The lexer does not recognize */ + +static void +cp_parser_objc_property_attrlist (cp_parser *parser) +{ + cp_token *token; + /* Initialize to an empty list. */ + objc_set_property_attr (cp_lexer_peek_token (parser->lexer)->location, + OBJC_PATTR_INIT, NULL_TREE); + + /* The list is optional. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + return; + + /* Eat the '('. */ + cp_lexer_consume_token (parser->lexer); + + token = cp_lexer_peek_token (parser->lexer); + while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF) + { + location_t loc = token->location; + tree node = cp_parser_identifier (parser); + if (node == ridpointers [(int) RID_READONLY]) + objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE); + else if (node == ridpointers [(int) RID_GETTER] + || node == ridpointers [(int) RID_SETTER] + || node == ridpointers [(int) RID_IVAR]) + { + /* Do the getter/setter/ivar attribute. */ + token = cp_lexer_consume_token (parser->lexer); + if (token->type == CPP_EQ) + { + tree attr_ident = cp_parser_identifier (parser); + objc_property_attribute_kind pkind; + if (node == ridpointers [(int) RID_GETTER]) + pkind = OBJC_PATTR_GETTER; + else if (node == ridpointers [(int) RID_SETTER]) + { + pkind = OBJC_PATTR_SETTER; + /* Consume the ':' which must always follow the setter name. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + cp_lexer_consume_token (parser->lexer); + else + { + error_at (token->location, + "setter name must be followed by %<:%>"); + break; + } + } + else + pkind = OBJC_PATTR_IVAR; + objc_set_property_attr (loc, pkind, attr_ident); + } + else + { + error_at (token->location, + "getter/setter/ivar attribute must be followed by %<=%>"); + break; + } + } + else if (node == ridpointers [(int) RID_COPIES]) + objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE); + else + { + error_at (token->location,"unknown property attribute"); + break; + } + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) + warning_at (token->location, 0, + "property attributes should be separated by a %<,%>"); + token = cp_lexer_peek_token (parser->lexer); + } + + if (token->type != CPP_CLOSE_PAREN) + error_at (token->location, + "syntax error in @property's attribute declaration"); + else + /* Consume ')' */ + cp_lexer_consume_token (parser->lexer); +} + +/* This function parses a @property declaration inside an objective class + or its implementation. */ + +static void +cp_parser_objc_at_property (cp_parser *parser) +{ + /* Consume @property */ + cp_lexer_consume_token (parser->lexer); + + /* Parse optional attributes list... */ + cp_parser_objc_property_attrlist (parser); + /* ... and the property declaration(s). */ + cp_parser_objc_property_decl (parser); +} /* OpenMP 2.5 parsing routines. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ff5714d..ca832c6 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2593,7 +2593,11 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, return build_min_nt (COMPONENT_REF, object, name, NULL_TREE); object = build_non_dependent_expr (object); } - + else if (c_dialect_objc () + && TREE_CODE (name) == IDENTIFIER_NODE + && (expr = objc_build_getter_call (object, name))) + return expr; + /* [expr.ref] The type of the first expression shall be "class object" (of a @@ -6758,6 +6762,13 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, if (modifycode == NOP_EXPR) { + if (c_dialect_objc ()) + { + result = objc_build_setter_call (lhs, rhs); + if (result) + return result; + } + /* `operator=' is not an inheritable operator. */ if (! MAYBE_CLASS_TYPE_P (lhstype)) /* Do the default thing. */; @@ -6796,6 +6807,12 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, /* Now it looks like a plain assignment. */ modifycode = NOP_EXPR; + if (c_dialect_objc ()) + { + result = objc_build_setter_call (lhs, newrhs); + if (result) + return result; + } } gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE); diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 81a872d..1a51c14 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,48 @@ +2010-10-14 Iain Sandoe <iains@gcc.gnu.org> + + merge from FSF apple 'trunk' branch. + 2006 Fariborz Jahanian <fjahanian@apple.com> + + Radars 4436866, 4505126, 4506903, 4517826 + * 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. + 2010-10-13 Richard Henderson <rth@redhat.com> * objc-act.c (objc_eh_personality): Update call to diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index edde784..88f5d6c 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -163,6 +163,27 @@ static void build_next_objc_exception_stuff (void); static bool objc_derived_from_p (tree, tree); #define DERIVED_FROM_P(PARENT, CHILD) objc_derived_from_p (PARENT, CHILD) #endif + +/* Property. */ +static void objc_gen_one_property_datum (tree, tree, tree, bool*); +static void objc_gen_property_data (tree, tree); +static void objc_synthesize_getter (tree, tree, tree); +static void objc_process_getter_setter (tree, tree, bool); +static void objc_synthesize_setter (tree, tree, tree); +static char *objc_build_property_ivar_name (tree); +static char *objc_build_property_setter_name (tree, bool); +static int match_proto_with_proto (tree, tree, int); +static tree lookup_property (tree, tree); +static tree lookup_property_in_list (tree, tree); +static tree lookup_property_in_protocol_list (tree, tree); +static tree objc_setter_func_call (tree, tree, tree); +static tree build_property_reference (tree, tree); +static tree is_property (tree, tree); +/* Set on a CALL_EXPR if it is for call to a getter function represented by an + objective-c property declaration. */ +#define CALL_EXPR_OBJC_PROPERTY_GETTER(NODE) \ + (CALL_EXPR_CHECK(NODE)->base.deprecated_flag) + static void objc_xref_basetypes (tree, tree); static void build_class_template (void); @@ -194,6 +215,10 @@ static hash hash_lookup (hash *, tree); static tree lookup_method (tree, tree); static tree lookup_method_static (tree, tree, int); +static tree add_class (tree, tree); +static void add_category (tree, tree); +static inline tree lookup_category (tree, tree); + enum string_section { class_names, /* class, category, protocol, module names */ @@ -369,6 +394,13 @@ static int method_slot = 0; required. */ static bool objc_method_optional_flag = false; +static bool property_readonly; +static tree property_getter; +static tree property_setter; +static tree property_ivar; +static bool property_copies; +static bool in_objc_property_setter_name_context = false; + static int objc_collecting_ivars = 0; #define BUFSIZE 1024 @@ -807,6 +839,449 @@ objc_set_method_opt (bool optional) } } +/* This routine gathers property attribute information from the attribute + portion of a property declaration. */ + +void +objc_set_property_attr (location_t loc, objc_property_attribute_kind attr, + tree ident) +{ + static char string[BUFSIZE]; + switch (attr) + { + case OBJC_PATTR_INIT: /* init */ + property_readonly = property_copies = false; + property_setter = property_getter = property_ivar = NULL_TREE; + break; + case OBJC_PATTR_READONLY: /* readonly */ + property_readonly = true; + break; + case OBJC_PATTR_GETTER: /* getter = ident */ + if (property_getter != NULL_TREE) + error_at (loc, "the %<getter%> attribute may only be specified once"); + property_getter = ident; + break; + case OBJC_PATTR_SETTER: /* setter = ident */ + if (property_setter != NULL_TREE) + error_at (loc, "the %<setter%> attribute may only be specified once"); + /* setters always have a trailing ':' in their name. In fact, this is the + only syntax that parser recognizes for a setter name. Must add a trailing + ':' here so name matches that of the declaration of user instance method + for the setter. */ + sprintf (string, "%s:", IDENTIFIER_POINTER (ident)); + property_setter = get_identifier (string);; + break; + case OBJC_PATTR_IVAR: /* ivar = ident */ + if (property_ivar != NULL_TREE) + error_at (loc, "the %<ivar%> attribute may only be specified once"); + else if (objc_interface_context) + { + warning_at (loc, 0, "the %<ivar%> attribute is ignored in an @interface"); + property_ivar = NULL_TREE; + } + else + property_ivar = ident; + break; + case OBJC_PATTR_COPIES: /* copies */ + property_copies = true; + break; + default: + break; + } +} + +/* This routine builds a 'property_decl' tree node and adds it to the list + of such properties in the current class. It also checks for duplicates. +*/ + +void +objc_add_property_variable (tree decl) +{ + tree property_decl; + tree x; + tree interface = NULL_TREE; + + if (objc_implementation_context) + { + interface = lookup_interface (CLASS_NAME (objc_implementation_context)); + if (!interface) + { + error ("no class property can be implemented without an interface"); + return; + } + if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE) + { + interface = lookup_category (interface, + CLASS_SUPER_NAME (objc_implementation_context)); + if (!interface) + { + error ("no category property can be implemented without an interface"); + return; + } + } + } + else if (!objc_interface_context) + { + fatal_error ("property declaration not in @interface or @implementation context"); + return; + } + + property_decl = make_node (PROPERTY_DECL); + TREE_TYPE (property_decl) = TREE_TYPE (decl); + + PROPERTY_NAME (property_decl) = DECL_NAME (decl); + PROPERTY_GETTER_NAME (property_decl) = property_getter; + PROPERTY_SETTER_NAME (property_decl) = property_setter; + PROPERTY_IVAR_NAME (property_decl) = property_ivar; + PROPERTY_READONLY (property_decl) = property_readonly + ? boolean_true_node + : boolean_false_node; + PROPERTY_COPIES (property_decl) = property_copies + ? boolean_true_node + : boolean_false_node; + + if (objc_interface_context) + { + /* Doing the property in interface declaration. */ + + /* Issue error if property and an ivar name match. */ + if (TREE_CODE (objc_interface_context) == CLASS_INTERFACE_TYPE + && is_ivar (CLASS_IVARS (objc_interface_context), DECL_NAME (decl))) + error ("property %qD may not have the same name as an ivar in the class", decl); + /* must check for duplicate property declarations. */ + for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x)) + { + if (PROPERTY_NAME (x) == DECL_NAME (decl)) + { + error ("duplicate property declaration %qD", decl); + return; + } + } + TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context); + CLASS_PROPERTY_DECL (objc_interface_context) = property_decl; + } + else + { + /* Doing the property in implementation context. */ + /* If property is not declared in the interface issue error. */ + for (x = CLASS_PROPERTY_DECL (interface); x; x = TREE_CHAIN (x)) + if (PROPERTY_NAME (x) == DECL_NAME (decl)) + break; + if (!x) + { + error ("no declaration of property %qD found in the interface", decl); + return; + } + /* readonlys must also match. */ + if (PROPERTY_READONLY (x) != PROPERTY_READONLY (property_decl)) + { + error ("property %qD %<readonly%> attribute conflicts with its" + " interface version", decl); + } + /* copies must also match. */ + if (PROPERTY_COPIES (x) != PROPERTY_COPIES (property_decl)) + { + error ("property %qD %<copies%> attribute conflicts with its" + " interface version", decl); + } + /* Cannot have readonly and setter attribute for the same property. */ + if (PROPERTY_READONLY (property_decl) == boolean_true_node && + PROPERTY_SETTER_NAME (property_decl)) + { + warning (0, "a %<readonly%> property cannot have a setter (ignored)"); + PROPERTY_SETTER_NAME (property_decl) = NULL_TREE; + } + /* Add the property to the list of properties for current implementation. */ + TREE_CHAIN (property_decl) = IMPL_PROPERTY_DECL (objc_implementation_context); + IMPL_PROPERTY_DECL (objc_implementation_context) = property_decl; + } +} + +/* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or + PROTOCOL. +*/ +static tree +lookup_property_in_list (tree chain, tree property) +{ + tree x; + for (x = CLASS_PROPERTY_DECL (chain); x; x = TREE_CHAIN (x)) + if (PROPERTY_NAME (x) == property) + return x; + return NULL_TREE; +} + +/* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */ + +static tree lookup_property_in_protocol_list (tree rproto_list, tree property) +{ + tree rproto, x; + for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) + { + tree p = TREE_VALUE (rproto); + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + { + if ((x = lookup_property_in_list (p, property))) + return x; + if (PROTOCOL_LIST (p)) + return lookup_property_in_protocol_list (PROTOCOL_LIST (p), property); + } + else + { + ; /* An identifier...if we could not find a protocol. */ + } + } + return NULL_TREE; +} + +/* This routine looks up the PROPERTY in current INTERFACE, its categories and up the + chain of interface hierarchy. +*/ +static tree +lookup_property (tree interface_type, tree property) +{ + tree inter = interface_type; + while (inter) + { + tree x, category; + if ((x = lookup_property_in_list (inter, property))) + return x; + /* Failing that, look for the property in each category of the class. */ + category = inter; + while ((category = CLASS_CATEGORY_LIST (category))) + if ((x = lookup_property_in_list (category, property))) + return x; + + /* Failing to find in categories, look for property in protocol list. */ + if (CLASS_PROTOCOL_LIST (inter) + && (x = lookup_property_in_protocol_list ( + CLASS_PROTOCOL_LIST (inter), property))) + return x; + + /* Failing that, climb up the inheritance hierarchy. */ + inter = lookup_interface (CLASS_SUPER_NAME (inter)); + } + return inter; +} + +/* This routine recognizes a dot-notation for a propery reference and generates a call to + the getter function for this property. In all other cases, it returns a NULL_TREE. +*/ + +tree +objc_build_getter_call (tree receiver, tree component) +{ + tree x = NULL_TREE; + tree rtype; + + if (receiver == NULL_TREE + || receiver == error_mark_node + || (rtype = TREE_TYPE (receiver)) == NULL_TREE) + return NULL_TREE; + + if (component == NULL_TREE + || component == error_mark_node + || TREE_CODE (component) != IDENTIFIER_NODE) + return NULL_TREE; + + if (objc_is_id (rtype)) + { + tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype)) + ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype)) + : NULL_TREE); + if (rprotos) + x = lookup_property_in_protocol_list (rprotos, component); + } + else + { + tree basetype = TYPE_MAIN_VARIANT (rtype); + + if (basetype != NULL_TREE && TREE_CODE (basetype) == POINTER_TYPE) + basetype = TREE_TYPE (basetype); + else + return NULL_TREE; + + while (basetype != NULL_TREE + && TREE_CODE (basetype) == RECORD_TYPE + && OBJC_TYPE_NAME (basetype) + && TREE_CODE (OBJC_TYPE_NAME (basetype)) == TYPE_DECL + && DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (basetype))) + basetype = DECL_ORIGINAL_TYPE (OBJC_TYPE_NAME (basetype)); + + if (basetype != NULL_TREE && TYPED_OBJECT (basetype)) + { + tree interface_type = TYPE_OBJC_INTERFACE (basetype); + if (!interface_type) + return NULL_TREE; + x = lookup_property (interface_type, component); + } + } + + if (x) + { + tree call_exp, getter; + /* Get the getter name. */ + gcc_assert (PROPERTY_NAME (x)); + getter = objc_finish_message_expr (receiver, PROPERTY_NAME (x), + NULL_TREE); + call_exp = getter; +#ifdef OBJCPLUS + /* In C++, a getter which returns an aggregate value results in a + target_expr which initializes a temporary to the call expression. */ + if (TREE_CODE (getter) == TARGET_EXPR) + { + gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter))); + gcc_assert (TREE_CODE (TREE_OPERAND (getter,0)) == VAR_DECL); + call_exp = TREE_OPERAND (getter,1); + } +#endif + gcc_assert (TREE_CODE (call_exp) == CALL_EXPR); + + CALL_EXPR_OBJC_PROPERTY_GETTER (call_exp) = 1; + return getter; + } + return NULL_TREE; +} + +/* This routine builds a call to property's 'setter' function. RECEIVER is the + receiving object for 'setter'. PROPERTY_IDENT is name of the property and + RHS is the argument passed to the 'setter' function. */ + +static tree +objc_setter_func_call (tree receiver, tree property_ident, tree rhs) +{ + tree setter_argument = build_tree_list (NULL_TREE, rhs); + char *setter_name = objc_build_property_setter_name (property_ident, true); + tree setter; + in_objc_property_setter_name_context = true; + setter = objc_finish_message_expr (receiver, get_identifier (setter_name), + setter_argument); + in_objc_property_setter_name_context = false; + return setter; +} + +/* Find the selector identifier from a reference. A somewhat tortuous way of + obtaining the information to allow a setter to be written, given an + existing getter. */ + +static tree +get_selector_from_reference (tree selref) +{ + tree chain; + + if (flag_next_runtime) + { + /* Run through the selectors until we find the one we're looking for. */ + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + if (TREE_PURPOSE (chain) == selref) + return TREE_VALUE (chain); + } + else + { + /* To find our way back to the selector for the GNU runtime is harder + work, we need to decompose the representation of SELECTOR_TABLE[n] + to find 'n'. This representation is in several forms. */ + if (TREE_CODE (selref) == POINTER_PLUS_EXPR) + { + /* We need the element size to decode the array offset expression + into an index. */ + unsigned size = (unsigned) TREE_INT_CST_LOW + (TYPE_SIZE_UNIT + (TREE_TYPE + (TREE_TYPE + (TREE_OPERAND + (TREE_OPERAND + (TREE_OPERAND (selref, 0), 0), 0))))); + unsigned index = + (unsigned) TREE_INT_CST_LOW (TREE_OPERAND (selref, 1)) + / size; + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + if (!index--) + return TREE_VALUE (chain); + } + else if (TREE_CODE (selref) == NOP_EXPR) + { + /* Either we have a base an index, or we have just a base (when the + index is 0. */ + if (TREE_CODE (TREE_OPERAND (selref, 0)) == ADDR_EXPR + && TREE_CODE + (TREE_OPERAND + (TREE_OPERAND (selref, 0), 0)) == ARRAY_REF) + { + /* The Nth. */ + unsigned index = (unsigned) TREE_INT_CST_LOW + (TREE_OPERAND + (TREE_OPERAND + (TREE_OPERAND (selref, 0), 0), 1)); + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + if (!index--) + return TREE_VALUE (chain); + } + else + return TREE_VALUE (sel_ref_chain); + } /* Else we don't know how to figure this out - which will produce a + parse error - saying that the LHS is not writeable. */ + } + return NULL_TREE; +} + +/* This routine converts a previously synthesized 'getter' function call for + a property and converts it to a 'setter' function call for the same + property. */ + +tree +objc_build_setter_call (tree lhs, tree rhs) +{ + if (lhs + && TREE_CODE (lhs) == CALL_EXPR + && CALL_EXPR_OBJC_PROPERTY_GETTER (lhs)) + { + tree selector; + /* Get the Object. */ + tree receiver = TREE_OPERAND (lhs, 3); + /* Get the selector reference. */ + tree selector_reference = TREE_OPERAND (lhs, 4); + gcc_assert (receiver && selector_reference); + /* The style of the selector reference is different for GNU & NeXT. */ + selector = get_selector_from_reference (selector_reference); + if (selector) + return objc_setter_func_call (receiver, selector, rhs); + } + return NULL_TREE; +} + +/* This routine checks to see if ID is a property name. If so, it + returns property declaration. */ + +static tree +is_property (tree klass, tree id) +{ + tree x; + + for (x = CLASS_PROPERTY_DECL (klass); x; x = TREE_CHAIN (x)) + if (PROPERTY_NAME (x) == id) + return x; + return NULL_TREE; +} + +/* This routine returns call to property's getter when a property is + used stand-alone (without self. notation). */ + +static tree +build_property_reference (tree property, tree id) +{ + tree getter; + if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL) + { + error ("property %qs accessed in class method", + IDENTIFIER_POINTER (id)); + return error_mark_node; + } + + getter = objc_finish_message_expr (self_decl, PROPERTY_NAME (property), NULL_TREE); + CALL_EXPR_OBJC_PROPERTY_GETTER (getter) = 1; + return getter; +} + void objc_set_method_type (enum tree_code type) { @@ -6511,9 +6986,11 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) || CONVERT_EXPR_P (rtype) || TREE_CODE (rtype) == COMPONENT_REF) rtype = TREE_OPERAND (rtype, 0); + self = (rtype == self_decl); super = (rtype == UOBJC_SUPER_decl); rtype = TREE_TYPE (receiver); + have_cast = (TREE_CODE (receiver) == NOP_EXPR || (TREE_CODE (receiver) == COMPOUND_EXPR && !IS_SUPER (rtype))); @@ -6663,7 +7140,9 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE); } - if (!method_prototype) + if (!method_prototype && in_objc_property_setter_name_context) + error ("readonly property can not be set"); + else if (!method_prototype) { static bool warn_missing_methods = false; @@ -7968,6 +8447,309 @@ continue_class (tree klass) return error_mark_node; } +/* This routine builds a property ivar name. */ + +static char * +objc_build_property_ivar_name (tree property_decl) +{ + static char string[BUFSIZE]; + sprintf (string, "_%s", IDENTIFIER_POINTER (PROPERTY_NAME (property_decl))); + return string; +} + +/* This routine builds name of the setter synthesized function. */ + +static char * +objc_build_property_setter_name (tree ident, bool delimit_colon) +{ + static char string[BUFSIZE]; + if (delimit_colon) + sprintf (string, "set%s:", IDENTIFIER_POINTER (ident)); + else + sprintf (string, "set%s", IDENTIFIER_POINTER (ident)); + string[3] = TOUPPER (string[3]); + return string; +} + +/* This routine does all the work for generating data and code per each + property declared in current implementation. */ + +static void +objc_gen_one_property_datum (tree klass, tree property, tree class_methods, bool *ivar_added) +{ + tree mth; + + /* If getter, check that it is already declared in user code. */ + if (PROPERTY_GETTER_NAME (property)) + { + mth = lookup_method (CLASS_NST_METHODS (class_methods), + PROPERTY_GETTER_NAME (property)); + if (!mth) + error ("property getter %qs not declared in class %qs", + IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property)), + IDENTIFIER_POINTER (CLASS_NAME (class_methods))); + } + /* If setter, check that it is already declared in user code. */ + if (PROPERTY_SETTER_NAME (property)) + { + mth = lookup_method (CLASS_NST_METHODS (class_methods), + PROPERTY_SETTER_NAME (property)); + if (!mth) + error ("property setter %qs not declared in class %qs", + IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property)), + IDENTIFIER_POINTER (CLASS_NAME (class_methods))); + } + /* If ivar attribute specified, check that it is already declared. */ + if (PROPERTY_IVAR_NAME (property)) + { + if (!is_ivar (CLASS_IVARS (klass), + PROPERTY_IVAR_NAME (property))) + error ("ivar %qs in property declaration must be an existing ivar", + IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property))); + } + else if (!PROPERTY_GETTER_NAME (property) + || (PROPERTY_READONLY (property) == boolean_false_node + && !PROPERTY_SETTER_NAME (property))) + { + /* Setter and/or getter must be synthesize and there was no user-specified + ivar. Must create an ivar and add to to current class's ivar list. */ + tree record = CLASS_STATIC_TEMPLATE (klass); + tree type = TREE_TYPE (property); + tree field_decl, field; + field_decl = create_field_decl (type, + objc_build_property_ivar_name (property)); + DECL_CONTEXT (field_decl) = record; + (void) add_instance_variable (klass, + 1, field_decl); + /* Unfortunately, CLASS_IVARS is completed when interface is completed. + Must add the new ivar by hand to its list here. */ + + CLASS_IVARS (klass) = + chainon (CLASS_IVARS (klass), + copy_node (field_decl)); + gcc_assert (record); + /* Must also add this ivar to the end of list of fields for this class. */ + field = TYPE_FIELDS (record); + if (field && field != CLASS_IVARS (klass)) + /* class has a hidden field, attach ivar list after the hiddent field. */ + TREE_CHAIN (field) = CLASS_IVARS (klass); + else + TYPE_FIELDS (record) = CLASS_IVARS (klass); + *ivar_added = true; + } +} + +/* This routine processes an existing getter or setter attribute. + It aliases internal property getter or setter to the user implemented + getter or setter. +*/ + +static void +objc_process_getter_setter (tree klass, tree property, bool getter) +{ + tree prop_mth_decl; + tree prop_getter_mth_decl; + tree name_ident; + + if (getter) + /* getter name is same as property name. */ + name_ident = PROPERTY_NAME (property); + else + /* Must synthesize setter name from property name. */ + name_ident = get_identifier (objc_build_property_setter_name ( + PROPERTY_NAME (property), true)); + + /* Find declaration of instance method for the property in its class. */ + prop_mth_decl = lookup_method (CLASS_NST_METHODS (klass), name_ident); + + if (!prop_mth_decl) + return; + + prop_getter_mth_decl = lookup_method (CLASS_NST_METHODS (objc_implementation_context), + getter ? PROPERTY_GETTER_NAME (property) + : PROPERTY_SETTER_NAME (property)); + + if (!prop_getter_mth_decl) + return; + + if (!match_proto_with_proto (prop_getter_mth_decl, prop_mth_decl, 1)) + { + error ("User %s %qs does not match property %qs type", + getter ? "getter" : "setter", + IDENTIFIER_POINTER (DECL_NAME (prop_getter_mth_decl)), + IDENTIFIER_POINTER (PROPERTY_NAME (property))); + return; + } + /* We alias internal property getter to the user implemented getter by copying relevant + entries from user's implementation to the internal one. */ + prop_mth_decl = copy_node (prop_mth_decl); + METHOD_ENCODING (prop_mth_decl) = METHOD_ENCODING (prop_getter_mth_decl); + METHOD_DEFINITION (prop_mth_decl) = METHOD_DEFINITION (prop_getter_mth_decl); + objc_add_method (objc_implementation_context, prop_mth_decl, 0, 0); +} + +/* This routine synthesizes a 'getter' method. */ + +static void +objc_synthesize_getter (tree klass, tree class_method, tree property) +{ + tree fn, decl; + tree body; + tree ret_val; + tree ivar_ident; + + /* If user has implemented a getter with same name then do nothing. */ + if (lookup_method (CLASS_NST_METHODS (objc_implementation_context), + PROPERTY_NAME (property))) + return; + + /* Find declaration of the property in the interface. There must be one. */ + decl = lookup_method (CLASS_NST_METHODS (class_method), + PROPERTY_NAME (property)); + + /* If one not declared in the interface, this condition has already been reported + as user error (because property was not declared in the interface). */ + if (!decl) + return; + + objc_inherit_code = INSTANCE_METHOD_DECL; + /* For now no attributes. */ + objc_start_method_definition (copy_node (decl), NULL_TREE); + + body = c_begin_compound_stmt (true); + /* return self->_property_name; */ + /* If user specified an ivar, use it in generation of the getter. */ + ivar_ident = PROPERTY_IVAR_NAME (property) + ? PROPERTY_IVAR_NAME (property) + : get_identifier (objc_build_property_ivar_name (property)); + + /* objc_ivar_chain might not be up to date in the case that property 'ivar' + is added *after* user ivar is parsed and objc_continue_implementation + has already been called. */ + objc_ivar_chain = CLASS_IVARS (klass); + ret_val = objc_lookup_ivar (NULL_TREE, ivar_ident); + /* If ivar attribute is not a user declared attribute, this condition has + already been repored as error. */ + gcc_assert (ret_val || PROPERTY_IVAR_NAME (property)); + + if (ret_val) + { +#ifdef OBJCPLUS + finish_return_stmt (ret_val); +#else + (void)c_finish_return (input_location, ret_val, NULL); +#endif + } + add_stmt (c_end_compound_stmt (input_location, body, true)); + fn = current_function_decl; +#ifdef OBJCPLUS + finish_function (); +#endif + objc_finish_method_definition (fn); +} + +/* This routine synthesizes a 'setter' method. */ + +static void +objc_synthesize_setter (tree klass, tree class_method, tree property) +{ + tree fn, decl, ivar_ident, lhs, rhs; + tree body; + char *setter_name = objc_build_property_setter_name ( + PROPERTY_NAME (property), true); + tree setter_ident = get_identifier (setter_name); + + /* If user has implemented a setter with same name then do nothing. */ + if (lookup_method (CLASS_NST_METHODS (objc_implementation_context), + setter_ident)) + return; + + /* Find declaration of the property in the interface. There must be one. */ + decl = lookup_method (CLASS_NST_METHODS (class_method), setter_ident); + + /* If one not declared in the inerface, this condition has already been reported + as user error (because property was not declared in the interface. */ + if (!decl) + return; + + objc_inherit_code = INSTANCE_METHOD_DECL; + /* For now, no attributes. */ + objc_start_method_definition (copy_node (decl), NULL_TREE); + + body = c_begin_compound_stmt (true); + /* _property_name = _value; */ + /* If user specified an ivar, use it in generation of the setter. */ + ivar_ident = PROPERTY_IVAR_NAME (property) + ? PROPERTY_IVAR_NAME (property) + : get_identifier (objc_build_property_ivar_name (property)); + + /* objc_ivar_chain might not be up to date in the case that property 'ivar' + is added *after* user ivar is parsed and objc_continue_implementation + has already been called. */ + objc_ivar_chain = CLASS_IVARS (klass); + lhs = objc_lookup_ivar (NULL_TREE, ivar_ident); + /* If ivar attribute is not a user declared attribute, this condition has + already been repored as error. */ + gcc_assert (lhs || PROPERTY_IVAR_NAME (property)); + if (lhs) + { + rhs = lookup_name (get_identifier ("_value")); + gcc_assert (rhs); + /* FIXME: NULL types to get compile. */ + add_stmt (build_modify_expr (input_location, + lhs, NULL_TREE, NOP_EXPR, + input_location, rhs, NULL_TREE)); + } + add_stmt (c_end_compound_stmt (input_location, body, true)); + fn = current_function_decl; +#ifdef OBJCPLUS + finish_function (); +#endif + objc_finish_method_definition (fn); +} + +/* 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 + could be a class or a category depending on whether we are implementing + property of a class or a category. */ + +static void +objc_gen_property_data (tree klass, tree class_methods) +{ + tree x; + bool ivar_added = false; + for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x)) + objc_gen_one_property_datum (klass, x, class_methods, &ivar_added); + + if (ivar_added) + { + tree record = CLASS_STATIC_TEMPLATE (klass); + /* Ugh, must recalculate struct layout since at least one ivar was added. */ + TYPE_SIZE (record) = 0; + layout_type (record); + } + + /* Synthesize all getters for properties. */ + for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x)) + { + /* Property has a getter attribute, no need to synthesize one. */ + if (PROPERTY_GETTER_NAME (x) == NULL_TREE) + objc_synthesize_getter (klass, class_methods, x); + else + objc_process_getter_setter (class_methods, x, true); + + if (PROPERTY_READONLY (x) == boolean_false_node) + { + /* not a readonly property. */ + if (PROPERTY_SETTER_NAME (x) == NULL_TREE) + objc_synthesize_setter (klass, class_methods, x); + else + objc_process_getter_setter (class_methods, x, false); + } + } +} + /* This is called once we see the "@end" in an interface/implementation. */ static void @@ -7977,6 +8759,9 @@ finish_class (tree klass) { /* All code generation is done in finish_objc. */ + /* Generate what needed for property; setters, getters, etc. */ + objc_gen_property_data (implementation_template, implementation_template); + if (implementation_template != objc_implementation_context) { /* Ensure that all method listed in the interface contain bodies. */ @@ -7998,6 +8783,9 @@ finish_class (tree klass) if (category) { + /* Generate what needed for property; setters, getters, etc. */ + objc_gen_property_data (implementation_template, category); + /* Ensure all method listed in the interface contain bodies. */ check_methods (CLASS_CLS_METHODS (category), CLASS_CLS_METHODS (objc_implementation_context), '+'); @@ -8010,6 +8798,60 @@ finish_class (tree klass) CLASS_SUPER_NAME (objc_implementation_context)); } } + else + { + /* Process properties of the class. */ + tree x; + for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x)) + { + tree type = TREE_TYPE (x); + tree prop_name = PROPERTY_NAME (x); + /* Build an instance method declaration: - (type) prop_name; */ + if (PROPERTY_GETTER_NAME (x) == NULL_TREE) + { + /* No getter attribute specified. Generate an instance method for the + getter. */ + tree rettype = build_tree_list (NULL_TREE, type); + tree getter_decl = build_method_decl (INSTANCE_METHOD_DECL, + rettype, prop_name, + NULL_TREE, false); + objc_add_method (objc_interface_context, getter_decl, false, false); + METHOD_PROPERTY_CONTEXT (getter_decl) = x; + } + else + warning (0, "getter = %qs may not be specified in an interface", + IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (x))); + + /* Build an instance method declaration: - (void) setName: (type)value; */ + if (PROPERTY_SETTER_NAME (x) == NULL_TREE + && PROPERTY_READONLY (x) == boolean_false_node) + { + /* Declare a setter instance method in the interface. */ + tree key_name, arg_type, arg_name; + tree setter_decl, selector; + tree ret_type = build_tree_list (NULL_TREE, void_type_node); + /* setter name. */ + key_name = get_identifier (objc_build_property_setter_name ( + PROPERTY_NAME (x), false)); + arg_type = build_tree_list (NULL_TREE, type); + arg_name = get_identifier ("_value"); + /* For now, no attributes. */ + selector = objc_build_keyword_decl (key_name, arg_type, arg_name, NULL); + setter_decl = build_method_decl (INSTANCE_METHOD_DECL, + ret_type, selector, + build_tree_list (NULL_TREE, NULL_TREE), + false); + objc_add_method (objc_interface_context, setter_decl, false, false); + METHOD_PROPERTY_CONTEXT (setter_decl) = x; + } + else if (PROPERTY_SETTER_NAME (x)) + warning (0, "setter = %qs may not be specified in an interface", + IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x))); + if (PROPERTY_IVAR_NAME (x)) + warning (0, "ivar = %qs attribute may not be specified in an interface", + IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (x))); + } + } } static tree @@ -8988,13 +9830,19 @@ objc_types_share_size_and_alignment (tree type1, tree type2) static int comp_proto_with_proto (tree proto1, tree proto2, int strict) { - tree type1, type2; - /* The following test is needed in case there are hashing collisions. */ if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2)) return 0; + return match_proto_with_proto (proto1, proto2, strict); +} + +static int +match_proto_with_proto (tree proto1, tree proto2, int strict) +{ + tree type1, type2; + /* Compare return types. */ type1 = TREE_VALUE (TREE_TYPE (proto1)); type2 = TREE_VALUE (TREE_TYPE (proto2)); @@ -9970,11 +10818,11 @@ generate_objc_image_info (void) /* Look up ID as an instance variable. OTHER contains the result of the C or C++ lookup, which we may want to use instead. */ - +/* Also handle use of property as setter/getter. */ tree objc_lookup_ivar (tree other, tree id) { - tree ivar; + tree ivar, property; /* If we are not inside of an ObjC method, ivar lookup makes no sense. */ if (!objc_method_context) @@ -9990,11 +10838,18 @@ objc_lookup_ivar (tree other, tree id) && other && other != error_mark_node) return other; - /* Look up the ivar, but do not use it if it is not accessible. */ - ivar = is_ivar (objc_ivar_chain, id); + property = NULL_TREE; + if (objc_implementation_context) + property = is_property (objc_implementation_context, id); - if (!ivar || is_private (ivar)) - return other; + if (!property) + { + /* Look up the ivar, but do not use it if it is not accessible. */ + ivar = is_ivar (objc_ivar_chain, id); + + if (!ivar || is_private (ivar)) + return other; + } /* In an instance method, a local variable (or parameter) may hide the instance variable. */ @@ -10006,12 +10861,17 @@ objc_lookup_ivar (tree other, tree id) && !DECL_FILE_SCOPE_P (other)) #endif { - warning (0, "local declaration of %qE hides instance variable", - id); + if (property) + warning (0, "local declaration of %qE hides property", id); + else + warning (0, "local declaration of %qE hides instance variable", id); return other; } + if (property) + return build_property_reference (property, id); + /* At this point, we are either in an instance method with no obscuring local definitions, or in a class method with no alternate definitions at all. */ diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index f7a0755..1dd777c 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -37,8 +37,8 @@ tree objc_eh_personality (void); /* Objective-C structures */ -#define CLASS_LANG_SLOT_ELTS 5 -#define PROTOCOL_LANG_SLOT_ELTS 4 +#define CLASS_LANG_SLOT_ELTS 7 +#define PROTOCOL_LANG_SLOT_ELTS 7 #define OBJC_INFO_SLOT_ELTS 2 /* KEYWORD_DECL */ @@ -53,6 +53,14 @@ tree objc_eh_personality (void); #define METHOD_DEFINITION(DECL) ((DECL)->decl_common.initial) #define METHOD_ENCODING(DECL) ((DECL)->decl_minimal.context) #define METHOD_TYPE_ATTRIBUTES(DECL) ((DECL)->decl_common.abstract_origin) +#define METHOD_PROPERTY_CONTEXT(DECL) ((DECL)->decl_common.size_unit) + +#define PROPERTY_NAME(DECL) ((DECL)->decl_minimal.name) +#define PROPERTY_GETTER_NAME(DECL) ((DECL)->decl_non_common.arguments) +#define PROPERTY_SETTER_NAME(DECL) ((DECL)->decl_non_common.result) +#define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial) +#define PROPERTY_READONLY(DECL) ((DECL)->decl_minimal.context) +#define PROPERTY_COPIES(DECL) ((DECL)->decl_common.size_unit) /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE, @@ -66,6 +74,8 @@ tree objc_eh_personality (void); #define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2) #define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3) #define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 4) +#define TOTAL_CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 5) + #define PROTOCOL_NAME(CLASS) ((CLASS)->type.name) #define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0) #define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval) @@ -75,6 +85,11 @@ tree objc_eh_personality (void); #define PROTOCOL_OPTIONAL_CLS_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2) #define PROTOCOL_OPTIONAL_NST_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3) +/* For CATEGORY_INTERFACE_TYPE, CLASS_INTERFACE_TYPE or PROTOCOL_INTERFACE_TYPE */ +#define CLASS_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6) +/* For CLASS_IMPLEMENTATION_TYPE or CATEGORY_IMPLEMENTATION_TYPE. */ +#define IMPL_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6) + /* ObjC-specific information pertaining to RECORD_TYPEs are stored in the LANG_SPECIFIC structures, which may itself need allocating first. */ diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c index fa74964..2469845 100644 --- a/gcc/objc/objc-lang.c +++ b/gcc/objc/objc-lang.c @@ -69,22 +69,27 @@ objc_init_ts (void) tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1; } void diff --git a/gcc/objc/objc-tree.def b/gcc/objc/objc-tree.def index a3e40db..b567347 100644 --- a/gcc/objc/objc-tree.def +++ b/gcc/objc/objc-tree.def @@ -34,6 +34,7 @@ DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", tcc_type, 0) DEFTREECODE (KEYWORD_DECL, "keyword_decl", tcc_declaration, 0) DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", tcc_declaration, 0) DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", tcc_declaration, 0) +DEFTREECODE (PROPERTY_DECL, "property_decl", tcc_declaration, 0) /* Objective-C expressions. */ DEFTREECODE (MESSAGE_SEND_EXPR, "message_send_expr", tcc_expression, 3) diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog index 26e3c7a..c60766e 100644 --- a/gcc/objcp/ChangeLog +++ b/gcc/objcp/ChangeLog @@ -1,3 +1,11 @@ +2010-10-14 Iain Sandoe <iains@gcc.gnu.org> + + merge from FSF apple 'trunk' branch. + 2006 Fariborz Jahanian <fjahanian@apple.com> + + Radars 4436866, 4505126, 4506903, 4517826 + * objcp-lang.c (objcxx_init_ts): Update for property_decl. + 2010-10-13 Richard Henderson <rth@redhat.com> * objcp-lang.c (objcxx_eh_personality): Update call to diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c index 6a45404..d03e754 100644 --- a/gcc/objcp/objcp-lang.c +++ b/gcc/objcp/objcp-lang.c @@ -100,22 +100,27 @@ objcxx_init_ts (void) tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1; tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1; tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1; tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1; /* C++ decls */ tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1; |