diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 10 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 28 | ||||
-rw-r--r-- | gcc/c-family/stub-objc.c | 20 | ||||
-rw-r--r-- | gcc/c-parser.c | 106 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/parser.c | 106 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 187 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/at-property-4.mm | 41 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/property-neg-5.mm | 2 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/at-property-4.m | 41 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/property-neg-5.m | 2 |
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 } */ |