From 68ade9e4e84617fd5c613618cfdc0cc1fa6d6d81 Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Mon, 28 Feb 2011 14:48:23 +0000 Subject: [PATCH] In libobjc/: 2011-02-28 Nicola Pero In libobjc/: 2011-02-28 Nicola Pero * selector.c (sel_getTypedSelector): Return NULL if there are multiple selectors with conflicting types. * objc/runtime.h (sel_getTypedSelector): Updated documentation. In gcc/testsuite/: 2011-02-28 Nicola Pero * objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return NULL in case of a selector with conflicting types. * obj-c++.dg/gnu-api-2-sel.mm: Same change. From-SVN: r170563 --- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm | 22 ++++++++++++++ gcc/testsuite/objc.dg/gnu-api-2-sel.m | 22 ++++++++++++++ libobjc/ChangeLog | 6 ++++ libobjc/objc/runtime.h | 10 ++++--- libobjc/selector.c | 35 +++++++++++++++++++++-- 6 files changed, 95 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 213e9c26613..fe2cedddfc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-02-28 Nicola Pero + + * objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return + NULL in case of a selector with conflicting types. + * obj-c++.dg/gnu-api-2-sel.mm: Same change. + 2011-02-28 Kazu Hirata * gcc.target/arm/vfp-ldmdbd.c, gcc.target/arm/vfp-ldmdbs.c, diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm index b00588c9360..ff50058566b 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm @@ -46,6 +46,21 @@ - (void) method { return; } @end +@interface ClassA : MyRootClass +- (id) conflictingSelectorMethod; +@end + +@implementation ClassA +- (id) conflictingSelectorMethod { return nil; } +@end + +@interface ClassB : MyRootClass +- (void) conflictingSelectorMethod; +@end + +@implementation ClassB +- (void) conflictingSelectorMethod { return; } +@end int main () { @@ -132,6 +147,13 @@ int main () untyped. */ selector = sel_getTypedSelector ("registered_with_no_types"); + if (selector != NULL) + abort (); + + /* Now try a selector with multiple, conflicting types. NULL + should be returned. */ + selector = sel_getTypedSelector ("conflictingSelectorMethod"); + if (selector != NULL) abort (); } diff --git a/gcc/testsuite/objc.dg/gnu-api-2-sel.m b/gcc/testsuite/objc.dg/gnu-api-2-sel.m index 9a6aef28262..b71fdfab48c 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-sel.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-sel.m @@ -46,6 +46,21 @@ - (void) method { return; } @end +@interface ClassA : MyRootClass +- (id) conflictingSelectorMethod; +@end + +@implementation ClassA +- (id) conflictingSelectorMethod { return nil; } +@end + +@interface ClassB : MyRootClass +- (void) conflictingSelectorMethod; +@end + +@implementation ClassB +- (void) conflictingSelectorMethod { return; } +@end int main(int argc, void **args) { @@ -132,6 +147,13 @@ int main(int argc, void **args) untyped. */ selector = sel_getTypedSelector ("registered_with_no_types"); + if (selector != NULL) + abort (); + + /* Now try a selector with multiple, conflicting types. NULL + should be returned. */ + selector = sel_getTypedSelector ("conflictingSelectorMethod"); + if (selector != NULL) abort (); } diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index a9399e6bea9..485d2a4b513 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,9 @@ +2011-02-28 Nicola Pero + + * selector.c (sel_getTypedSelector): Return NULL if there are + multiple selectors with conflicting types. + * objc/runtime.h (sel_getTypedSelector): Updated documentation. + 2011-02-28 Richard Frith-Macdonald PR libobjc/47922 diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h index 551c348d307..6e1f1ec36e8 100644 --- a/libobjc/objc/runtime.h +++ b/libobjc/objc/runtime.h @@ -226,14 +226,16 @@ objc_EXPORT SEL * sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors); /* Return a selector with name 'name' and a non-zero type encoding, if - any such selector is registered with the runtime. If there is no - such selector, NULL is returned. Return NULL if 'name' is NULL. + there is a single selector with a type, and with that name, + registered with the runtime. If there is no such selector, or if + there are multiple selectors with the same name but conflicting + types, NULL is returned. Return NULL if 'name' is NULL. This is useful if you have the name of the selector, and would really like to get a selector for it that includes the type encoding. Unfortunately, if the program contains multiple selector - with the same name but different types, sel_getTypedSelector - returns a random one of them, which may not be the right one. + with the same name but different types, sel_getTypedSelector can + not possibly know which one you need, and so will return NULL. Compatibility Note: the Apple/NeXT runtime has untyped selectors, so it does not have this function, which is specific to the GNU diff --git a/libobjc/selector.c b/libobjc/selector.c index 99efcf87e6c..80d2d800422 100644 --- a/libobjc/selector.c +++ b/libobjc/selector.c @@ -369,6 +369,7 @@ sel_getTypedSelector (const char *name) if (i != 0) { struct objc_list *l; + SEL returnValue = NULL; for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); l; l = l->tail) @@ -376,10 +377,40 @@ sel_getTypedSelector (const char *name) SEL s = (SEL) l->head; if (s->sel_types) { - objc_mutex_unlock (__objc_runtime_mutex); - return s; + if (returnValue == NULL) + { + /* First typed selector that we find. Keep it in + returnValue, but keep checking as we want to + detect conflicts. */ + returnValue = s; + } + else + { + /* We had already found a typed selectors, so we + have multiple ones. Double-check that they have + different types, just in case for some reason we + got duplicates with the same types. If so, it's + OK, we'll ignore the duplicate. */ + if (returnValue->sel_types == s->sel_types) + continue; + else if (sel_types_match (returnValue->sel_types, s->sel_types)) + continue; + else + { + /* The types of the two selectors are different; + it's a conflict. Too bad. Return NULL. */ + objc_mutex_unlock (__objc_runtime_mutex); + return NULL; + } + } } } + + if (returnValue != NULL) + { + objc_mutex_unlock (__objc_runtime_mutex); + return returnValue; + } } /* No typed selector found. Return NULL. */ -- 2.30.2