In gcc/objc/: 2011-06-01 Nicola Pero <nicola.pero@meta-innovation.com>
authorNicola Pero <nicola.pero@meta-innovation.com>
Wed, 1 Jun 2011 09:30:18 +0000 (09:30 +0000)
committerNicola Pero <nicola@gcc.gnu.org>
Wed, 1 Jun 2011 09:30:18 +0000 (09:30 +0000)
In gcc/objc/:
2011-06-01  Nicola Pero  <nicola.pero@meta-innovation.com>

* objc-act.c (objc_decl_method_attributes): Implement nonnull
attribute for Objective-C methods.

In gcc/testsuite/:
2011-06-01  Nicola Pero  <nicola.pero@meta-innovation.com>

* objc.dg/attributes/method-nonnull-1.m: New test.
* obj-c++.dg/attributes/method-nonnull-1.mm: New test.

From-SVN: r174520

gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/attributes/method-nonnull-1.m [new file with mode: 0644]

index 0b8b595e63cb7a85d69460e15a77279d03e7c1e3..c52fcc3ff98043b319fc9fcb0b37889c3d95ce36 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-01  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-act.c (objc_decl_method_attributes): Implement nonnull
+       attribute for Objective-C methods.
+
 2011-05-21  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * config-lang.in (gtfiles): Updated order of files to fix building
index 0e15fe55aa798d1ab52e456d285406b51bca4f03..be65a534f1bd0f8fcb774a40a21e041f61eaa98d 100644 (file)
@@ -5042,6 +5042,48 @@ objc_decl_method_attributes (tree *node, tree attributes, int flags)
              filtered_attributes = chainon (filtered_attributes,
                                             new_attribute);
            }
+         else if (is_attribute_p ("nonnull", name))
+           {
+             /* We need to fixup all the argument indexes by adding 2
+                for the two hidden arguments of an Objective-C method
+                invocation, similat to what we do above for the
+                "format" attribute.  */
+             /* FIXME: This works great in terms of implementing the
+                functionality, but the warnings that are produced by
+                nonnull do mention the argument index (while the
+                format ones don't).  For example, you could get
+                "warning: null argument where non-null required
+                (argument 3)".  Now in that message, "argument 3"
+                includes the 2 hidden arguments; it would be much
+                more friendly to call it "argument 1", as that would
+                be consistent with __attribute__ ((nonnnull (1))).
+                To do this, we'd need to have the C family code that
+                checks the arguments know about adding/removing 2 to
+                the argument index ... or alternatively we could
+                maybe store the "printable" argument index in
+                addition to the actual argument index ?  Some
+                refactoring is needed to do this elegantly.  */
+             tree new_attribute = copy_node (attribute);
+             tree argument = TREE_VALUE (attribute);
+             while (argument != NULL_TREE)
+               {
+                 /* Get the value of the argument and add 2.  */
+                 tree number = TREE_VALUE (argument);
+                 if (number
+                     && TREE_CODE (number) == INTEGER_CST
+                     && TREE_INT_CST_HIGH (number) == 0
+                     && TREE_INT_CST_LOW (number) != 0)
+                   {
+                     TREE_VALUE (argument)
+                       = build_int_cst (integer_type_node,
+                                        TREE_INT_CST_LOW (number) + 2);
+                   }
+                 argument = TREE_CHAIN (argument);
+               }
+
+             filtered_attributes = chainon (filtered_attributes,
+                                            new_attribute);
+           }
          else
            warning (OPT_Wattributes, "%qE attribute directive ignored", name);
        }
index f8eea2b32e6968cd542a542a0ce4dc4145d84430..3a0371bb4869fdc4c89b23cc1b937c872724b294 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-01  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc.dg/attributes/method-nonnull-1.m: New test.
+       * obj-c++.dg/attributes/method-nonnull-1.mm: New test.  
+
 2011-05-31  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/18918
