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
This commit is contained in:
parent
f0a0390e69
commit
f7e71da52f
|
@ -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.
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
119
gcc/c-parser.c
119
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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".
|
||||
|
|
141
gcc/cp/parser.c
141
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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
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.
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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];
|
||||
}
|
Loading…
Reference in New Issue