diff options
author | iains <iains@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-28 21:02:38 +0000 |
---|---|---|
committer | iains <iains@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-28 21:02:38 +0000 |
commit | 03fc2271198493dcf1377e49f603aa9e004eb642 (patch) | |
tree | 0b58ec78878b5ec817b8d9d6545ff6e30a03c52c | |
parent | cc7d6aed6b7186313ada1a58107b9dbcaac2f435 (diff) | |
download | gcc-03fc2271198493dcf1377e49f603aa9e004eb642.tar.gz |
add parsing for ObjC* method & method parm attributes
gcc/cp:
Partially merged from apple/trunk branch on FSF servers:
2006-04-26 Fariborz Jahanian <fjahanian@apple.com>
Radar 3803157 (method attributes)
* parser.c (cp_parser_objc_method_keyword_params): Handle attributes.
(cp_parser_objc_method_tail_params_opt): Likewise.
(cp_parser_objc_method_signature): Likewise.
(cp_parser_objc_method_maybe_bad_prefix_attributes): New.
(cp_parser_objc_method_prototype_list): Handle attributes.
(cp_parser_objc_method_definition_list): Likewise.
gcc/objc:
* objc-act.c (objc_add_method_declaration): Handle attributes.
(objc_start_method_definition): Likewise.
(objc_generate_cxx_ctor_or_dtor): Pass NULL attributes to ctor/dtor.
(objc_build_keyword_decl): Handle attributes.
gcc:
* c-parser.c (c_parser_declaration_or_fndef): Diagnose incorrect prefix
attributes on methods.
(c_parser_objc_method_definition): Handle attributes.
(c_parser_objc_methodproto): Likewise.
(c_parser_objc_maybe_method_attributes): New.
(c_parser_objc_method_decl): Handle attributes, add a similar diagnostic
to ObjC++ for a missing definition.
gcc/c-family:
* c-common.h: Update declarations to include attributes.
* stub-objc.c: Likewise.
testsuite:
* objc.dg/attributes/method-attribute-1.m: New.
* objc.dg/attributes/method-attribute-2.m: New.
* obj-c++.dg/attributes/method-attribute-1.m: New.
* obj-c++.dg/attributes/method-attribute-2.m: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164702 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 6 | ||||
-rw-r--r-- | gcc/c-family/stub-objc.c | 9 | ||||
-rw-r--r-- | gcc/c-parser.c | 119 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/parser.c | 141 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm | 41 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm | 31 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/attributes/method-attribute-1.m | 40 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/attributes/method-attribute-2.m | 31 |
14 files changed, 455 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c4304e61876..2aded972862 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + + * c-parser.c (c_parser_declaration_or_fndef): Diagnose incorrect prefix + attributes on methods. + (c_parser_objc_method_definition): Handle attributes. + (c_parser_objc_methodproto): Likewise. + (c_parser_objc_maybe_method_attributes): New. + (c_parser_objc_method_decl): Handle attributes, add a diagnostic for a + missing definition, similar to that in ObjC++. + 2010-09-28 Richard Henderson <rth@redhat.com> * defaults.h (DWARF2_UNWIND_INFO): Don't depend on TARGET_UNWIND_INFO. @@ -62,7 +72,7 @@ (TARGET_UNWIND_INFO): Remove. * config/pa/pa.c (pa_option_override): Use targetm.except_unwind_info. - + 2010-09-28 Iain Sandoe <iains@gcc.gnu.org> * c-parser.c (c_parser_objc_class_definition): Adjust prototype. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index b3687d8c71c..7480f63f321 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,5 +1,15 @@ 2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + * c-common.h (objc_add_method_declaration): Adjust prototype to + include attributes. + (objc_start_method_definition): Likewise. + (objc_build_keyword_decl): Likewise. + * stub-objc.c:(objc_add_method_declaration): Handle attributes. + (objc_start_method_definition): Likewise. + (objc_build_keyword_decl): Likewise. + +2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + * c-common.h (objc_start_class_interface): Adjust prototype. (objc_start_category_interface): Likewise. (objc_start_protocol): Likewise. diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 99efe84906d..45ec999745e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -977,11 +977,11 @@ extern void objc_finish_implementation (void); extern void objc_set_visibility (int); extern void objc_set_method_type (enum tree_code); extern tree objc_build_method_signature (tree, tree, tree, bool); -extern void objc_add_method_declaration (tree); -extern bool objc_start_method_definition (tree); +extern void objc_add_method_declaration (tree, tree); +extern bool objc_start_method_definition (tree, tree); extern void objc_finish_method_definition (tree); extern void objc_add_instance_variable (tree); -extern tree objc_build_keyword_decl (tree, tree, tree); +extern tree objc_build_keyword_decl (tree, tree, tree, tree); extern tree objc_build_throw_stmt (location_t, tree); extern void objc_begin_try_stmt (location_t, tree); extern tree objc_finish_try_stmt (void); diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c index 83472bef1d1..6e205bfb178 100644 --- a/gcc/c-family/stub-objc.c +++ b/gcc/c-family/stub-objc.c @@ -196,12 +196,14 @@ objc_finish_implementation (void) } void -objc_add_method_declaration (tree ARG_UNUSED (signature)) +objc_add_method_declaration (tree ARG_UNUSED (signature), + tree ARG_UNUSED (attributes)) { } bool -objc_start_method_definition (tree ARG_UNUSED (signature)) +objc_start_method_definition (tree ARG_UNUSED (signature), + tree ARG_UNUSED (attributes)) { return true; } @@ -214,7 +216,8 @@ objc_finish_method_definition (tree ARG_UNUSED (fndecl)) tree objc_build_keyword_decl (tree ARG_UNUSED (selector), tree ARG_UNUSED (type), - tree ARG_UNUSED (identifier)) + tree ARG_UNUSED (identifier), + tree ARG_UNUSED (attributes)) { return 0; } diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 2743f3020e4..5d0f36bacb2 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -986,7 +986,7 @@ static enum tree_code c_parser_objc_method_type (c_parser *); static void c_parser_objc_method_definition (c_parser *); static void c_parser_objc_methodprotolist (c_parser *); static void c_parser_objc_methodproto (c_parser *); -static tree c_parser_objc_method_decl (c_parser *); +static tree c_parser_objc_method_decl (c_parser *, tree *); static tree c_parser_objc_type_name (c_parser *); static tree c_parser_objc_protocol_refs (c_parser *); static void c_parser_objc_try_catch_statement (c_parser *); @@ -1244,6 +1244,29 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } else if (c_dialect_objc ()) { + /* Prefix attributes are an error on method decls. */ + switch (c_parser_peek_token (parser)->type) + { + case CPP_PLUS: + case CPP_MINUS: + if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) + return; + if (specs->attrs) + { + warning_at (c_parser_peek_token (parser)->location, + OPT_Wattributes, + "prefix attributes are ignored for methods"); + specs->attrs = NULL_TREE; + } + if (fndef_ok) + c_parser_objc_method_definition (parser); + else + c_parser_objc_methodproto (parser); + return; + break; + default: + break; + } /* This is where we parse 'attributes @interface ...', 'attributes @implementation ...', 'attributes @protocol ...' (where attributes could be, for example, __attribute__ @@ -6635,23 +6658,28 @@ static void c_parser_objc_method_definition (c_parser *parser) { enum tree_code type = c_parser_objc_method_type (parser); - tree decl; + tree decl, attributes = NULL_TREE; objc_set_method_type (type); parser->objc_pq_context = true; - decl = c_parser_objc_method_decl (parser); + decl = c_parser_objc_method_decl (parser, &attributes); + if (decl == error_mark_node) + return; /* Bail here. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, "extra semicolon in method definition specified"); } + if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { c_parser_error (parser, "expected %<{%>"); return; } + parser->objc_pq_context = false; - if (objc_start_method_definition (decl)) + if (objc_start_method_definition (decl, attributes)) { add_stmt (c_parser_compound_statement (parser)); objc_finish_method_definition (current_function_decl); @@ -6722,17 +6750,64 @@ static void c_parser_objc_methodproto (c_parser *parser) { enum tree_code type = c_parser_objc_method_type (parser); - tree decl; + tree decl, attributes = NULL_TREE; objc_set_method_type (type); /* Remember protocol qualifiers in prototypes. */ parser->objc_pq_context = true; - decl = c_parser_objc_method_decl (parser); - /* Forget protocol qualifiers here. */ + decl = c_parser_objc_method_decl (parser, &attributes); + /* Forget protocol qualifiers now. */ parser->objc_pq_context = false; - objc_add_method_declaration (decl); + + /* Do not allow the presence of attributes to hide an erroneous + method implementation in the interface section. */ + if (!c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + c_parser_error (parser, "expected %<;%>"); + return; + } + + if (decl != error_mark_node) + objc_add_method_declaration (decl, attributes); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } +/* If we are at a position that method attributes may be present, check that + there are not any parsed already (a syntax error) and then collect any + specified at the current location. Finally, if new attributes were present, + check that the next token is legal ( ';' for decls and '{' for defs). */ + +static bool +c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes) +{ + bool bad = false; + if (*attributes) + { + c_parser_error (parser, + "method attributes must be specified at the end only"); + *attributes = NULL_TREE; + bad = true; + } + + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + *attributes = c_parser_attributes (parser); + + /* If there were no attributes here, just report any earlier error. */ + if (*attributes == NULL_TREE || bad) + return bad; + + /* If the attributes are followed by a ; or {, then just report any earlier + error. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON) + || c_parser_next_token_is (parser, CPP_OPEN_BRACE)) + return bad; + + /* We've got attributes, but not at the end. */ + c_parser_error (parser, + "expected %<;%> or %<{%> after method attribute definition"); + return true; +} + /* Parse an objc-method-decl. objc-method-decl: @@ -6740,6 +6815,7 @@ c_parser_objc_methodproto (c_parser *parser) objc-selector ( objc-type-name ) objc-keyword-selector objc-optparmlist objc-keyword-selector objc-optparmlist + attributes objc-keyword-selector: objc-keyword-decl @@ -6764,13 +6840,15 @@ c_parser_objc_methodproto (c_parser *parser) */ static tree -c_parser_objc_method_decl (c_parser *parser) +c_parser_objc_method_decl (c_parser *parser, tree *attributes) { tree type = NULL_TREE; tree sel; tree parms = NULL_TREE; bool ellipsis = false; + bool attr_err = false; + *attributes = NULL_TREE; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { c_parser_consume_token (parser); @@ -6788,6 +6866,7 @@ c_parser_objc_method_decl (c_parser *parser) while (true) { tree atype = NULL_TREE, id, keyworddecl; + tree param_attr = NULL_TREE; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) break; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) @@ -6797,6 +6876,9 @@ c_parser_objc_method_decl (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } + /* New ObjC allows attributes on method parameters. */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + param_attr = c_parser_attributes (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { c_parser_error (parser, "expected identifier"); @@ -6804,12 +6886,15 @@ c_parser_objc_method_decl (c_parser *parser) } id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); - keyworddecl = objc_build_keyword_decl (tsel, atype, id); + keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr); list = chainon (list, keyworddecl); tsel = c_parser_objc_selector (parser); if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) break; } + + attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ; + /* Parse the optional parameter list. Optional Objective-C method parameters follow the C syntax, and may include '...' to denote a variable number of arguments. */ @@ -6822,6 +6907,8 @@ c_parser_objc_method_decl (c_parser *parser) { ellipsis = true; c_parser_consume_token (parser); + attr_err |= c_parser_objc_maybe_method_attributes + (parser, attributes) ; break; } parm = c_parser_parameter_declaration (parser, NULL_TREE); @@ -6832,6 +6919,18 @@ c_parser_objc_method_decl (c_parser *parser) } sel = list; } + else + attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ; + + if (sel == NULL) + { + c_parser_error (parser, "objective-c method declaration is expected"); + return error_mark_node; + } + + if (attr_err) + return error_mark_node; + return objc_build_method_signature (type, sel, parms, ellipsis); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 095ac2efa89..1776ee6fba8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + + Partially merged from apple/trunk branch on FSF servers: + 2006-04-26 Fariborz Jahanian <fjahanian@apple.com> + Radar 3803157 (method attributes) + + * parser.c (cp_parser_objc_method_keyword_params): Handle attributes. + (cp_parser_objc_method_tail_params_opt): Likewise. + (cp_parser_objc_method_signature): Likewise. + (cp_parser_objc_method_maybe_bad_prefix_attributes): New. + (cp_parser_objc_method_prototype_list): Handle attributes. + (cp_parser_objc_method_definition_list): Likewise. + 2010-09-28 Richard Henderson <rth@redhat.com> * cp-lang.c: Include "target.h". diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8f6ea256ea7..b622613d3ca 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -21449,7 +21449,7 @@ cp_parser_objc_selector (cp_parser* parser) /* Parse an Objective-C params list. */ static tree -cp_parser_objc_method_keyword_params (cp_parser* parser) +cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes) { tree params = NULL_TREE; bool maybe_unary_selector_p = true; @@ -21458,6 +21458,10 @@ cp_parser_objc_method_keyword_params (cp_parser* parser) while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) { tree selector = NULL_TREE, type_name, identifier; + tree parm_attr = NULL_TREE; + + if (token->keyword == RID_ATTRIBUTE) + break; if (token->type != CPP_COLON) selector = cp_parser_objc_selector (parser); @@ -21465,29 +21469,55 @@ cp_parser_objc_method_keyword_params (cp_parser* parser) /* Detect if we have a unary selector. */ if (maybe_unary_selector_p && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) - return selector; + { + params = selector; /* Might be followed by attributes. */ + break; + } maybe_unary_selector_p = false; cp_parser_require (parser, CPP_COLON, RT_COLON); type_name = cp_parser_objc_typename (parser); + /* New ObjC allows attributes on parameters too. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) + parm_attr = cp_parser_attributes_opt (parser); identifier = cp_parser_identifier (parser); params = chainon (params, objc_build_keyword_decl (selector, type_name, - identifier)); + identifier, + parm_attr)); token = cp_lexer_peek_token (parser->lexer); } + if (params == NULL_TREE) + { + cp_parser_error (parser, "objective-c++ method declaration is expected"); + return error_mark_node; + } + + /* We allow tail attributes for the method. */ + if (token->keyword == RID_ATTRIBUTE) + { + *attributes = cp_parser_attributes_opt (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + return params; + cp_parser_error (parser, + "method attributes must be specified at the end"); + return error_mark_node; + } + return params; } /* Parse the non-keyword Objective-C params. */ static tree -cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) +cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, + tree* attributes) { tree params = make_node (TREE_LIST); cp_token *token = cp_lexer_peek_token (parser->lexer); @@ -21508,6 +21538,7 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) break; } + /* TODO: parse attributes for tail parameters. */ parmdecl = cp_parser_parameter_declaration (parser, false, NULL); parm = grokdeclarator (parmdecl->declarator, &parmdecl->decl_specifiers, @@ -21518,6 +21549,26 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) token = cp_lexer_peek_token (parser->lexer); } + /* We allow tail attributes for the method. */ + if (token->keyword == RID_ATTRIBUTE) + { + if (*attributes == NULL_TREE) + { + *attributes = cp_parser_attributes_opt (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + return params; + } + else + /* We have an error, but parse the attributes, so that we can + carry on. */ + *attributes = cp_parser_attributes_opt (parser); + + cp_parser_error (parser, + "method attributes must be specified at the end"); + return error_mark_node; + } + return params; } @@ -21547,34 +21598,70 @@ cp_parser_objc_interstitial_code (cp_parser* parser) /* Parse a method signature. */ static tree -cp_parser_objc_method_signature (cp_parser* parser) +cp_parser_objc_method_signature (cp_parser* parser, tree* attributes) { tree rettype, kwdparms, optparms; bool ellipsis = false; cp_parser_objc_method_type (parser); rettype = cp_parser_objc_typename (parser); - kwdparms = cp_parser_objc_method_keyword_params (parser); - optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis); + *attributes = NULL_TREE; + kwdparms = cp_parser_objc_method_keyword_params (parser, attributes); + if (kwdparms == error_mark_node) + return error_mark_node; + optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes); + if (optparms == error_mark_node) + return error_mark_node; return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis); } -/* Pars an Objective-C method prototype list. */ +static bool +cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser) +{ + tree tattr; + cp_lexer_save_tokens (parser->lexer); + tattr = cp_parser_attributes_opt (parser); + gcc_assert (tattr) ; + + /* If the attributes are followed by a method introducer, this is not allowed. + Dump the attributes and flag the situation. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS) + || cp_lexer_next_token_is (parser->lexer, CPP_MINUS)) + return true; + + /* Otherwise, the attributes introduce some interstitial code, possibly so + rewind to allow that check. */ + cp_lexer_rollback_tokens (parser->lexer); + return false; +} + +/* Parse an Objective-C method prototype list. */ static void cp_parser_objc_method_prototype_list (cp_parser* parser) { cp_token *token = cp_lexer_peek_token (parser->lexer); - while (token->keyword != RID_AT_END) + while (token->keyword != RID_AT_END && token->type != CPP_EOF) { if (token->type == CPP_PLUS || token->type == CPP_MINUS) { - objc_add_method_declaration - (cp_parser_objc_method_signature (parser)); + tree attributes, sig; + sig = cp_parser_objc_method_signature (parser, &attributes); + if (sig == error_mark_node) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + continue; + } + objc_add_method_declaration (sig, attributes); cp_parser_consume_semicolon_at_end_of_statement (parser); } + else if (token->keyword == RID_ATTRIBUTE + && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) + warning_at (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wattributes, + "prefix attributes are ignored for methods"); else /* Allow for interspersed non-ObjC++ code. */ cp_parser_objc_interstitial_code (parser); @@ -21593,27 +21680,43 @@ cp_parser_objc_method_definition_list (cp_parser* parser) { cp_token *token = cp_lexer_peek_token (parser->lexer); - while (token->keyword != RID_AT_END) + while (token->keyword != RID_AT_END && token->type != CPP_EOF) { tree meth; if (token->type == CPP_PLUS || token->type == CPP_MINUS) { + cp_token *ptk; + tree sig, attribute; push_deferring_access_checks (dk_deferred); - objc_start_method_definition - (cp_parser_objc_method_signature (parser)); + sig = cp_parser_objc_method_signature (parser, &attribute); + if (sig == error_mark_node) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + continue; + } + objc_start_method_definition (sig, attribute); /* For historical reasons, we accept an optional semicolon. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) cp_lexer_consume_token (parser->lexer); - perform_deferred_access_checks (); - stop_deferring_access_checks (); - meth = cp_parser_function_definition_after_declarator (parser, + ptk = cp_lexer_peek_token (parser->lexer); + if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS + || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END)) + { + perform_deferred_access_checks (); + stop_deferring_access_checks (); + meth = cp_parser_function_definition_after_declarator (parser, false); - pop_deferring_access_checks (); - objc_finish_method_definition (meth); + pop_deferring_access_checks (); + objc_finish_method_definition (meth); + } } + else if (token->keyword == RID_ATTRIBUTE + && cp_parser_objc_method_maybe_bad_prefix_attributes(parser)) + warning_at (token->location, OPT_Wattributes, + "prefix attributes are ignored for methods"); else /* Allow for interspersed non-ObjC++ code. */ cp_parser_objc_interstitial_code (parser); diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 7aa91dc395d..26be691cc37 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,11 @@ +2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + + * objc-act.c (objc_add_method_declaration): Handle and ignore + attributes. + (objc_start_method_definition): Likewise. + (objc_generate_cxx_ctor_or_dtor): Pass NULL attributes to ctor/dtor. + (objc_build_keyword_decl): Handle and ignore attributes. + 2010-09-28 Richard Henderson <rth@redhat.com> * objc-act.c (objc_eh_personality): Use targetm.except_unwind_info. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 67e9b516d43..02c60ab0bdd 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -769,7 +769,7 @@ objc_build_method_signature (tree rettype, tree selector, } void -objc_add_method_declaration (tree decl) +objc_add_method_declaration (tree decl, tree attributes) { if (!objc_interface_context) { @@ -780,6 +780,11 @@ objc_add_method_declaration (tree decl) fatal_error ("method declaration not in @interface context"); } + if (attributes) + warning_at (input_location, OPT_Wattributes, + "method attributes are not available in this version" + " of the compiler, (ignored)"); + objc_add_method (objc_interface_context, decl, objc_inherit_code == CLASS_METHOD_DECL); @@ -789,7 +794,7 @@ objc_add_method_declaration (tree decl) 'false' if not (because we are outside an @implementation context). */ bool -objc_start_method_definition (tree decl) +objc_start_method_definition (tree decl, tree attributes) { if (!objc_implementation_context) { @@ -797,6 +802,11 @@ objc_start_method_definition (tree decl) return false; } + if (attributes) + warning_at (input_location, OPT_Wattributes, + "method attributes are not available in this version" + " of the compiler, (ignored)"); + #ifndef OBJCPLUS /* Indicate no valid break/continue context by setting these variables to some non-null, non-label value. We'll notice and emit the proper @@ -4644,7 +4654,7 @@ objc_generate_cxx_ctor_or_dtor (bool dtor) ? TAG_CXX_DESTRUCT : TAG_CXX_CONSTRUCT), make_node (TREE_LIST), - false)); + false), NULL); body = begin_function_body (); compound_stmt = begin_compound_stmt (0); @@ -5976,6 +5986,7 @@ adjust_type_for_id_default (tree type) In: key_name, an "identifier_node" (optional). arg_type, a "tree_list" (optional). arg_name, an "identifier_node". + attributes, a optional tree containing param attributes. Note: It would be really nice to strongly type the preceding arguments in the function prototype; however, then I @@ -5984,10 +5995,16 @@ adjust_type_for_id_default (tree type) Out: an instance of "keyword_decl". */ tree -objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name) +objc_build_keyword_decl (tree key_name, tree arg_type, + tree arg_name, tree attributes) { tree keyword_decl; + if (attributes) + warning_at (input_location, OPT_Wattributes, + "method parameter attributes are not available in this " + "version of the compiler, (ignored)"); + /* If no type is specified, default to "id". */ arg_type = adjust_type_for_id_default (arg_type); @@ -8128,7 +8145,7 @@ encode_array (tree type, int curtype, int format) tree an_int_cst = TYPE_SIZE (type); tree array_of = TREE_TYPE (type); char buffer[40]; - + if (an_int_cst == NULL) { /* We are trying to encode an incomplete array. An incomplete diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 22cb056a0d2..4cbe57b18de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,13 @@ 2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + * objc.dg/attributes/method-attribute-1.m: New. + * objc.dg/attributes/method-attribute-2.m: New. + + * obj-c++.dg/attributes/method-attribute-1.m: New. + * obj-c++.dg/attributes/method-attribute-2.m: New. + +2010-09-28 Iain Sandoe <iains@gcc.gnu.org> + * objc.dg/attributes: New. * objc.dg/attributes/attributes.exp: New. * objc.dg/attributes/class-attribute-1.m: New. diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm new file mode 100644 index 00000000000..2e2326c13b5 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm @@ -0,0 +1,41 @@ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; ++ (id) dep_cls_mth __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mth __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mtharg: (int) i __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mtharg1: (int) i __attribute__((deprecated)) add: (int) j;/* { dg-error "method attributes must be specified at the end " } */ +- (int) nodef __attribute__((deprecated)) { return var-2; } ; /* { dg-error "expected ';' before '\{' token" } */ + /* { dg-warning "method attributes are not available in this version" "" { target *-*-* } 15 } */ +__attribute__((deprecated)) +- (int) bad_pref_mth; /* { dg-warning "prefix attributes are ignored for methods" } */ +@end + +@implementation obj +- (int) mth { return var; } ++ (id) dep_cls_mth { return self; } +- (int) dep_ins_mth { return var ; } +- (int) dep_ins_mtharg: (int) i { return var + i ; } +- (int) dep_ins_mtharg1: (int) i add: (int) j { return var + i + j ; } +- (int) bad_pref_mth { return var; }; +- (int) nodef { return var-2; } ; +@end + +int foo (void) +{ + obj *p = [obj new]; + id n = [obj dep_cls_mth]; + + [p dep_ins_mth]; + [p dep_ins_mtharg:2]; + [p dep_ins_mtharg1:3 add:3]; + + return [p mth]; +} diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm b/gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm new file mode 100644 index 00000000000..f02149e3332 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm @@ -0,0 +1,31 @@ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) depmtharg:(int) iarg __attribute__((deprecated)); /* { dg-warning "method attributes are not available in this version" } */ +- (int) unusedarg:(int) __attribute__((unused)) uarg ; /* { dg-warning "method parameter attributes are not available in this version" } */ +- (int) depunusedarg:(int) __attribute__((unused)) uarg __attribute__((deprecated)) ; /* { dg-warning "method attributes are not available in this version" } */ + /* { dg-warning "method parameter attributes are not available in this version" "" { target *-*-* } 12 } */ +@end + +@implementation obj +- (int) depmtharg:(int) iarg { return var + iarg ; }; +- (int) unusedarg:(int) __attribute__((unused)) uarg { return var; } ; /* { dg-warning "method parameter attributes are not available in this version" } */ +- (int) depunusedarg:(int) __attribute__((unused)) uarg { return var; }; /* { dg-warning "method parameter attributes are not available in this version" } */ +@end + +int foo (void) +{ + obj *p = [obj new]; + + [p depmtharg:1]; + [p unusedarg:2]; + [p depunusedarg:3 ]; + + return [p depmtharg:0]; +} diff --git a/gcc/testsuite/objc.dg/attributes/method-attribute-1.m b/gcc/testsuite/objc.dg/attributes/method-attribute-1.m new file mode 100644 index 00000000000..83bc1c02468 --- /dev/null +++ b/gcc/testsuite/objc.dg/attributes/method-attribute-1.m @@ -0,0 +1,40 @@ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) mth; ++ (id) dep_cls_mth __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mth __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mtharg: (int) i __attribute__((deprecated)) ;/* { dg-warning "method attributes are not available in this version" } */ +- (int) dep_ins_mtharg1: (int) i __attribute__((deprecated)) add: (int) j;/* { dg-error "expected ';' or '\{' after method attribute definition" } */ +- (int) nodef __attribute__((deprecated)) { return var-2; } ; /* { dg-error "expected ';' before '\{' token" } */ +__attribute__((deprecated)) +- (int) bad_pref_mth; /* { dg-warning "prefix attributes are ignored for methods" } */ +@end + +@implementation obj +- (int) mth { return var; } ++ (id) dep_cls_mth { return self; } +- (int) dep_ins_mth { return var ; } +- (int) dep_ins_mtharg: (int) i { return var + i ; } +- (int) dep_ins_mtharg1: (int) i add: (int) j { return var + i + j ; } +- (int) bad_pref_mth { return var; }; +- (int) nodef { return var-2; } ; +@end + +int foo (void) +{ + obj *p = [obj new]; + id n = [obj dep_cls_mth]; + + [p dep_ins_mth]; + [p dep_ins_mtharg:2]; + [p dep_ins_mtharg1:3 add:3]; + + return [p mth]; +} diff --git a/gcc/testsuite/objc.dg/attributes/method-attribute-2.m b/gcc/testsuite/objc.dg/attributes/method-attribute-2.m new file mode 100644 index 00000000000..f02149e3332 --- /dev/null +++ b/gcc/testsuite/objc.dg/attributes/method-attribute-2.m @@ -0,0 +1,31 @@ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include "../../objc-obj-c++-shared/Object1.h" + +@interface obj : Object { +@public + int var; +} +- (int) depmtharg:(int) iarg __attribute__((deprecated)); /* { dg-warning "method attributes are not available in this version" } */ +- (int) unusedarg:(int) __attribute__((unused)) uarg ; /* { dg-warning "method parameter attributes are not available in this version" } */ +- (int) depunusedarg:(int) __attribute__((unused)) uarg __attribute__((deprecated)) ; /* { dg-warning "method attributes are not available in this version" } */ + /* { dg-warning "method parameter attributes are not available in this version" "" { target *-*-* } 12 } */ +@end + +@implementation obj +- (int) depmtharg:(int) iarg { return var + iarg ; }; +- (int) unusedarg:(int) __attribute__((unused)) uarg { return var; } ; /* { dg-warning "method parameter attributes are not available in this version" } */ +- (int) depunusedarg:(int) __attribute__((unused)) uarg { return var; }; /* { dg-warning "method parameter attributes are not available in this version" } */ +@end + +int foo (void) +{ + obj *p = [obj new]; + + [p depmtharg:1]; + [p unusedarg:2]; + [p depunusedarg:3 ]; + + return [p depmtharg:0]; +} |