aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-10-27 05:23:08 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-10-27 05:23:08 +0000
commit200290f23991f50e04f2ac5c4341f055db72bea5 (patch)
treeba6ae21d33b46a8fb8b884194c9eb79ecdd38f48 /gcc
parentf614132bc795c4773957e0d7fec7ee9dfd127274 (diff)
downloadgcc-200290f23991f50e04f2ac5c4341f055db72bea5.zip
gcc-200290f23991f50e04f2ac5c4341f055db72bea5.tar.gz
gcc-200290f23991f50e04f2ac5c4341f055db72bea5.tar.bz2
In gcc/: 2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/: 2010-10-27 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. In gcc/cp/: 2010-10-27 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. In gcc/c-family/: 2010-10-27 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. In gcc/objc/: 2010-10-27 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. In gcc/testsuite/: 2010-10-27 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. From-SVN: r165997
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/c-family/ChangeLog14
-rw-r--r--gcc/c-family/c-common.c10
-rw-r--r--gcc/c-family/c-common.h28
-rw-r--r--gcc/c-family/stub-objc.c20
-rw-r--r--gcc/c-parser.c106
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/parser.c106
-rw-r--r--gcc/objc/ChangeLog17
-rw-r--r--gcc/objc/objc-act.c187
-rw-r--r--gcc/objc/objc-act.h6
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-4.mm41
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-5.mm2
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-4.m41
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-5.m2
16 files changed, 437 insertions, 174 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 22fb34a..460cef3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
2010-10-27 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-27 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.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d742912..4f30512 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,5 +1,19 @@
2010-10-27 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-27 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.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 2f205ad..a847be2 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -556,10 +556,16 @@ const struct c_common_resword c_common_reswords[] =
{ "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 },
};
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 5563765..aa877d4 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -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_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_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);
diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c
index fb92c7f..d4a4e58 100644
--- a/gcc/c-family/stub-objc.c
+++ b/gcc/c-family/stub-objc.c
@@ -324,14 +324,18 @@ objc_get_class_ivars (tree ARG_UNUSED (name))
}
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))
{
}
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index c885c8a..932ab31 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -7603,24 +7603,42 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
@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_parser *parser)
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_parser *parser)
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_parser *parser)
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 %<;%>");
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 582e5c8..3a7e754 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2010-10-27 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-27 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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 95be6d3..d0bd6bb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -22648,23 +22648,41 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
@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 (cp_parser *parser)
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 (cp_parser *parser)
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 (cp_parser *parser)
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);
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index de29539..aa58764 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,5 +1,22 @@
2010-10-27 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-27 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
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index efdf17f..674b77e 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -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)
+ {
+ 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
{
- case OBJC_PATTR_INIT: /* init */
- property_readonly = property_copies = false;
- property_setter = property_getter = property_ivar = NULL_TREE;
- break;
- case OBJC_PATTR_READONLY: /* readonly */
+ 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_t location, tree decl)
}
}
}
+ 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_t location, tree decl)
? 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_t location, tree decl)
}
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_t location, tree decl)
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, tree property)
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.
*/
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index f56ae7b..2456c10 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -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 */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2a82488..09a9f6b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,14 @@
2010-10-27 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-27 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.
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
new file mode 100644
index 0000000..05223a3
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
@@ -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
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
index 53fada2..7a9090a 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
@@ -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 } */
diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m
new file mode 100644
index 0000000..05223a3
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-4.m
@@ -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
diff --git a/gcc/testsuite/objc.dg/property/property-neg-5.m b/gcc/testsuite/objc.dg/property/property-neg-5.m
index 53fada2..7a9090a 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-5.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-5.m
@@ -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 } */