diff --git a/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm b/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm
new file mode 100644 (file)
index 0000000..c554894
--- /dev/null
@@ -0,0 +1,46 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, May 2011.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface MyArray
+{
+  Class isa;
+} 
++ (void) addObject: (id)object __attribute__ ((nonnull));
+- (void) addObject: (id)object __attribute__ ((nonnull));
+
++ (void) insertObject: (id)object  atIndex: (size_t)index __attribute__ ((nonnull (1)));
+- (void) insertObject: (id)object  atIndex: (size_t)index __attribute__ ((nonnull (1)));
+
++ (void) insertObject: (id)object  atIndex: (size_t)index  andObject: (id)anotherObject  atIndex: (size_t)anotherIndex __attribute__ ((nonnull (1, 3)));
+- (void) insertObject: (id)object  atIndex: (size_t)index  andObject: (id)anotherObject  atIndex: (size_t)anotherIndex __attribute__ ((nonnull (1, 3)));
+
+/* Test the behaviour with invalid code.  */
++ (void) removeObject: (id)object __attribute__ ((nonnull (0))); /* { dg-error "out-of-range" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (0))); /* { dg-error "out-of-range" } */
+
++ (void) removeObject: (id)object __attribute__ ((nonnull (2))); /* { dg-error "out-of-range" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (2))); /* { dg-error "out-of-range" } */
+
++ (void) removeObjectAtIndex: (size_t)object __attribute__ ((nonnull (1))); /* { dg-error "non-pointer operand" } */
+- (void) removeObjectAtIndex: (size_t)object __attribute__ ((nonnull (1))); /* { dg-error "non-pointer operand" } */
+
++ (void) removeObject: (id)object __attribute__ ((nonnull (MyArray))); /* { dg-error "" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (MyArray))); /* { dg-error "" } */
+@end
+
+void test (MyArray *object)
+{
+  [object addObject: object];
+  [object addObject: nil]; /* { dg-warning "null argument where non-null required" } */
+
+  [object insertObject: object atIndex: 4];
+  [object insertObject: nil    atIndex: 4]; /* { dg-warning "null argument where non-null required" } */
+
+  [object insertObject: object atIndex: 2 andObject: object atIndex: 3];
+  [object insertObject: nil    atIndex: 2 andObject: object atIndex: 3]; /* { dg-warning "null argument where non-null required" } */
+  [object insertObject: object atIndex: 2 andObject: nil    atIndex: 3]; /* { dg-warning "null argument where non-null required" } */
+}
diff --git a/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m b/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m
new file mode 100644 (file)
index 0000000..4900324
--- /dev/null
@@ -0,0 +1,46 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, May 2011.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface MyArray
+{
+  Class isa;
+} 
++ (void) addObject: (id)object __attribute__ ((nonnull));
+- (void) addObject: (id)object __attribute__ ((nonnull));
+
++ (void) insertObject: (id)object  atIndex: (size_t)index __attribute__ ((nonnull (1)));
+- (void) insertObject: (id)object  atIndex: (size_t)index __attribute__ ((nonnull (1)));
+
++ (void) insertObject: (id)object  atIndex: (size_t)index  andObject: (id)anotherObject  atIndex: (size_t)anotherIndex __attribute__ ((nonnull (1, 3)));
+- (void) insertObject: (id)object  atIndex: (size_t)index  andObject: (id)anotherObject  atIndex: (size_t)anotherIndex __attribute__ ((nonnull (1, 3)));
+
+/* Test the behaviour with invalid code.  */
++ (void) removeObject: (id)object __attribute__ ((nonnull (0))); /* { dg-error "out-of-range" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (0))); /* { dg-error "out-of-range" } */
+
++ (void) removeObject: (id)object __attribute__ ((nonnull (2))); /* { dg-error "out-of-range" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (2))); /* { dg-error "out-of-range" } */
+
++ (void) removeObjectAtIndex: (size_t)object __attribute__ ((nonnull (1))); /* { dg-error "non-pointer operand" } */
+- (void) removeObjectAtIndex: (size_t)object __attribute__ ((nonnull (1))); /* { dg-error "non-pointer operand" } */
+
++ (void) removeObject: (id)object __attribute__ ((nonnull (MyArray))); /* { dg-error "invalid operand" } */
+- (void) removeObject: (id)object __attribute__ ((nonnull (MyArray))); /* { dg-error "invalid operand" } */
+@end
+
+void test (MyArray *object)
+{
+  [object addObject: object];
+  [object addObject: nil]; /* { dg-warning "null argument where non-null required" } */
+
+  [object insertObject: object atIndex: 4];
+  [object insertObject: nil    atIndex: 4]; /* { dg-warning "null argument where non-null required" } */
+
+  [object insertObject: object atIndex: 2 andObject: object atIndex: 3];
+  [object insertObject: nil    atIndex: 2 andObject: object atIndex: 3]; /* { dg-warning "null argument where non-null required" } */
+  [object insertObject: object atIndex: 2 andObject: nil    atIndex: 3]; /* { dg-warning "null argument where non-null required" } */
+}