Index: c-family/ChangeLog
===================================================================
--- c-family/ChangeLog	(revision 166103)
+++ c-family/ChangeLog	(working copy)
@@ -1,3 +1,9 @@
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented format and noreturn attributes for Objective-C methods.
+	* c-common.c (handle_noreturn_attribute): Recognize 'noreturn'
+	attribute for Objective-C methods.
+
 2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 166103)
+++ c-family/c-common.c	(working copy)
@@ -5731,7 +5731,8 @@ handle_noreturn_attribute (tree *node, tree name,
   tree type = TREE_TYPE (*node);
 
   /* See FIXME comment in c_common_attribute_table.  */
-  if (TREE_CODE (*node) == FUNCTION_DECL)
+  if (TREE_CODE (*node) == FUNCTION_DECL
+      || objc_method_decl (TREE_CODE (*node)))
     TREE_THIS_VOLATILE (*node) = 1;
   else if (TREE_CODE (type) == POINTER_TYPE
 	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 166103)
+++ objc/objc-act.c	(working copy)
@@ -1257,7 +1257,11 @@ objc_start_method_definition (bool is_class_method
   c_break_label = c_cont_label = size_zero_node;
 #endif
 
-  objc_decl_method_attributes (&decl, attributes, 0);
+  if (attributes)
+    warning_at (input_location, 0, "method attributes can not be specified in @implementation context");
+  else
+    objc_decl_method_attributes (&decl, attributes, 0);
+
   objc_add_method (objc_implementation_context,
 		   decl,
 		   is_class_method,
@@ -6590,6 +6594,11 @@ build_method_decl (enum tree_code code, tree ret_t
   /* If no type is specified, default to "id".  */
   ret_type = adjust_type_for_id_default (ret_type);
 
+  /* Note how a method_decl has a TREE_TYPE which is not the function
+     type of the function implementing the method, but only the return
+     type of the method.  We may want to change this, and store the
+     entire function type in there (eg, it may be used to simplify
+     dealing with attributes below).  */
   method_decl = make_node (code);
   TREE_TYPE (method_decl) = ret_type;
 
@@ -6620,19 +6629,119 @@ build_method_decl (enum tree_code code, tree ret_t
 static void
 objc_decl_method_attributes (tree *node, tree attributes, int flags)
 {
-  tree sentinel_attr = lookup_attribute ("sentinel", attributes);
-  if (sentinel_attr)
+  /* TODO: Replace the hackery below.  An idea would be to store the
+     full function type in the method declaration (for example in
+     TREE_TYPE) and then expose ObjC method declarations to c-family
+     and they could deal with them by simply treating them as
+     functions.  */
+
+  /* Because of the dangers in the hackery below, we filter out any
+     attribute that we do not know about.  For the ones we know about,
+     we know that they work with the hackery.  For the other ones,
+     there is no guarantee, so we have to filter them out.  */
+  tree filtered_attributes = NULL_TREE;
+
+  if (attributes)
     {
-      /* hackery to make an obj method look like a function type. */
-      tree rettype = TREE_TYPE (*node);
-      TREE_TYPE (*node) = build_function_type (TREE_VALUE (rettype), 
-		       	    get_arg_type_list (*node, METHOD_REF, 0));
-      decl_attributes (node, attributes, flags);
+      tree attribute;
+      for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute))
+	{
+	  const char *name = IDENTIFIER_POINTER (TREE_PURPOSE (attribute));
+	  
+	  if (strcmp (name, "deprecated") == 0
+	      || strcmp (name, "sentinel") == 0
+	      || strcmp (name, "noreturn") == 0)
+	    {
+	      /* An attribute that we support; add it to the filtered
+		 attributes.  */
+	      filtered_attributes = chainon (filtered_attributes, 
+					     copy_node (attribute));
+	    }
+	  else if (strcmp (name, "format") == 0)
+	    {
+	      /* "format" is special because before adding it to the
+		 filtered attributes we need to adjust the specified
+		 format by adding the hidden function parameters for
+		 an Objective-C method (self, _cmd).  */
+	      tree new_attribute = copy_node (attribute);
+
+	      /* Check the arguments specified with the attribute, and
+		 modify them adding 2 for the two hidden arguments.
+		 Note how this differs from C++; according to the
+		 specs, C++ does not do it so you have to add the +1
+		 yourself.  For Objective-C, instead, the compiler
+		 adds the +2 for you.  */
+
+	      /* The attribute arguments have not been checked yet, so
+		 we need to be careful as they could be missing or
+		 invalid.  If anything looks wrong, we skip the
+		 process and the compiler will complain about it later
+		 when it validates the attribute.  */
+	      /* Check that we have at least three arguments.  */
+	      if (TREE_VALUE (new_attribute)
+		  && TREE_CHAIN (TREE_VALUE (new_attribute))
+		  && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (new_attribute))))
+		{
+		  tree second_argument = TREE_CHAIN (TREE_VALUE (new_attribute));
+		  tree third_argument = TREE_CHAIN (second_argument);
+		  tree number;
+
+		  /* This is the second argument, the "string-index",
+		     which specifies the index of the format string
+		     argument.  Add 2.  */
+		  number = TREE_VALUE (second_argument);
+		  if (number
+		      && TREE_CODE (number) == INTEGER_CST
+		      && TREE_INT_CST_HIGH (number) == 0)
+		    {
+		      TREE_VALUE (second_argument) 
+			= build_int_cst (integer_type_node,
+					 TREE_INT_CST_LOW (number) + 2);
+		    }
+		  
+		  /* This is the third argument, the "first-to-check",
+		     which specifies the index of the first argument to
+		     check.  This could be 0, meaning it is not available,
+		     in which case we don't need to add 2.  Add 2 if not
+		     0.  */
+		  number = TREE_VALUE (third_argument);
+		  if (number
+		      && TREE_CODE (number) == INTEGER_CST
+		      && TREE_INT_CST_HIGH (number) == 0
+		      && TREE_INT_CST_LOW (number) != 0)
+		    {
+		      TREE_VALUE (third_argument) 
+			= build_int_cst (integer_type_node,
+					 TREE_INT_CST_LOW (number) + 2);
+		    }
+		}
+	      filtered_attributes = chainon (filtered_attributes,
+					     new_attribute);
+	    }
+	  else
+	    warning (OPT_Wattributes, "%qs attribute directive ignored", name);
+	}
+    }
+
+  if (filtered_attributes)
+    {
+      /* This hackery changes the TREE_TYPE of the ObjC method
+	 declaration to be a function type, so that decl_attributes
+	 will treat the ObjC method as if it was a function.  Some
+	 attributes (sentinel, format) will be applied to the function
+	 type, changing it in place; so after calling decl_attributes,
+	 we extract the function type attributes and store them in
+	 METHOD_TYPE_ATTRIBUTES.  Some other attributes (noreturn,
+	 deprecated) are applied directly to the method declaration
+	 (by setting TREE_DEPRECATED and TREE_THIS_VOLATILE) so there
+	 is nothing to do.  */
+      tree saved_type = TREE_TYPE (*node);
+      TREE_TYPE (*node) = build_function_type 
+	(TREE_VALUE (saved_type), get_arg_type_list (*node, METHOD_REF, 0));
+      decl_attributes (node, filtered_attributes, flags);
       METHOD_TYPE_ATTRIBUTES (*node) = TYPE_ATTRIBUTES (TREE_TYPE (*node));
-      TREE_TYPE (*node) = rettype;
+      TREE_TYPE (*node) = saved_type;
     }
-  else
-    decl_attributes (node, attributes, flags);
 }
 
 bool 
@@ -7141,7 +7250,27 @@ objc_finish_message_expr (tree receiver, tree sel_
 	  warn_missing_methods = true;
 	}
     }
