Patchwork [ObjC/C++,Attributes,Part2] Recognize attributes on Methods and Method params.

login
register
mail settings
Submitter IainS
Date Sept. 28, 2010, 5:07 p.m.
Message ID <0FA6C616-C5FB-481A-ADE2-DDE7D657B5A3@sandoe-acoustics.co.uk>
Download mbox | patch
Permalink /patch/66005/
State New
Headers show

Comments

IainS - Sept. 28, 2010, 5:07 p.m.
Hi Mike,

Again this patch touches gcc/ gcc/cp gcc/objc gcc/c-family (and  
testsuite) but only in ObjC routines/code paths.

This adds the parser support for attributes on ObjC* methods and their  
parameters (at least as described in the OSX 10.5 runtime release  
notes).

I looked at the FSF apple-local/trunk  gcc/c-parser.in etc. (the radar  
is 3803157).    What I ended up looks quite different tho.

In particular:
  o  there is diagnosis of erroneous prefix attributes on methods
  o I added the parsing of method parameter attributes (although this  
could be regarded as almost obvious once the rest is done).
  o I tried to make both the behavior and code of the c++ and c parts  
match.
  o different code factoring decisions.

So it should be reviewed as new code rather than a merge.

[The objc-act implementation of the functionality - to follow once  
this patch is agreed -- is probably going made as a straight merge  
from the apple local branch]

tested on i686-darwin9, x86_64-linux and a cross to cris-elf

OK for trunk?
Iain

gcc/cp:
	
	* 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.
testsuuite:

	* 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.
Index: gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm	(revision 0)
+++ gcc/testsuite/obj-c++.dg/attributes/method-attribute-1.mm	(revision 0)
@@ -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];    
+}
Index: gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm	(revision 0)
+++ gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm	(revision 0)
@@ -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];    
+}

Index: gcc/testsuite/objc.dg/attributes/method-attribute-1.m
===================================================================
--- gcc/testsuite/objc.dg/attributes/method-attribute-1.m	(revision 0)
+++ gcc/testsuite/objc.dg/attributes/method-attribute-1.m	(revision 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];    
+}
Index: gcc/testsuite/objc.dg/attributes/method-attribute-2.m
===================================================================
--- gcc/testsuite/objc.dg/attributes/method-attribute-2.m	(revision 0)
+++ gcc/testsuite/objc.dg/attributes/method-attribute-2.m	(revision 0)
@@ -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];    
+}
Mike Stump - Sept. 28, 2010, 5:25 p.m.
On Sep 28, 2010, at 10:07 AM, IainS wrote:
> OK for trunk?

Ok.

Patch

Index: 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);
Index: gcc/c-family/stub-objc.c
===================================================================
@@ -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;
 }
Index: gcc/cp/parser.c
===================================================================
@@ -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);
Index: gcc/objc/objc-act.c
===================================================================
@@ -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
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c      2010-09-28 17:17:10.000000000 +0100
+++ gcc/c-parser.c-attr 2010-09-28 15:30:42.000000000 +0100
@@ -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);
 }