From 98ab0248600687a1a0df95fa2eed84ed170c405e Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Wed, 1 Jun 2011 09:30:18 +0000 Subject: [PATCH] In gcc/objc/: 2011-06-01 Nicola Pero In gcc/objc/: 2011-06-01 Nicola Pero * objc-act.c (objc_decl_method_attributes): Implement nonnull attribute for Objective-C methods. In gcc/testsuite/: 2011-06-01 Nicola Pero * 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 | 5 ++ gcc/objc/objc-act.c | 42 +++++++++++++++++ gcc/testsuite/ChangeLog | 5 ++ .../obj-c++.dg/attributes/method-nonnull-1.mm | 46 +++++++++++++++++++ .../objc.dg/attributes/method-nonnull-1.m | 46 +++++++++++++++++++ 5 files changed, 144 insertions(+) create mode 100644 gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm create mode 100644 gcc/testsuite/objc.dg/attributes/method-nonnull-1.m diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 0b8b595e63c..c52fcc3ff98 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2011-06-01 Nicola Pero + + * objc-act.c (objc_decl_method_attributes): Implement nonnull + attribute for Objective-C methods. + 2011-05-21 Nicola Pero * config-lang.in (gtfiles): Updated order of files to fix building diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 0e15fe55aa7..be65a534f1b 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f8eea2b32e6..3a0371bb486 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-06-01 Nicola Pero + + * objc.dg/attributes/method-nonnull-1.m: New test. + * obj-c++.dg/attributes/method-nonnull-1.mm: New test. + 2011-05-31 Tobias Burnus 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 index 00000000000..c554894b228 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/attributes/method-nonnull-1.mm @@ -0,0 +1,46 @@ +/* Contributed by Nicola Pero , May 2011. */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +#include +#include + +@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 index 00000000000..49003242d76 --- /dev/null +++ b/gcc/testsuite/objc.dg/attributes/method-nonnull-1.m @@ -0,0 +1,46 @@ +/* Contributed by Nicola Pero , May 2011. */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +#include +#include + +@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" } */ +} -- 2.30.2