Patchwork ObjC/ObjC++ - finish off method attributes

login
register
mail settings
Submitter Nicola Pero
Date Oct. 31, 2010, 5:42 p.m.
Message ID <1288546960.234428318@192.168.2.229>
Download mbox | patch
Permalink /patch/69727/
State New
Headers show

Comments

Nicola Pero - Oct. 31, 2010, 5:42 p.m.
This patch implements the "format" and "noreturn" method attributes for Objective-C
and Objective-C++ methods.  It also fixes some warnings for "deprecated" attributes
and adds testcases for all the method attributes that we now support (deprecated,
format, noreturn and sentinel).

Ok to commit to trunk ?

Thanks

In gcc/c-family/:
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.

In gcc/objc/:
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.

In gcc/testsuite/:
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.
Nicola Pero - Oct. 31, 2010, 6:01 p.m.
I have just realized that I had missed the case of __attribute__ ((__deprecated__))
(as opposed to __attribute__ ((deprecated))).  This is a revised patch which 
fixes the problem.  A new testcase for that case is also included.  Apologies.

Ok to commit to trunk ?

Thanks

In gcc/c-family/:
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.

In gcc/objc/:
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.

In gcc/testsuite/:
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-deprecated-3.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-deprecated-3.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.
Mike Stump - Nov. 1, 2010, 5:01 p.m.
On Oct 31, 2010, at 11:01 AM, Nicola Pero wrote:
> I have just realized that I had missed the case of __attribute__ ((__deprecated__))
> (as opposed to __attribute__ ((deprecated))).  This is a revised patch which 
> fixes the problem.  A new testcase for that case is also included.  Apologies.
> 
> Ok to commit to trunk ?

Ok.

Patch

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" } */
+}