@@ -556,10 +556,16 @@ const struct c_common_resword c_common_r
{ "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 },
+ { "assign", RID_ASSIGN, D_OBJC },
+ { "copy", RID_COPY, D_OBJC },
{ "getter", RID_GETTER, D_OBJC },
+ { "nonatomic", RID_NONATOMIC, D_OBJC },
+ { "readonly", RID_READONLY, D_OBJC },
+ { "readwrite", RID_READWRITE, D_OBJC },
+ { "retain", RID_RETAIN, D_OBJC },
{ "setter", RID_SETTER, D_OBJC },
+ /* The following two will be removed once @synthesize is fully implemented. */
+ { "copies", RID_COPIES, D_OBJC },
{ "ivar", RID_IVAR, D_OBJC },
};
@@ -82,7 +82,13 @@ enum rid
/* 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,
+ RID_GETTER, RID_SETTER,
+ RID_READONLY, RID_READWRITE,
+ RID_ASSIGN, RID_RETAIN, RID_COPY,
+ /* RID_IVAR and RID_COPIES will be removed once @synthesize is
+ completed. */
+ RID_COPIES, RID_IVAR,
+ RID_NONATOMIC,
/* C (reserved and imaginary types not implemented, so any use is a
syntax error) */
@@ -187,8 +193,8 @@ enum rid
RID_LAST_AT = RID_AT_IMPLEMENTATION,
RID_FIRST_PQ = RID_IN,
RID_LAST_PQ = RID_ONEWAY,
- RID_FIRST_PATTR = RID_READONLY,
- RID_LAST_PATTR = RID_IVAR
+ RID_FIRST_PATTR = RID_GETTER,
+ RID_LAST_PATTR = RID_NONATOMIC
};
#define OBJC_IS_AT_KEYWORD(rid) \
@@ -431,16 +437,6 @@ 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;
-
/* ObjC ivar visibility types. */
typedef enum objc_ivar_visibility_kind {
OBJC_IVAR_VIS_PROTECTED = 0,
@@ -1040,10 +1036,10 @@ extern tree objc_generate_static_init_ca
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_declaration (location_t, tree);
+extern void objc_add_property_declaration (location_t, tree, bool, bool, bool,
+ bool, bool, bool, tree, tree,
+ bool, tree);
extern tree objc_build_getter_call (tree, tree);
extern tree objc_build_setter_call (tree, tree);
extern void objc_add_synthesize_declaration (location_t, tree);
@@ -1,5 +1,19 @@
2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+ * c-common.h (enum rid): Added RID_READWRITE, RID_ASSIGN,
+ RID_RETAIN, RID_COPY and RID_NONATOMIC. Updated RID_FIRST_PATTR
+ and RID_LAST_PATTR.
+ (objc_add_property_declaration): Added additional arguments.
+ (objc_property_attribute_kind): Removed.
+ (objc_set_property_attr): Removed.
+ * c-common.c (c_common_reswords): Added readwrite, assign, retain,
+ copy and nonatomic.
+ * stub-objc.c (objc_add_property_declaration): Added additional
+ arguments.
+ (objc_set_property_attr): Removed.
+
+2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+
* c-common.h (objc_add_property_variable): Renamed to
objc_add_property_declaration. Added location argument.
* stub-objc.c (objc_add_property_variable): Same change.
@@ -324,14 +324,18 @@ objc_get_class_ivars (tree ARG_UNUSED (n
}
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_declaration (location_t ARG_UNUSED (loc), tree ARG_UNUSED (prop))
+objc_add_property_declaration (location_t ARG_UNUSED (location),
+ tree ARG_UNUSED (decl),
+ bool ARG_UNUSED (parsed_property_readonly),
+ bool ARG_UNUSED (parsed_property_readwrite),
+ bool ARG_UNUSED (parsed_property_assign),
+ bool ARG_UNUSED (parsed_property_retain),
+ bool ARG_UNUSED (parsed_property_copy),
+ bool ARG_UNUSED (parsed_property_nonatomic),
+ tree ARG_UNUSED (parsed_property_getter_ident),
+ tree ARG_UNUSED (parsed_property_setter_ident),
+ bool ARG_UNUSED (parsed_property_copies),
+ tree ARG_UNUSED (parsed_property_ivar_ident))
{
}
@@ -1,5 +1,16 @@
2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+ * c-parser.c (c_parser_objc_at_property_declaration): Recognize
+ RID_ASSIGN, RID_COPY, RID_RETAIN, RID_READWRITE and RID_NONATOMIC.
+ Do not use objc_set_property_attr, but use local variables
+ instead. Detect repeated usage of setter, getter and ivar
+ attributes. Improved error processing when a setter name does not
+ end in ':'. Do not check for CPP_CLOSE_PAREN after we determined
+ that the token is a keyword. Updated call to
+ objc_add_property_declaration.
+
+2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+
* c-parser.c (c_parser_objc_at_property): Renamed to
c_parser_objc_at_property_declaration. Updated calls to
objc_add_property_variable, now objc_add_property_declaration.
@@ -1,5 +1,16 @@
2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+ * parser.c (cp_parser_objc_at_property_declaration): Recognize
+ RID_ASSIGN, RID_COPY, RID_RETAIN, RID_READWRITE and RID_NONATOMIC.
+ Do not use objc_set_property_attr, but use local variables
+ instead. Detect repeated usage of setter, getter and ivar
+ attributes. Improved error processing when a setter name does not
+ end in ':'. Do not check for CPP_CLOSE_PAREN after we determined
+ that the token is a keyword. Updated call to
+ objc_add_property_declaration.
+
+2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+
* parser.c (cp_parser_objc_property_decl): Renamed to
cp_parser_objc_struct_declaration. Return the parsed trees
instead of calling objc_add_property_variable directly. Detect
@@ -22648,23 +22648,41 @@ cp_parser_objc_struct_declaration (cp_pa
@property int a, b, c;
PS: This function is identical to
- c_parser_objc_at_property_declaration for C. Keep them in sync.
-
- WORK IN PROGRESS: At the moment, the list of attributes that are
- parsed is different from the above list. It will be updated to use
- the above list at the same time as @synthesize is implemented. */
+ c_parser_objc_at_property_declaration for C. Keep them in sync. */
static void
cp_parser_objc_at_property_declaration (cp_parser *parser)
{
+ /* The following variables hold the attributes of the properties as
+ parsed. They are 'false' or 'NULL_TREE' if the attribute was not
+ seen. When we see an attribute, we set them to 'true' (if they
+ are boolean properties) or to the identifier (if they have an
+ argument, ie, for getter and setter). Note that here we only
+ parse the list of attributes, check the syntax and accumulate the
+ attributes that we find. objc_add_property_declaration() will
+ then process the information. */
+ bool property_assign = false;
+ bool property_copy = false;
+ tree property_getter_ident = NULL_TREE;
+ bool property_nonatomic = false;
+ bool property_readonly = false;
+ bool property_readwrite = false;
+ bool property_retain = false;
+ tree property_setter_ident = NULL_TREE;
+ /* The following two will be removed once @synthesize is
+ implemented. */
+ bool property_copies = false;
+ tree property_ivar_ident = NULL_TREE;
+
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three). */
tree properties;
location_t loc;
+
loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
- /* Initialize attributes to an empty list. */
- objc_set_property_attr (loc, OBJC_PATTR_INIT, NULL_TREE);
-
/* Parse the optional attribute list... */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
@@ -22683,18 +22701,20 @@ cp_parser_objc_at_property_declaration (
break;
}
keyword = C_RID_CODE (token->u.value);
+ cp_lexer_consume_token (parser->lexer);
switch (keyword)
{
- tree ident;
- objc_property_attribute_kind pkind;
- case RID_READONLY:
- cp_lexer_consume_token (parser->lexer);
- objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE);
- break;
+ case RID_ASSIGN: property_assign = true; break;
+ case RID_COPIES: property_copies = true; break;
+ case RID_COPY: property_copy = true; break;
+ case RID_NONATOMIC: property_nonatomic = true; break;
+ case RID_READONLY: property_readonly = true; break;
+ case RID_READWRITE: property_readwrite = true; break;
+ case RID_RETAIN: property_retain = true; break;
+
case RID_GETTER:
case RID_SETTER:
case RID_IVAR:
- cp_lexer_consume_token (parser->lexer);
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
cp_parser_error (parser,
@@ -22709,39 +22729,37 @@ cp_parser_objc_at_property_declaration (
syntax_error = true;
break;
}
- ident = cp_lexer_peek_token (parser->lexer)->u.value;
- cp_lexer_consume_token (parser->lexer);
if (keyword == RID_SETTER)
{
- pkind = OBJC_PATTR_SETTER;
- /* Eat the identifier, and look for the following : */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
- {
- cp_parser_error (parser,
- "setter name must be followed by %<:%>");
- syntax_error = true;
- break;
- }
+ if (property_setter_ident != NULL_TREE)
+ cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+ else
+ property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ cp_parser_error (parser, "setter name must terminate with %<:%>");
+ else
+ cp_lexer_consume_token (parser->lexer);
}
else if (keyword == RID_GETTER)
- pkind = OBJC_PATTR_GETTER;
- else
- pkind = OBJC_PATTR_IVAR;
- objc_set_property_attr (loc, pkind, ident);
- break;
- case RID_COPIES:
- cp_lexer_consume_token (parser->lexer);
- objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE);
- break;
- default:
- if (token->type == CPP_CLOSE_PAREN)
- cp_parser_error (parser, "expected identifier");
- else
{
+ if (property_getter_ident != NULL_TREE)
+ cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+ else
+ property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
- cp_parser_error (parser, "unknown property attribute");
}
+ else /* RID_IVAR, this case will go away. */
+ {
+ if (property_ivar_ident != NULL_TREE)
+ cp_parser_error (parser, "the %<ivar%> attribute may only be specified once");
+ else
+ property_ivar_ident = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ break;
+ default:
+ cp_parser_error (parser, "unknown property attribute");
syntax_error = true;
break;
}
@@ -22785,7 +22803,13 @@ cp_parser_objc_at_property_declaration (
properties = nreverse (properties);
for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties));
+ objc_add_property_declaration (loc, copy_node (properties),
+ property_readonly, property_readwrite,
+ property_assign, property_retain,
+ property_copy, property_nonatomic,
+ property_getter_ident, property_setter_ident,
+ /* The following two will be removed. */
+ property_copies, property_ivar_ident);
}
cp_parser_consume_semicolon_at_end_of_statement (parser);
@@ -7603,24 +7603,42 @@ c_parser_objc_diagnose_bad_element_prefi
@property int a, b, c;
PS: This function is identical to cp_parser_objc_at_propery_declaration
- for C++. Keep them in sync.
-
- WORK IN PROGRESS: At the moment, the list of attributes that are
- parsed is different from the above list. It will be updated to use
- the above list at the same time as @synthesize is implemented. */
+ for C++. Keep them in sync. */
static void
c_parser_objc_at_property_declaration (c_parser *parser)
{
+ /* The following variables hold the attributes of the properties as
+ parsed. They are 'false' or 'NULL_TREE' if the attribute was not
+ seen. When we see an attribute, we set them to 'true' (if they
+ are boolean properties) or to the identifier (if they have an
+ argument, ie, for getter and setter). Note that here we only
+ parse the list of attributes, check the syntax and accumulate the
+ attributes that we find. objc_add_property_declaration() will
+ then process the information. */
+ bool property_assign = false;
+ bool property_copy = false;
+ tree property_getter_ident = NULL_TREE;
+ bool property_nonatomic = false;
+ bool property_readonly = false;
+ bool property_readwrite = false;
+ bool property_retain = false;
+ tree property_setter_ident = NULL_TREE;
+ /* The following two will be removed once @synthesize is
+ implemented. */
+ bool property_copies = false;
+ tree property_ivar_ident = NULL_TREE;
+
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three). */
tree properties;
location_t loc;
+
loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
c_parser_consume_token (parser); /* Eat '@property'. */
- /* Initialize attributes to an empty list. */
- objc_set_property_attr (loc, OBJC_PATTR_INIT, NULL_TREE);
-
/* Parse the optional attribute list... */
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
@@ -7648,18 +7666,20 @@ c_parser_objc_at_property_declaration (c
break;
}
keyword = token->keyword;
+ c_parser_consume_token (parser);
switch (keyword)
{
- tree ident;
- objc_property_attribute_kind pkind;
- case RID_READONLY:
- c_parser_consume_token (parser);
- objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE);
- break;
+ case RID_ASSIGN: property_assign = true; break;
+ case RID_COPIES: property_copies = true; break;
+ case RID_COPY: property_copy = true; break;
+ case RID_NONATOMIC: property_nonatomic = true; break;
+ case RID_READONLY: property_readonly = true; break;
+ case RID_READWRITE: property_readwrite = true; break;
+ case RID_RETAIN: property_retain = true; 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,
@@ -7674,39 +7694,37 @@ c_parser_objc_at_property_declaration (c
syntax_error = true;
break;
}
- ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
if (keyword == RID_SETTER)
{
- pkind = OBJC_PATTR_SETTER;
- /* Eat the identifier, and look for the following : */
- if (c_parser_next_token_is_not (parser, CPP_COLON))
- {
- c_parser_error (parser,
- "setter name must be followed by %<:%>");
- syntax_error = true;
- break;
- }
+ if (property_setter_ident != NULL_TREE)
+ c_parser_error (parser, "the %<setter%> attribute may only be specified once");
+ else
+ property_setter_ident = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_COLON))
+ c_parser_error (parser, "setter name must terminate with %<:%>");
+ else
+ c_parser_consume_token (parser);
}
else if (keyword == RID_GETTER)
- pkind = OBJC_PATTR_GETTER;
- else
- pkind = OBJC_PATTR_IVAR;
- objc_set_property_attr (loc, pkind, ident);
- break;
- case RID_COPIES:
- c_parser_consume_token (parser);
- objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE);
- break;
- default:
- if (token->type == CPP_CLOSE_PAREN)
- c_parser_error (parser, "expected identifier");
- else
{
+ if (property_getter_ident != NULL_TREE)
+ c_parser_error (parser, "the %<getter%> attribute may only be specified once");
+ else
+ property_getter_ident = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ }
+ else /* RID_IVAR, this case will go away. */
+ {
+ if (property_ivar_ident != NULL_TREE)
+ c_parser_error (parser, "the %<ivar%> attribute may only be specified once");
+ else
+ property_ivar_ident = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
- c_parser_error (parser, "unknown property attribute");
}
+ break;
+ default:
+ c_parser_error (parser, "unknown property attribute");
syntax_error = true;
break;
}
@@ -7741,7 +7759,13 @@ c_parser_objc_at_property_declaration (c
properties = nreverse (properties);
for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties));
+ objc_add_property_declaration (loc, copy_node (properties),
+ property_readonly, property_readwrite,
+ property_assign, property_retain,
+ property_copy, property_nonatomic,
+ property_getter_ident, property_setter_ident,
+ /* The following two will be removed. */
+ property_copies, property_ivar_ident);
}
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -1,5 +1,22 @@
2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+ * objc-act.c (objc_add_property_declaration): Added arguments to
+ pass the various property attributes that were parsed with the
+ property declaration. Process arguments to determine the final
+ property attributes and produce error messages as appropriate.
+ Added temporary code to keep the compiler silent about variables
+ set but not used - for new attributes that are only checked but
+ have no effect yet.
+ (property_readonly): Removed.
+ (property_setter): Removed.
+ (property_getter): Removed.
+ (property_ivar): Removed.
+ (property_copies): Removed.
+ (objc_set_property_attr): Removed.
+ * objc-act.h (enum property_assign_semantics): New.
+
+2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+
* objc-act.c (objc_add_property_variable): Renamed to
objc_add_property_declaration. Added location argument. Updated
warnings and errors to use it. Use error, not fatal_error, if a
@@ -406,11 +406,6 @@ 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;
@@ -815,68 +810,93 @@ objc_set_method_opt (bool optional)
}
}
-/* This routine gathers property attribute information from the attribute
- portion of a property declaration. */
-
+/* This routine is called by the parser when a
+ @property... declaration is found. 'decl' is the declaration of
+ the property (type/identifier), and the other arguments represent
+ property attributes that may have been specified in the Objective-C
+ declaration. 'parsed_property_readonly' is 'true' if the attribute
+ 'readonly' was specified, and 'false' if not; similarly for the
+ other bool parameters. 'parsed_property_getter_ident' is NULL_TREE
+ if the attribute 'getter' was not specified, and is the identifier
+ corresponding to the specified getter if it was; similarly for
+ 'parsed_property_setter_ident'. */
void
-objc_set_property_attr (location_t loc, objc_property_attribute_kind attr,
- tree ident)
+objc_add_property_declaration (location_t location, tree decl,
+ bool parsed_property_readonly, bool parsed_property_readwrite,
+ bool parsed_property_assign, bool parsed_property_retain,
+ bool parsed_property_copy, bool parsed_property_nonatomic,
+ tree parsed_property_getter_ident, tree parsed_property_setter_ident,
+ /* The following two will be removed. */
+ bool parsed_property_copies, tree parsed_property_ivar_ident)
{
- static char string[BUFSIZE];
- switch (attr)
+ tree property_decl;
+ tree x;
+ tree interface = NULL_TREE;
+ /* 'property_readonly' is the final readonly/rewrite attribute of
+ the property declaration after all things have been
+ considered. */
+ bool property_readonly = false;
+ enum objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
+ /* The following will be removed once @synthesize is implemented. */
+ bool property_copies = false;
+
+ if (parsed_property_readonly && parsed_property_readwrite)
{
- case OBJC_PATTR_INIT: /* init */
- property_readonly = property_copies = false;
- property_setter = property_getter = property_ivar = NULL_TREE;
- break;
- case OBJC_PATTR_READONLY: /* readonly */
+ error_at (location, "%<readonly%> attribute conflicts with %<readwrite%> attribute");
+ /* In case of conflicting attributes (here and below), after
+ producing an error, we pick one of the attributes and keep
+ going. */
+ property_readonly = false;
+ }
+ else
+ {
+ if (parsed_property_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;
+
+ if (parsed_property_readwrite)
+ property_readonly = false;
}
-}
-/* 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.
-*/
+ if (parsed_property_readonly && parsed_property_setter_ident)
+ {
+ /* Maybe this should be an error ? */
+ warning_at (location, 0, "%<readonly%> attribute conflicts with %<setter%> attribute");
+ parsed_property_readonly = false;
+ }
-void
-objc_add_property_declaration (location_t location, tree decl)
-{
- tree property_decl;
- tree x;
- tree interface = NULL_TREE;
+ if (parsed_property_assign && parsed_property_retain)
+ {
+ error_at (location, "%<assign%> attribute conflicts with %<retain%> attribute");
+ property_assign_semantics = OBJC_PROPERTY_RETAIN;
+ }
+ else if (parsed_property_assign && parsed_property_copy)
+ {
+ error_at (location, "%<assign%> attribute conflicts with %<copy%> attribute");
+ property_assign_semantics = OBJC_PROPERTY_COPY;
+ }
+ else if (parsed_property_retain && parsed_property_copy)
+ {
+ error_at (location, "%<retain%> attribute conflicts with %<copy%> attribute");
+ property_assign_semantics = OBJC_PROPERTY_COPY;
+ }
+ else
+ {
+ if (parsed_property_assign)
+ property_assign_semantics = OBJC_PROPERTY_ASSIGN;
+
+ if (parsed_property_retain)
+ property_assign_semantics = OBJC_PROPERTY_RETAIN;
+
+ if (parsed_property_copy)
+ property_assign_semantics = OBJC_PROPERTY_COPY;
+ }
+
+ /* This will be removed when @synthesize is implemented. */
+ if (parsed_property_copies)
+ property_copies = true;
+ /* This case will be removed when @synthesize is implemented; then
+ @property will only be allowed in an @interface context. */
if (objc_implementation_context)
{
interface = lookup_interface (CLASS_NAME (objc_implementation_context));
@@ -896,19 +916,41 @@ objc_add_property_declaration (location_
}
}
}
+ else if (objc_interface_context)
+ {
+ /* This will be removed when ivar is removed. */
+ if (parsed_property_ivar_ident)
+ {
+ warning_at (location, 0, "the %<ivar%> attribute is ignored in an @interface");
+ parsed_property_ivar_ident = NULL_TREE;
+ }
+ }
else if (!objc_interface_context)
{
error_at (location, "property declaration not in @interface or @implementation context");
return;
}
+ if (parsed_property_setter_ident)
+ {
+ /* The setter should be terminated by ':', but the parser only
+ passes us an identifier without ':'. So, we need to add ':'
+ at the end. */
+ const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
+ size_t length = strlen (parsed_setter);
+ char *final_setter = (char *)alloca (length + 2);
+
+ sprintf (final_setter, "%s:", parsed_setter);
+ parsed_property_setter_ident = get_identifier (final_setter);
+ }
+
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_GETTER_NAME (property_decl) = parsed_property_getter_ident;
+ PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
+ PROPERTY_IVAR_NAME (property_decl) = parsed_property_ivar_ident;
PROPERTY_READONLY (property_decl) = property_readonly
? boolean_true_node
: boolean_false_node;
@@ -916,6 +958,20 @@ objc_add_property_declaration (location_
? boolean_true_node
: boolean_false_node;
+ /* TODO: The following is temporary code that will be removed when
+ property_assign_semantics and property_nonatomic are
+ implemented. */
+ if (objc_implementation_context && objc_interface_context)
+ {
+ /* This branch is impossible but the compiler can't know it. Do
+ something with property_assign_semantics and
+ parsed_property_nonatomic (not implemented yet) to convince
+ the compiler we're using them and prevent it from generating
+ warnings and breaking bootstrap. */
+ PROPERTY_COPIES (property_decl) = property_assign_semantics ? boolean_true_node : boolean_false_node;
+ PROPERTY_READONLY (property_decl) = parsed_property_nonatomic ? boolean_true_node : boolean_false_node;
+ }
+
if (objc_interface_context)
{
/* Doing the property in interface declaration. */
@@ -938,6 +994,8 @@ objc_add_property_declaration (location_
}
else
{
+ /* This case will go away once @syhtensize is implemented. */
+
/* 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))
@@ -964,7 +1022,8 @@ objc_add_property_declaration (location_
if (PROPERTY_READONLY (property_decl) == boolean_true_node &&
PROPERTY_SETTER_NAME (property_decl))
{
- warning_at (location, 0, "a %<readonly%> property cannot have a setter (ignored)");
+ /* This error is already reported up there. */
+ /* warning_at (location, 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. */
@@ -1039,7 +1098,7 @@ lookup_property (tree interface_type, tr
return inter;
}
-/* This routine recognizes a dot-notation for a propery reference and generates a call to
+/* This routine recognizes a dot-notation for a property reference and generates a call to
the getter function for this property. In all other cases, it returns a NULL_TREE.
*/
@@ -61,6 +61,12 @@ tree objc_eh_personality (void);
#define PROPERTY_READONLY(DECL) ((DECL)->decl_minimal.context)
#define PROPERTY_COPIES(DECL) ((DECL)->decl_common.size_unit)
+enum objc_property_assign_semantics {
+ OBJC_PROPERTY_ASSIGN = 1,
+ OBJC_PROPERTY_RETAIN = 2,
+ OBJC_PROPERTY_COPY = 3
+};
+
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
PROTOCOL_INTERFACE_TYPE */
@@ -1,5 +1,14 @@
2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+ * obj-c.dg/property/at-property-4.m: New.
+ * obj-c++.dg/property/at-property-4.mm: New.
+ * obj-c++.dg/property/property-neg-5.m: Updated testcase for
+ updates in warning.
+ * obj-c++.dg/property/property-neg-5.mm: Updated testcase for
+ updates in warning.
+
+2010-10-25 Nicola Pero <nicola.pero@meta-innovation.com>
+
* objc.dg/property/at-property-1.m: New.
* objc.dg/property/at-property-2.m: New.
* objc.dg/property/at-property-3.m: New.
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
+- (id) myGetter;
+- (id) myGetterB;
+- (void) mySetter: (id)property;
+- (void) mySetterB: (id)property;
+
+/* Test that all the new property attributes can be parsed. */
+@property (assign) id property_a;
+@property (copy) id property_b;
+@property (nonatomic) id property_c;
+@property (readonly) id property_d;
+@property (readwrite) id property_e;
+@property (retain) id property_f;
+@property (release) id property_g; /* { dg-error "unknown property attribute" } */
+
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (getter=myGetter) id property_h; */
+/* @property (setter=mySetter:) id property_i; */
+
+/* Now test various problems. */
+
+@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+
+@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
+@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
+@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
+
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (setter=mySetter:,setter=mySetterB:) id f; */ /* dg-error ".setter. attribute may only be specified once" */
+/* @property (getter=myGetter:,getter=myGetterB:) id f; */ /* dg-error ".getter. attribute may only be specified once" */
+
+@end
@@ -2,6 +2,6 @@
/* { dg-do compile } */
@interface Foo
-@property ( readonly, getter = HELLO, setter = THERE : ) int value;
+@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
@end /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */
/* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
+- (id) myGetter;
+- (id) myGetterB;
+- (void) mySetter: (id)property;
+- (void) mySetterB: (id)property;
+
+/* Test that all the new property attributes can be parsed. */
+@property (assign) id property_a;
+@property (copy) id property_b;
+@property (nonatomic) id property_c;
+@property (readonly) id property_d;
+@property (readwrite) id property_e;
+@property (retain) id property_f;
+@property (release) id property_g; /* { dg-error "unknown property attribute" } */
+
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (getter=myGetter) id property_h; */
+/* @property (setter=mySetter:) id property_i; */
+
+/* Now test various problems. */
+
+@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+
+@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
+@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
+@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
+
+/* The following will be enabled when @synthesized is implemented. */
+/* @property (setter=mySetter:,setter=mySetterB:) id f; */ /* dg-error ".setter. attribute may only be specified once" */
+/* @property (getter=myGetter:,getter=myGetterB:) id f; */ /* dg-error ".getter. attribute may only be specified once" */
+
+@end
@@ -2,6 +2,6 @@
/* { dg-do compile } */
@interface Foo
-@property ( readonly, getter = HELLO, setter = THERE : ) int value;
+@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
@end /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */
/* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */