aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-parser.c
diff options
context:
space:
mode:
authorIain Sandoe <iains@gcc.gnu.org>2010-09-28 21:02:38 +0000
committerIain Sandoe <iains@gcc.gnu.org>2010-09-28 21:02:38 +0000
commitf7e71da52f7d29cd3bdb81815026d0daf8bbbb9e (patch)
tree0b58ec78878b5ec817b8d9d6545ff6e30a03c52c /gcc/c-parser.c
parentf0a0390e691ece0d859b7d87c6e6617d227cb8dd (diff)
downloadgcc-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.c119
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);
}