This patch fixes libobjc/48177. I applied it to trunk. I'd like to apply this patch to the 4.6 branch too. Do I need permission from a Release Manager ? Can I get it ? :-)
It is a fairly obvious fix as selector types should generally be compared using sel_types_match() and not strcmp(). But note that this bug has been in libobjc forever; it never mattered much because the traditional API (the only one available before GCC 4.6) had a number of different functions for dealing with typed selectors, and gnustep-base (the main user of this API) was using some other function to do this and the problem wasn't visible. The modern API (recommended from GCC 4.6.0 onwards) has a more limited, and elegant, set of functions, and the code in gnustep-base would be massively simplified ... if only this bug wasn't in the way! :-( Due to this bug, gnustep-base actually has to forcefully use the traditional API in the middle of the modern API, which it does by copying some declarations from the traditional API and it's all quite horrible. Ideally, we'd fix this bug in trunk and in 4.6.1, so that once 4.6.1 is released, gnustep-base can remove the horrible hacks, simply use the Modern API, and just tell everyone running 4.6.0 to upgrade to 4.6.1 to get the fix. :-) So, OK to commit to the 4.6 branch too ? Thanks Index: libobjc/ChangeLog =================================================================== --- libobjc/ChangeLog (revision 174141) +++ libobjc/ChangeLog (working copy) @@ -1,3 +1,10 @@ +2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com> + + PR libobjc/48177 + * selector.c (__sel_register_typed_name): Use sel_types_match() + instead of strcmp() to compare selector types (Suggestion by + Richard Frith-Macdonald <r...@gnu.org>). + 2011-04-15 Rainer Orth <r...@cebitec.uni-bielefeld.de> PR libobjc/32037 Index: libobjc/selector.c =================================================================== --- libobjc/selector.c (revision 174138) +++ libobjc/selector.c (working copy) @@ -597,7 +597,7 @@ __sel_register_typed_name (const char *name, const return s; } } - else if (! strcmp (s->sel_types, types)) + else if (sel_types_match (s->sel_types, types)) { if (orig) { Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 174142) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,5 +1,10 @@ 2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com> + PR libobjc/48177 + * objc.dg/pr48177.m: New testcase. + +2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com> + PR objc/48187 * objc.dg/pr48187.m: New testcase. * obj-c++.dg/pr48187.mm: New testcase. Index: gcc/testsuite/objc.dg/pr48177.m =================================================================== --- gcc/testsuite/objc.dg/pr48177.m (revision 0) +++ gcc/testsuite/objc.dg/pr48177.m (revision 0) @@ -0,0 +1,35 @@ +/* Contributed by Nicola Pero <nicola.p...@meta-innovation.com>, May 2011. */ +/* { dg-do run } */ +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ + +#include <objc/runtime.h> +#include <stdlib.h> + +int main(int argc, void **args) +{ +#ifdef __GNU_LIBOBJC__ + /* This special test tests that, if you have a selector already + registered in the runtime with full type information, you can use + sel_registerTypedName() to get it even if you specify the type + with incorrect argframe information. This is helpful as + selectors generated by the compiler (which have correct argframe + information) are usually registered before hand-written ones + (which often have incorrect argframe information, but need the + correct one). + + Note that in this hand-written test, even the type information of + the first selector may be wrong (on this machine); but that's OK + as we'll never actually use the selectors. */ + SEL selector1 = sel_registerTypedName ("testMethod", "i8@0:4"); + SEL selector2 = sel_registerTypedName ("testMethod", "i8@8:8"); + + /* We compare the selectors using ==, not using sel_isEqual(). This + is because we are testing internals of the runtime and we know + that in the current implementation they should be identical if + the stuff is to work as expected. Don't do this at home. */ + if (selector1 != selector2) + abort (); +#endif + + return 0; +}