OSDN Git Service

In gcc/c-family/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 1 Nov 2010 22:54:35 +0000 (22:54 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 1 Nov 2010 22:54:35 +0000 (22:54 +0000)
2010-11-01  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-11-01  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-11-01  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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166153 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/attributes/method-attribute-2.mm
gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-attribute-2.m
gcc/testsuite/objc.dg/attributes/method-deprecated-1.m [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-deprecated-2.m [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-deprecated-3.m [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-format-1.m [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-noreturn-1.m [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-sentinel-1.m [new file with mode: 0644]

index cb5b5dc..b2c9011 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-01  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-31  Jason Merrill  <jason@redhat.com>
 
        * c-common.c (conversion_warning, warn_for_collisions_1): Use
index 923c63a..ab050ab 100644 (file)
@@ -5729,7 +5729,8 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   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 1e61291..e9e5592 100644 (file)
@@ -1,5 +1,21 @@
 2010-11-01  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-11-01  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        * objc-act.c (objc_maybe_build_component_ref): Warn about using
        deprecated properties.
        (objc_maybe_printable_name): Support PROPERTY_DECL.
index 68639ce..768215e 100644 (file)
@@ -1261,7 +1261,11 @@ objc_start_method_definition (bool is_class_method, tree decl, tree attributes)
   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,
@@ -6598,6 +6602,11 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector,
   /* 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;
 
@@ -6628,19 +6637,119 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector,
 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))
+       {
+         tree name = TREE_PURPOSE (attribute);
+         
+         if (is_attribute_p  ("deprecated", name)
+             || is_attribute_p ("sentinel", name)
+             || is_attribute_p ("noreturn", name))
+           {
+             /* An attribute that we support; add it to the filtered
+                attributes.  */
+             filtered_attributes = chainon (filtered_attributes, 
+                                            copy_node (attribute));
+           }
+         else if (is_attribute_p ("format", name))
+           {
+             /* "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, "%qE 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 
@@ -7149,6 +7258,26 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
          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;
@@ -7209,14 +7338,12 @@ build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
   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.  */
@@ -10636,6 +10763,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 ccace6f..ea07278 100644 (file)
@@ -1,5 +1,23 @@
 2010-11-01  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.        
+       
+2010-11-01  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        * objc.dg/property/at-property-deprecated-1.m: New.
        * obj-c++.dg/property/at-property-deprecated-1.mm: New. 
 
index f9a184c..4a56b3a 100644 (file)
@@ -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; }
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-1.mm
new file mode 100644 (file)
index 0000000..8343856
--- /dev/null
@@ -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" } */ 
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-2.mm
new file mode 100644 (file)
index 0000000..1e5d87f
--- /dev/null
@@ -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" } */ 
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm b/gcc/testsuite/obj-c++.dg/attributes/method-deprecated-3.mm
new file mode 100644 (file)
index 0000000..5c715a2
--- /dev/null
@@ -0,0 +1,21 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that __attribute__ ((__deprecated__)) works as well as __attribute__ ((deprecated)).  */
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) deprecatedClassMethod: (id)firstObject, ...    __attribute__((__deprecated__));
+- (int) deprecatedInstanceMethod: (id)firstobject, ... __attribute__((__deprecated__));
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+  [MyClass deprecatedClassMethod: object, nil];           /* { dg-warning "is deprecated" } */
+  [object deprecatedInstanceMethod: object, nil];         /* { dg-warning "is deprecated" } */ 
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-format-1.mm
new file mode 100644 (file)
index 0000000..0a078ff
--- /dev/null
@@ -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" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-noreturn-1.mm
new file mode 100644 (file)
index 0000000..af051a6
--- /dev/null
@@ -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
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-sentinel-1.mm
new file mode 100644 (file)
index 0000000..ecaa36c
--- /dev/null
@@ -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 f9a184c..4a56b3a 100644 (file)
@@ -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; }
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-1.m
new file mode 100644 (file)
index 0000000..8343856
--- /dev/null
@@ -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" } */ 
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-2.m
new file mode 100644 (file)
index 0000000..1e5d87f
--- /dev/null
@@ -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" } */ 
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m b/gcc/testsuite/objc.dg/attributes/method-deprecated-3.m
new file mode 100644 (file)
index 0000000..5c715a2
--- /dev/null
@@ -0,0 +1,21 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that __attribute__ ((__deprecated__)) works as well as __attribute__ ((deprecated)).  */
+@interface MyClass
+{
+  Class isa;
+} 
++ (int) deprecatedClassMethod: (id)firstObject, ...    __attribute__((__deprecated__));
+- (int) deprecatedInstanceMethod: (id)firstobject, ... __attribute__((__deprecated__));
+@end
+
+void foo (void)
+{
+  MyClass *object = nil;
+
+  [MyClass deprecatedClassMethod: object, nil];           /* { dg-warning "is deprecated" } */
+  [object deprecatedInstanceMethod: object, nil];         /* { dg-warning "is deprecated" } */ 
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-format-1.m b/gcc/testsuite/objc.dg/attributes/method-format-1.m
new file mode 100644 (file)
index 0000000..0a078ff
--- /dev/null
@@ -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" } */
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m b/gcc/testsuite/objc.dg/attributes/method-noreturn-1.m
new file mode 100644 (file)
index 0000000..af051a6
--- /dev/null
@@ -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
diff --git a/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m b/gcc/testsuite/objc.dg/attributes/method-sentinel-1.m
new file mode 100644 (file)
index 0000000..ecaa36c
--- /dev/null
@@ -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" } */
+}