+  else
+    {
+      /* Warn if the method is deprecated, but not if the receiver is
+	 a generic 'id'.  'id' is used to cast an object to a generic
+	 object of an unspecified class; in that case, we'll use
+	 whatever method prototype we can find to get the method
+	 argument and return types, but it is not appropriate to
+	 produce deprecation warnings since we don't know the class
+	 that the object will be of at runtime.  The @interface(s) for
+	 that class may not even be available to the compiler right
+	 now, and it is perfectly possible that the method is marked
+	 as non-deprecated in such @interface(s).
 
+	 In practice this makes sense since casting an object to 'id'
+	 is often used precisely to turn off warnings associated with
+	 the object being of a particular class.  */
+      if (TREE_DEPRECATED (method_prototype)  &&  rtype != NULL_TREE)
+	warn_deprecated_use (method_prototype, NULL_TREE);
+    }
+
+
   /* Save the selector name for printing error messages.  */
   current_objc_message_selector = sel_name;
 
@@ -7201,14 +7330,12 @@ build_objc_method_call (location_t loc, int super_
   tree method, t;
 
   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
-    ftype = build_type_attribute_variant (
-	      ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
+    ftype = build_type_attribute_variant (ftype, 
+					  METHOD_TYPE_ATTRIBUTES 
+					  (method_prototype));
 
   sender_cast = build_pointer_type (ftype);
 
-  if (method_prototype && TREE_DEPRECATED (method_prototype))
-    warn_deprecated_use (method_prototype, NULL_TREE);
-
   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
 
   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
@@ -10282,6 +10409,20 @@ really_start_method (tree method,
 		      (type ? '-' : '+'),
 		      identifier_to_locale (gen_method_decl (proto)));
 	    }
+	  else
+	    {
+	      /* If the method in the @interface was deprecated, mark
+		 the implemented method as deprecated too.  It should
+		 never be used for messaging (when the deprecation
+		 warnings are produced), but just in case.  */
+	      if (TREE_DEPRECATED (proto))
+		TREE_DEPRECATED (method) = 1;
+
+	      /* If the method in the @interface was marked as
+		 'noreturn', mark the function implementing the method
+		 as 'noreturn' too.  */
+	      TREE_THIS_VOLATILE (current_function_decl) = TREE_THIS_VOLATILE (proto);
+	    }
 	}
       else
 	{
Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog	(revision 166103)
+++ objc/ChangeLog	(working copy)
@@ -1,3 +1,19 @@
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented format and noreturn attributes for Objective-C methods.
+	* objc-act.c (objc_start_method_definition): If method attributes
+	are specified emit a warning and ignore them.
+	(build_objc_method_call): Moved deprecation warnings from here ...
+	(objc_finish_message_expr): to here.  Do not emit deprecation
+	warnings if the receiver is of type 'id'.
+	(really_start_method): Install 'deprecation' and 'noreturn'
+	attributes.
+	(objc_decl_method_attributes): Carefully filter out the list of
+	attributes, allowing only "noreturn", "format", "sentinel" and
+	"deprecated".  In the case of "format", adjust the arguments.
+	Always process the attributes in the same way no matter if
+	"sentinel" is in the list or not.
+	
 2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 166103)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,19 @@
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	Implemented format and noreturn attributes for Objective-C methods.
+	* objc.dg/attributes/method-attribute-2.m: Updated warnings.
+	* objc.dg/attributes/method-deprecated-1.m: New.
+	* objc.dg/attributes/method-deprecated-2.m: New.	
+	* objc.dg/attributes/method-noreturn-1.m: New.
+	* objc.dg/attributes/method-sentinel-1.m: New.
+	* objc.dg/attributes/method-format-1.m: New.
+	* obj-c++.dg/attributes/method-attribute-2.mm: Updated warnings.
+	* obj-c++.dg/attributes/method-deprecated-1.mm: New.
+	* obj-c++.dg/attributes/method-deprecated-2.mm: New.	
+	* obj-c++.dg/attributes/method-noreturn-1.mm: New.
+	* obj-c++.dg/attributes/method-sentinel-1.mm: New.
+	* obj-c++.dg/attributes/method-format-1.mm: New.	
+	
 2010-10-30  Janus Weil  <janus@gcc.gnu.org>
 
 	PR fortran/44917
