From 828839869831f7b3426b1924cb29b837237d019f Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Thu, 23 Dec 2010 05:30:12 +0000 Subject: [PATCH] In gcc/testsuite/: 2010-12-23 Nicola Pero In gcc/testsuite/: 2010-12-23 Nicola Pero * obj-c.dg/gnu-api-2-class.m: Test that class_addMethod() returns NO if the method is already implemented in the class. * obj-c++.dg/gnu-api-2-class.mm: Same change. In libobjc/: 2010-12-23 Nicola Pero * sendmsg.c (class_addMethod): Return NO if the method already exists in the class. From-SVN: r168199 --- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm | 15 ++++++++ gcc/testsuite/objc.dg/gnu-api-2-class.m | 15 ++++++++ libobjc/ChangeLog | 5 +++ libobjc/sendmsg.c | 39 +++++++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 22b83bf6758..7f0c770145f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-12-23 Nicola Pero + + * obj-c.dg/gnu-api-2-class.m: Test that class_addMethod() returns + NO if the method is already implemented in the class. + * obj-c++.dg/gnu-api-2-class.mm: Same change. + 2010-12-22 Sebastian Pop PR tree-optimization/47019 diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm index d6aa827bc8d..da25663d171 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm @@ -140,6 +140,12 @@ int main () method_getTypeEncoding (method2))) abort (); + /* Test that if the method already exists in the class, + class_addMethod() returns NO. */ + if (class_addMethod (new_class, @selector (variable), method_getImplementation (method2), + method_getTypeEncoding (method2))) + abort (); + objc_registerClassPair (new_class); /* Now, MySubClass2 is basically the same as MySubClass! We'll @@ -152,6 +158,15 @@ int main () if ([o variable] != o) abort (); } + + /* Now, try that if you take an existing class and try to add an + already existing method, class_addMethod returns NO. This is + subtly different from before, when 'new_class' was still in + construction. Now it's a real class and the libobjc internals + differ between the two cases. */ + if (class_addMethod (new_class, @selector (variable), method_getImplementation (method2), + method_getTypeEncoding (method2))) + abort (); } std::cout << "Testing class_addProtocol ()...\n"; diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class.m b/gcc/testsuite/objc.dg/gnu-api-2-class.m index 5e0df7e81b1..d38d9c253dc 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-class.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-class.m @@ -140,6 +140,12 @@ int main(int argc, void **args) method_getTypeEncoding (method2))) abort (); + /* Test that if the method already exists in the class, + class_addMethod() returns NO. */ + if (class_addMethod (new_class, @selector (variable), method_getImplementation (method2), + method_getTypeEncoding (method2))) + abort (); + objc_registerClassPair (new_class); /* Now, MySubClass2 is basically the same as MySubClass! We'll @@ -152,6 +158,15 @@ int main(int argc, void **args) if ([o variable] != o) abort (); } + + /* Now, try that if you take an existing class and try to add an + already existing method, class_addMethod returns NO. This is + subtly different from before, when 'new_class' was still in + construction. Now it's a real class and the libobjc internals + differ between the two cases. */ + if (class_addMethod (new_class, @selector (variable), method_getImplementation (method2), + method_getTypeEncoding (method2))) + abort (); } printf ("Testing class_addProtocol ()...\n"); diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index d1521f94ce9..9922b53f709 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,8 @@ +2010-12-23 Nicola Pero + + * sendmsg.c (class_addMethod): Return NO if the method already + exists in the class. + 2010-12-22 Nicola Pero * init.c (duplicate_classes): New. diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c index 5192d161973..983dd78d455 100644 --- a/libobjc/sendmsg.c +++ b/libobjc/sendmsg.c @@ -759,6 +759,45 @@ class_addMethod (Class class_, SEL selector, IMP implementation, if (method_name == NULL) return NO; + /* If the method already exists in the class, return NO. It is fine + if the method already exists in the superclass; in that case, we + are overriding it. */ + if (CLS_IS_IN_CONSTRUCTION (class_)) + { + /* The class only contains a list of methods; they have not been + registered yet, ie, the method_name of each of them is still + a string, not a selector. Iterate manually over them to + check if we have already added the method. */ + struct objc_method_list * method_list = class_->methods; + while (method_list) + { + int i; + + /* Search the method list. */ + for (i = 0; i < method_list->method_count; ++i) + { + struct objc_method * method = &method_list->method_list[i]; + + if (method->method_name + && strcmp ((char *)method->method_name, method_name) == 0) + return NO; + } + + /* The method wasn't found. Follow the link to the next list of + methods. */ + method_list = method_list->method_next; + } + /* The method wasn't found. It's a new one. Go ahead and add + it. */ + } + else + { + /* Do the standard lookup. This assumes the selectors are + mapped. */ + if (search_for_method_in_list (class_->methods, selector)) + return NO; + } + method_list = (struct objc_method_list *)objc_calloc (1, sizeof (struct objc_method_list)); method_list->method_count = 1;