aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iains@gcc.gnu.org>2010-10-14 20:09:41 +0000
committerIain Sandoe <iains@gcc.gnu.org>2010-10-14 20:09:41 +0000
commit668ea4b1106d1a28e07ed653874192696840829c (patch)
tree2460cc4b29d1b167cadadbf17f50074e1a75ef92
parente05eee4908da6139ecdfe1be68af5b58418ceedf (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/c-family/ChangeLog17
-rw-r--r--gcc/c-family/c-common.c7
-rw-r--r--gcc/c-family/c-common.h29
-rw-r--r--gcc/c-family/stub-objc.c24
-rw-r--r--gcc/c-parser.c168
-rw-r--r--gcc/c-typeck.c16
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/parser.c150
-rw-r--r--gcc/cp/typeck.c19
-rw-r--r--gcc/objc/ChangeLog45
-rw-r--r--gcc/objc/objc-act.c882
-rw-r--r--gcc/objc/objc-act.h19
-rw-r--r--gcc/objc/objc-lang.c5
-rw-r--r--gcc/objc/objc-tree.def1
-rw-r--r--gcc/objcp/ChangeLog8
-rw-r--r--gcc/objcp/objcp-lang.c5
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;