diff options
author | Iain Sandoe <iains@gcc.gnu.org> | 2010-09-28 21:02:38 +0000 |
---|---|---|
committer | Iain Sandoe <iains@gcc.gnu.org> | 2010-09-28 21:02:38 +0000 |
commit | f7e71da52f7d29cd3bdb81815026d0daf8bbbb9e (patch) | |
tree | 0b58ec78878b5ec817b8d9d6545ff6e30a03c52c /gcc/c-parser.c | |
parent | f0a0390e691ece0d859b7d87c6e6617d227cb8dd (diff) | |
download | gcc-f7e71da52f7d29cd3bdb81815026d0daf8bbbb9e.zip gcc-f7e71da52f7d29cd3bdb81815026d0daf8bbbb9e.tar.gz gcc-f7e71da52f7d29cd3bdb81815026d0daf8bbbb9e.tar.bz2 |
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.
From-SVN: r164702
Diffstat (limited to 'gcc/c-parser.c')
-rw-r--r-- | gcc/c-parser.c | 119 |
1 files changed, 109 insertions, 10 deletions
diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 2743f30..5d0f36b 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); } |