From 419b55d0f9076bfa47c93b5899a83e953cee2d96 Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Sun, 5 Jun 2011 17:37:06 +0000 Subject: [PATCH] In gcc/objc/: 2011-06-05 Nicola Pero In gcc/objc/: 2011-06-05 Nicola Pero * objc-act.c (receiver_is_class_object): Expanded comment. (objc_finish_message_expr): Likewise. In gcc/testsuite/: 2011-06-05 Nicola Pero PR testsuite/49287 * objc.dg/gnu-api-2-class.m: Updated testcase silencing compiler warning. * objc.dg/gnu-api-2-objc.m: Likewise. * obj-c++.dg/gnu-api-2-class.mm: Likewise * obj-c++.dg/gnu-api-2-objc.mm: Likewise. From-SVN: r174657 --- gcc/objc/ChangeLog | 5 ++ gcc/objc/objc-act.c | 54 ++++++++++++++++++--- gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm | 4 +- gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm | 2 +- gcc/testsuite/objc.dg/gnu-api-2-class.m | 4 +- gcc/testsuite/objc.dg/gnu-api-2-objc.m | 2 +- 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 50c80b5c7cb..208decc7c86 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2011-06-05 Nicola Pero + + * objc-act.c (receiver_is_class_object): Expanded comment. + (objc_finish_message_expr): Likewise. + 2011-06-02 Nicola Pero PR objc/48539 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index e7acb7f05b1..321d52aaf28 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -5270,7 +5270,42 @@ receiver_is_class_object (tree receiver, int self, int super) return exp; /* The receiver is a function call that returns an id. Check if - it is a call to objc_getClass, if so, pick up the class name. */ + it is a call to objc_getClass, if so, pick up the class name. + + This is required by the GNU runtime, which compiles + + [NSObject alloc] + + into + + [objc_get_class ("NSObject") alloc]; + + and then, to check that the receiver responds to the +alloc + method, needs to be able to determine that the objc_get_class() + call returns the NSObject class and not just a generic Class + pointer. + + But, traditionally this is enabled for all runtimes, not just the + GNU one, which means that the compiler is smarter than you'd + expect when dealing with objc_getClass(). For example, with the + Apple runtime, in the code + + [objc_getClass ("NSObject") alloc]; + + the compiler will recognize the objc_getClass() call as special + (due to the code below) and so will know that +alloc is called on + the 'NSObject' class, and can perform the corresponding checks. + + Programmers can disable this behaviour by casting the results of + objc_getClass() to 'Class' (this may seem weird because + objc_getClass() is already declared to return 'Class', but the + compiler treats it as a special function). This may be useful if + the class is never declared, and the compiler would complain + about a missing @interface for it. Then, you can do + + [(Class)objc_getClass ("MyClassNeverDeclared") alloc]; + + to silence the warnings. */ if (TREE_CODE (receiver) == CALL_EXPR && (exp = CALL_EXPR_FN (receiver)) && TREE_CODE (exp) == ADDR_EXPR @@ -5478,13 +5513,16 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params, { /* If 'rtype' is NULL_TREE at this point it means that we have seen no @interface corresponding to that - class name, only a @class declaration. So, we have a - class name (class_tree) but no actual details of the - class methods. We won't be able to check that the - class responds to the method, and we will have to - guess the method prototype. Emit a warning, then - keep going (this will use any method with a matching - name, as if the receiver was of type 'Class'). */ + class name, only a @class declaration (alternatively, + this was a call such as [objc_getClass("SomeClass") + alloc], where we've never seen the @interface of + SomeClass). So, we have a class name (class_tree) + but no actual details of the class methods. We won't + be able to check that the class responds to the + method, and we will have to guess the method + prototype. Emit a warning, then keep going (this + will use any method with a matching name, as if the + receiver was of type 'Class'). */ warning (0, "@interface of class %qE not found", class_tree); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7194f87fac4..7fdb2ae2a1d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2011-06-05 Nicola Pero + + PR testsuite/49287 + * objc.dg/gnu-api-2-class.m: Updated testcase silencing compiler + warning. + * objc.dg/gnu-api-2-objc.m: Likewise. + * obj-c++.dg/gnu-api-2-class.mm: Likewise + * obj-c++.dg/gnu-api-2-objc.mm: Likewise. + 2011-06-05 Nicola Pero * objc.dg/gnu-api-2-objc.m: Fixed testcase. Use log2 of the 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 1e79e9b95c6..6dc9dd3733c 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm @@ -109,7 +109,7 @@ int main () objc_registerClassPair (new_class); { - MySubClass *o = [[objc_getClass ("MySubSubClass") alloc] init]; + MySubClass *o = [[(Class)objc_getClass ("MySubSubClass") alloc] init]; Ivar variable2 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable2_ivar"); Ivar variable3 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable3_ivar"); Ivar variable4 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable4_ivar"); @@ -178,7 +178,7 @@ int main () /* Now, MySubClass2 is basically the same as MySubClass! We'll use the variable and setVariable: methods on it. */ { - MySubClass *o = (MySubClass *)[[objc_getClass ("MySubClass2") alloc] init]; + MySubClass *o = (MySubClass *)[[(Class)objc_getClass ("MySubClass2") alloc] init]; [o setVariable: o]; diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm index ce70c5e434f..e5b1a69ed04 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-objc.mm @@ -93,7 +93,7 @@ int main () abort (); { - MySubClass *o = [[objc_getClass ("MyNewSubClass") alloc] init]; + MySubClass *o = [[(Class)objc_getClass ("MyNewSubClass") alloc] init]; if (object_getClass (o) != objc_getClass ("MyNewSubClass")) abort (); diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class.m b/gcc/testsuite/objc.dg/gnu-api-2-class.m index f3469f6ede8..f396a09fad8 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-class.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-class.m @@ -109,7 +109,7 @@ int main(int argc, void **args) objc_registerClassPair (new_class); { - MySubClass *o = [[objc_getClass ("MySubSubClass") alloc] init]; + MySubClass *o = [[(Class)objc_getClass ("MySubSubClass") alloc] init]; Ivar variable2 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable2_ivar"); Ivar variable3 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable3_ivar"); Ivar variable4 = class_getInstanceVariable (objc_getClass ("MySubSubClass"), "variable4_ivar"); @@ -178,7 +178,7 @@ int main(int argc, void **args) /* Now, MySubClass2 is basically the same as MySubClass! We'll use the variable and setVariable: methods on it. */ { - MySubClass *o = (MySubClass *)[[objc_getClass ("MySubClass2") alloc] init]; + MySubClass *o = (MySubClass *)[[(Class)objc_getClass ("MySubClass2") alloc] init]; [o setVariable: o]; diff --git a/gcc/testsuite/objc.dg/gnu-api-2-objc.m b/gcc/testsuite/objc.dg/gnu-api-2-objc.m index d1177d70e53..d65c120455e 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-objc.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-objc.m @@ -93,7 +93,7 @@ int main(int argc, void **args) abort (); { - MySubClass *o = [[objc_getClass ("MyNewSubClass") alloc] init]; + MySubClass *o = [[(Class)objc_getClass ("MyNewSubClass") alloc] init]; if (object_getClass (o) != objc_getClass ("MyNewSubClass")) abort (); -- 2.30.2