summaryrefslogtreecommitdiff
path: root/gcc/objc
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 /gcc/objc
parente05eee4908da6139ecdfe1be68af5b58418ceedf (diff)
downloadgcc-668ea4b1106d1a28e07ed653874192696840829c.tar.gz
add @property to ObjC*
merge from FSF apple 'trunk' branch. 2006 Fariborz Jahanian <fjahanian@apple.com> Radars 4436866, 4505126, 4506903, 4517826 gcc/c-family: * c-common.c (c_common_resword): Define @property and its attributes. * c-common.h: Define property attribute enum entries. (OBJC_IS_PATTR_KEYWORD): New. (objc_property_attribute_kind): New enum. Declare objc_set_property_attr (), objc_add_property_variable (), objc_build_getter_call () and objc_build_setter_call (). * stub-objc.c (objc_set_property_attr): New stub. (objc_add_property_variable): Likewise. (objc_build_getter_call): Likewise. (objc_build_setter_call) Likewise. gcc: * c-parser.c (c_parser, objc_property_attr_context) New flag. (c_lex_one_token): Handle property attributes. (c_parser_external_declaration): Handle @property. (c_parser_declaration_or_fndef): Warn on invalid attributes before @alias, @class, @end and @property objc keywords. (c_parser_objc_methodprotolist): Handle @property. (c_parser_objc_property_attrlist): New. (c_parser_objc_at_property): New. * c-typeck.c (build_component_ref): Handle CLASS.property syntax. (build_modify_expr): Likewise. gcc/cp: * typeck.c (finish_class_member_access_expr): Handle CLASS.property syntax. (cp_build_modify_expr): Likewise. * parser.c (cp_parser_objc_method_prototype_list): Handle @property. (cp_parser_objc_method_definition_list): Likewise. (cp_parser_objc_property_decl): New. (cp_parser_objc_property_attrlist): New. (cp_parser_objc_at_property): New. gcc/objc: * objc-act.c (CALL_EXPR_OBJC_PROPERTY_GETTER): New. property_readonly, property_getter, property_setter, property_ivar, property_copies, in_objc_property_setter_name_context: New vars. (objc_set_property_attr): New. (objc_add_property_variable): New. (lookup_property_in_list): New. (lookup_property): New. (objc_build_getter_call): New. (objc_setter_func_call): New. (get_selector_from_reference): New. (objc_build_setter_call): New. (is_property): New. (build_property_reference): New. (objc_finish_message_expr): Detect readonly property and warn. (objc_build_property_ivar_name): New. (objc_build_property_setter_name): New. (objc_gen_one_property_datum): New. (objc_process_getter_setter): New. (objc_synthesize_getter): New. (objc_synthesize_setter): New. (objc_gen_property_data): New. (finish_class): Generate property data. (comp_proto_with_proto): Separated from ... (match_proto_with_proto): ... New. (objc_lookup_ivar): Handle properties. * objc-tree.def (PROPERTY_DECL): New tree code. * objc-act.h: CLASS_LANG_SLOT_ELTS, PROTOCOL_LANG_SLOT_ELTS update size. (METHOD_PROPERTY_CONTEXT): New. (PROPERTY_NAME): New. (PROPERTY_GETTER_NAME): New. (PROPERTY_SETTER_NAME): New. (PROPERTY_IVAR_NAME): New. (PROPERTY_READONLY): New. (PROPERTY_COPIES): New. (TOTAL_CLASS_RAW_IVARS): New. (CLASS_PROPERTY_DECL): New. (IMPL_PROPERTY_DECL): New. * objc-lang.c (objc_init_ts): Update fields for property_decl. gcc/objcp: * objcp-lang.c (objcxx_init_ts): Update for property_decl. From-SVN: r165479
Diffstat (limited to 'gcc/objc')
-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
5 files changed, 939 insertions, 13 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 81a872d1ff8..1a51c1444ff 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 edde784c422..88f5d6c5a48 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 f7a075569d2..1dd777c912f 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 fa7496475fb..2469845b2c3 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 a3e40db2c3a..b56734789d8 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)