===================================================================
@@ -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);
===================================================================
@@ -193,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;
}
@@ -211,7 +216,8 @@ objc_finish_method_definition (tree ARG_UNUSED (fn
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;
}
===================================================================
@@ -21442,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;
@@ -21451,36 +21458,66 @@ static tree
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);
/* 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);
@@ -21501,6 +21538,7 @@ static tree
break;
}
+ /* TODO: parse attributes for tail parameters. */
parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
parm = grokdeclarator (parmdecl->declarator,
&parmdecl->decl_specifiers,
@@ -21511,6 +21549,26 @@ static tree
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;
}
@@ -21540,34 +21598,70 @@ cp_parser_objc_interstitial_code (cp_parser* parse
/* 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);
@@ -21586,27 +21680,43 @@ cp_parser_objc_method_definition_list (cp_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);
===================================================================
@@ -754,7 +768,7 @@ objc_build_method_signature (tree rettype, tree se
}
void
-objc_add_method_declaration (tree decl)
+objc_add_method_declaration (tree decl, tree attributes)
{
if (!objc_interface_context)
{
@@ -765,6 +779,11 @@ void
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);
@@ -774,7 +793,7 @@ void
'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)
{
@@ -782,6 +801,11 @@ bool
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
@@ -4629,7 +4653,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);
@@ -5961,6 +5985,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
@@ -5969,10 +5994,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);
@@ -8114,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
===================================================================
@@ -986,7 +986,7 @@ static enum tree_code c_parser_objc_meth
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
}
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 *par
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 *par
*/
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 *par
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 *par
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 *par
}
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 *par
{
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 *par
}
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);
}