Index: testsuite/objc.dg/attributes/method-noreturn-1.m
===================================================================
--- testsuite/objc.dg/attributes/method-noreturn-1.m	(revision 0)
+++ testsuite/objc.dg/attributes/method-noreturn-1.m	(revision 0)
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (id) method1 __attribute__ ((noreturn));
+- (id) method2 __attribute__ ((noreturn));
++ (id) method3 __attribute__ ((noreturn));
+- (id) method4 __attribute__ ((noreturn));
+@end
+
+@implementation MyClass
++ (id) method1
+{
+  return self;  /* { dg-warning "function declared .noreturn. has a .return. statement" } */
+}               /* { dg-warning ".noreturn. function does return" } */
+- (id) method2
+{
+  return self;  /* { dg-warning "function declared .noreturn. has a .return. statement" } */
+}               /* { dg-warning ".noreturn. function does return" } */
++ (id) method3
+{
+  abort ();
+}
+- (id) method4
+{
+  abort ();
+}
+@end
Index: testsuite/objc.dg/attributes/method-sentinel-1.m
===================================================================
--- testsuite/objc.dg/attributes/method-sentinel-1.m	(revision 0)
+++ testsuite/objc.dg/attributes/method-sentinel-1.m	(revision 0)
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface NSArray
+{
+  Class isa;
+} 
++ (id) arrayWithObject: (id)object __attribute__ ((sentinel));            /* { dg-warning "attribute only applies to variadic functions" } */
++ (id) arrayWithObjects: (id)firstObject, ... __attribute__ ((sentinel));
+
+- (id) initWithObject: (id)object __attribute__ ((sentinel));            /* { dg-warning "attribute only applies to variadic functions" } */
+- (id) initWithObjects: (id)firstObject, ... __attribute__ ((sentinel));
+@end
+
+void test (id object)
+{
+  NSArray *array;
+
+  array = [NSArray arrayWithObject: object];
+  array = [NSArray arrayWithObjects: object, nil];
+  array = [NSArray arrayWithObjects: object, object, nil];
+  array = [NSArray arrayWithObjects: object];               /* { dg-warning "not enough variable arguments" } */
+  array = [NSArray arrayWithObjects: object, object];       /* { dg-warning "missing sentinel" } */
+
+  [array initWithObject: object];
+  [array initWithObjects: object, nil];
+  [array initWithObjects: object, object, nil];
+  [array initWithObjects: object];               /* { dg-warning "not enough variable arguments" } */
+  [array initWithObjects: object, object];       /* { dg-warning "missing sentinel" } */
+}
Index: testsuite/objc.dg/attributes/method-format-1.m
===================================================================
--- testsuite/objc.dg/attributes/method-format-1.m	(revision 0)
+++ testsuite/objc.dg/attributes/method-format-1.m	(revision 0)
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface LogObject
+{
+  Class isa;
+} 
++ (void) log: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2, 3)));
+- (void) log: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2, 3)));
+
++ (void) debug: (const char *) my_format, ...  __attribute__ ((format (printf, 1, 2)));
+- (void) debug: (const char *) my_format, ...  __attribute__ ((format (printf, 1, 2)));
+
+/* Just make sure a missing or invalid attribute won't crash the compiler.  */
+- (void) log2: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2)));    /* { dg-error "wrong" } */
++ (void) debug2: (const char *) my_format, ...  __attribute__ ((format (printf))); /* { dg-error "wrong" } */
+- (void) debug2: (const char *) my_format, ...  __attribute__ ((format (printf))); /* { dg-error "wrong" } */
++ (void) alert: (const char *) my_format __attribute__ ((format (printf, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+- (void) alert: (const char *) my_format __attribute__ ((format (printf, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+@end
+
+void test (LogObject *object)
+{
+  [object log: 2  message: "attribute only applies to variadic functions"];
+  [object log: 2  message: "attribute %s only applies to variadic functions", "'format'"];
+  [object log: 2  message: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [object debug: "attribute only applies to variadic functions"];
+  [object debug: "attribute %s only applies to variadic functions", "'format'"];
+  [object debug: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [LogObject log: 2  message: "attribute only applies to variadic functions"];
+  [LogObject log: 2  message: "attribute %s only applies to variadic functions", "'format'"];
+  [LogObject log: 2  message: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [LogObject debug: "attribute only applies to variadic functions"];
+  [LogObject debug: "attribute %s only applies to variadic functions", "'format'"];
+  [LogObject debug: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+}
Index: testsuite/objc.dg/attributes/method-deprecated-1.m
===================================================================
--- testsuite/objc.dg/attributes/method-deprecated-1.m	(revision 0)
+++ testsuite/objc.dg/attributes/method-deprecated-1.m	(revision 0)
@@ -0,0 +1,33 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) method;
+- (int) method;
++ (int) deprecatedClassMethod __attribute__((deprecated));
+- (int) deprecatedInstanceMethod __attribute__((deprecated));
+@end
+
+/* Test that deprecation warnings are produced, but not if the
+   receiver is of type 'id'.  */
+void foo (void)
+{
+  Class c;
+  id object;
+  MyClass *another_object;
+
+  [c method];
+  [object method];
+  [c deprecatedClassMethod];
+  [object deprecatedInstanceMethod];
+
+  [object method];
+  [another_object method];
+  [MyClass deprecatedClassMethod];           /* { dg-warning "is deprecated" } */
+  [another_object deprecatedInstanceMethod]; /* { dg-warning "is deprecated" } */ 
+}
Index: testsuite/objc.dg/attributes/method-deprecated-2.m
===================================================================
--- testsuite/objc.dg/attributes/method-deprecated-2.m	(revision 0)
+++ testsuite/objc.dg/attributes/method-deprecated-2.m	(revision 0)
@@ -0,0 +1,23 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) deprecatedClassMethod: (id)firstObject, ...    __attribute__((sentinel)) __attribute__((deprecated));
+- (int) deprecatedInstanceMethod: (id)firstobject, ... __attribute__((sentinel)) __attribute__((deprecated));
+@end
+
+/* Test that deprecation warnings are produced even if the method is
+   also marked with another attribute too (this is to test the
+   processing of multiple attributes).  */
+void foo (void)
+{
+  MyClass *object = nil;
+
+  [MyClass deprecatedClassMethod: object, nil];           /* { dg-warning "is deprecated" } */
+  [object deprecatedInstanceMethod: object, nil];         /* { dg-warning "is deprecated" } */ 
+}
Index: testsuite/objc.dg/attributes/method-attribute-2.m
===================================================================
--- testsuite/objc.dg/attributes/method-attribute-2.m	(revision 166103)
+++ testsuite/objc.dg/attributes/method-attribute-2.m	(working copy)
@@ -14,7 +14,7 @@
 @end
 
 @implementation obj
-- (int) depmth __attribute__((deprecated)) { return var; }  
+- (int) depmth __attribute__((deprecated)) { return var; }  /* { dg-warning "method attributes can not be specified in @implementation context" } */
 - (int) depmtharg:(int) iarg { return var + iarg ; }
 - (int) unusedarg:(int) __attribute__((unused)) uarg { return var; }
 - (int) depunusedarg:(int) __attribute__((unused)) uarg { return var; }
Index: testsuite/obj-c++.dg/attributes/method-deprecated-1.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-deprecated-1.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/method-deprecated-1.mm	(revision 0)
@@ -0,0 +1,33 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) method;
+- (int) method;
++ (int) deprecatedClassMethod __attribute__((deprecated));
+- (int) deprecatedInstanceMethod __attribute__((deprecated));
+@end
+
+/* Test that deprecation warnings are produced, but not if the
+   receiver is of type 'id'.  */
+void foo (void)
+{
+  Class c;
+  id object;
+  MyClass *another_object;
+
+  [c method];
+  [object method];
+  [c deprecatedClassMethod];
+  [object deprecatedInstanceMethod];
+
+  [object method];
+  [another_object method];
+  [MyClass deprecatedClassMethod];           /* { dg-warning "is deprecated" } */
+  [another_object deprecatedInstanceMethod]; /* { dg-warning "is deprecated" } */ 
+}
Index: testsuite/obj-c++.dg/attributes/method-deprecated-2.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-deprecated-2.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/method-deprecated-2.mm	(revision 0)
@@ -0,0 +1,23 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) deprecatedClassMethod: (id)firstObject, ...    __attribute__((sentinel)) __attribute__((deprecated));
+- (int) deprecatedInstanceMethod: (id)firstobject, ... __attribute__((sentinel)) __attribute__((deprecated));
+@end
+
+/* Test that deprecation warnings are produced even if the method is
+   also marked with another attribute too (this is to test the
+   processing of multiple attributes).  */
+void foo (void)
+{
+  MyClass *object = nil;
+
+  [MyClass deprecatedClassMethod: object, nil];           /* { dg-warning "is deprecated" } */
+  [object deprecatedInstanceMethod: object, nil];         /* { dg-warning "is deprecated" } */ 
+}
Index: testsuite/obj-c++.dg/attributes/method-attribute-2.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-attribute-2.mm	(revision 166103)
+++ testsuite/obj-c++.dg/attributes/method-attribute-2.mm	(working copy)
@@ -14,7 +14,7 @@
 @end
 
 @implementation obj
-- (int) depmth __attribute__((deprecated)) { return var; }  
+- (int) depmth __attribute__((deprecated)) { return var; }  /* { dg-warning "method attributes can not be specified in @implementation context" } */
 - (int) depmtharg:(int) iarg { return var + iarg ; }
 - (int) unusedarg:(int) __attribute__((unused)) uarg { return var; }
 - (int) depunusedarg:(int) __attribute__((unused)) uarg { return var; }
Index: testsuite/obj-c++.dg/attributes/method-noreturn-1.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-noreturn-1.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/method-noreturn-1.mm	(revision 0)
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface MyClass
+{
+  Class isa;
+} 
++ (id) method1 __attribute__ ((noreturn));
+- (id) method2 __attribute__ ((noreturn));
++ (id) method3 __attribute__ ((noreturn));
+- (id) method4 __attribute__ ((noreturn));
+@end
+
+@implementation MyClass
++ (id) method1
+{
+  return self;  /* { dg-warning "function declared .noreturn. has a .return. statement" } */
+}               /* { dg-warning ".noreturn. function does return" } */
+- (id) method2
+{
+  return self;  /* { dg-warning "function declared .noreturn. has a .return. statement" } */
+}               /* { dg-warning ".noreturn. function does return" } */
++ (id) method3
+{
+  abort ();
+}
+- (id) method4
+{
+  abort ();
+}
+@end
Index: testsuite/obj-c++.dg/attributes/method-sentinel-1.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-sentinel-1.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/method-sentinel-1.mm	(revision 0)
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface NSArray
+{
+  Class isa;
+} 
++ (id) arrayWithObject: (id)object __attribute__ ((sentinel));            /* { dg-warning "attribute only applies to variadic functions" } */
++ (id) arrayWithObjects: (id)firstObject, ... __attribute__ ((sentinel));
+
+- (id) initWithObject: (id)object __attribute__ ((sentinel));            /* { dg-warning "attribute only applies to variadic functions" } */
+- (id) initWithObjects: (id)firstObject, ... __attribute__ ((sentinel));
+@end
+
+void test (id object)
+{
+  NSArray *array;
+
+  array = [NSArray arrayWithObject: object];
+  array = [NSArray arrayWithObjects: object, nil];
+  array = [NSArray arrayWithObjects: object, object, nil];
+  array = [NSArray arrayWithObjects: object];               /* { dg-warning "not enough variable arguments" } */
+  array = [NSArray arrayWithObjects: object, object];       /* { dg-warning "missing sentinel" } */
+
+  [array initWithObject: object];
+  [array initWithObjects: object, nil];
+  [array initWithObjects: object, object, nil];
+  [array initWithObjects: object];               /* { dg-warning "not enough variable arguments" } */
+  [array initWithObjects: object, object];       /* { dg-warning "missing sentinel" } */
+}
Index: testsuite/obj-c++.dg/attributes/method-format-1.mm
===================================================================
--- testsuite/obj-c++.dg/attributes/method-format-1.mm	(revision 0)
+++ testsuite/obj-c++.dg/attributes/method-format-1.mm	(revision 0)
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface LogObject
+{
+  Class isa;
+} 
++ (void) log: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2, 3)));
+- (void) log: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2, 3)));
+
++ (void) debug: (const char *) my_format, ...  __attribute__ ((format (printf, 1, 2)));
+- (void) debug: (const char *) my_format, ...  __attribute__ ((format (printf, 1, 2)));
+
+/* Just make sure a missing or invalid attribute won't crash the compiler.  */
+- (void) log2: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (printf, 2)));    /* { dg-error "wrong" } */
++ (void) debug2: (const char *) my_format, ...  __attribute__ ((format (printf))); /* { dg-error "wrong" } */
+- (void) debug2: (const char *) my_format, ...  __attribute__ ((format (printf))); /* { dg-error "wrong" } */
++ (void) alert: (const char *) my_format __attribute__ ((format (printf, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+- (void) alert: (const char *) my_format __attribute__ ((format (printf, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+@end
+
+void test (LogObject *object)
+{
+  [object log: 2  message: "attribute only applies to variadic functions"];
+  [object log: 2  message: "attribute %s only applies to variadic functions", "'format'"];
+  [object log: 2  message: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [object debug: "attribute only applies to variadic functions"];
+  [object debug: "attribute %s only applies to variadic functions", "'format'"];
+  [object debug: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [LogObject log: 2  message: "attribute only applies to variadic functions"];
+  [LogObject log: 2  message: "attribute %s only applies to variadic functions", "'format'"];
+  [LogObject log: 2  message: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [LogObject debug: "attribute only applies to variadic functions"];
+  [LogObject debug: "attribute %s only applies to variadic functions", "'format'"];
+  [LogObject debug: "attribute %s only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+}
