aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/obj-c++.dg/gnu-api-2-sel.mm22
-rw-r--r--gcc/testsuite/objc.dg/gnu-api-2-sel.m22
-rw-r--r--libobjc/ChangeLog6
-rw-r--r--libobjc/objc/runtime.h10
-rw-r--r--libobjc/selector.c35
6 files changed, 95 insertions, 6 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 213e9c2..fe2cedd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-02-28 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * 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 <kazu@codesourcery.com>
* 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 b00588c..ff50058 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 ()
{
@@ -134,6 +149,13 @@ int main ()
if (selector != NULL)
abort ();
+
+ /* Now try a selector with multiple, conflicting types. NULL
+ should be returned. */
+ selector = sel_getTypedSelector ("conflictingSelectorMethod");
+
+ if (selector != NULL)
+ abort ();
}
#endif
diff --git a/gcc/testsuite/objc.dg/gnu-api-2-sel.m b/gcc/testsuite/objc.dg/gnu-api-2-sel.m
index 9a6aef2..b71fdfa 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)
{
@@ -134,6 +149,13 @@ int main(int argc, void **args)
if (selector != NULL)
abort ();
+
+ /* Now try a selector with multiple, conflicting types. NULL
+ should be returned. */
+ selector = sel_getTypedSelector ("conflictingSelectorMethod");
+
+ if (selector != NULL)
+ abort ();
}
#endif
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index a9399e6..485d2a4 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,9 @@
+2011-02-28 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * 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 <rfm@gnu.org>
PR libobjc/47922
diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h
index 551c348..6e1f1ec 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 99efcf8..80d2d80 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. */