This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: objc.dg/method-2.m fix with the GNU runtime
- To: Nicola Pero <n dot pero at mi dot flashnet dot it>
- Subject: Re: objc.dg/method-2.m fix with the GNU runtime
- From: Ziemowit Laski <zlaski at apple dot com>
- Date: Mon, 29 Oct 2001 11:30:48 -0800
- Cc: Stan Shebs <shebs at apple dot com>, Ovidiu Predescu <ovidiu at cup dot hp dot com>, gcc-patches at gcc dot gnu dot org
Thanks! I'll makes sure to test out your two new testcases with
the NeXT runtime as soon as they appear in the mainline.
--Zem
On Friday, October 26, 2001, at 11:48 , Nicola Pero wrote:
>
> Hi,
>
> here is a patch which fixes the objc.dg/method-2.m testcase with the GNU
> runtime (I think adapting/porting what was done by apple for the next
> runtime).
>
> One comment on the fix so it's recorded on the mailing list - the fix
> statically types `self' in a class method to be the class the method is
> part of. This maximes error checking in normal situations, but gets in
> the way if you want to redefine self in a class method to be something
> else. But in that case, you can still get the old behaviour of having
> self to be untyped id by simply casting self to id.
>
> I wrote some testcases while playing with it, I'd like to commit the
> following two -
>
> objc/class_self-1.m: brings the problem of having an untyped self to the
> extreme consequences - an instance method of an unrelated class - with a
> different signature - is picked up by the compiler instead of the
> intended
> class method, and that causes compilation to fail. fixed by the patch.
>
> objc/class_self-2.m: is the case in which the new compiler code requires
> you to use a cast. self is redefined to be another class, so you have
> to
> cast it to an id to have it compile. This testcase is not failing, but
> I'd like to add it anyway to make sure we don't break it in the future.
>
> Ok to commit the new two testcases and apply the patch ?
>
> gcc/gcc/ChangeLog:
> ==================
>
> Fri Oct 26 07:42:53 2001 Nicola Pero <n.pero@mi.flashnet.it>
>
> * objc/objc-act.c (finish_message_expr): For the GNU runtime: when
> determining the type of the receiver, do not check that TREE_CODE
> of receiver is CALL_EXPR before calling receiver_is_class_object
> (). (receiver_is_class_object): For the GNU runtime: recognize
> the case that the receiver is self in a class method context.
> Check that TREE_CODE of receiver is CALL_EXPR when checking that
> the receiver is a call to objc_get_class.
>
> Index: objc-act.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
> retrieving revision 1.99
> diff -u -r1.99 objc-act.c
> --- objc-act.c 2001/10/21 21:03:48 1.99
> +++ objc-act.c 2001/10/27 12:18:56
> @@ -4710,14 +4710,16 @@
> {
> tree chain, exp, arg;
>
> + /* The receiver is 'self' in the context of a class method. */
> + if (objc_method_context
> + && receiver == self_decl
> + && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
> + {
> + return CLASS_NAME (objc_implementation_context);
> + }
> +
> if (flag_next_runtime)
> {
> - /* The receiver is 'self' in the context of a class method. */
> - if (objc_method_context
> - && receiver == self_decl
> - && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
> - return CLASS_NAME (objc_implementation_context);
> -
> /* The receiver is a variable created by
> build_class_reference_decl. */
> if (TREE_CODE (receiver) == VAR_DECL
> @@ -4731,7 +4733,8 @@
> {
> /* 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. */
> - if ((exp = TREE_OPERAND (receiver, 0))
> + if (TREE_CODE (receiver) == CALL_EXPR
> + && (exp = TREE_OPERAND (receiver, 0))
> && TREE_CODE (exp) == ADDR_EXPR
> && (exp = TREE_OPERAND (exp, 0))
> && TREE_CODE (exp) == FUNCTION_DECL
> @@ -4844,8 +4847,8 @@
> && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
> statically_typed = 1;
> else if ((flag_next_runtime
> - || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
> - && (class_ident = receiver_is_class_object (receiver)))
> + || (IS_ID (rtype)
> + && (class_ident = receiver_is_class_object (receiver)))))
> ;
> else if (! IS_ID (rtype)
> /* Allow any type that matches objc_class_type. */
> @@ -5022,9 +5025,9 @@
>
> /* We think we have an instance...loophole: extern id Object; */
> hsh = hash_lookup (nst_method_hash_list, sel_name);
> +
> if (!hsh)
> - /* For various loopholes, like sending messages to self in a
> - factory context. */
> + /* For various loopholes */
> hsh = hash_lookup (cls_method_hash_list, sel_name);
>
> method_prototype = check_duplicates (hsh);
>
> gcc/gcc/testsuite/ChangeLog:
> ============================
>
> Fri Oct 26 09:02:07 2001 Nicola Pero <n.pero@mi.flashnet.it>
>
> * objc/execute/class_self-1.m: New test.
> * objc/execute/class_self-2.m: New test.
>
> gcc/gcc/testsuite/objc/execute/class_self-1.m:
> ==============================================
> /* Contributed by Nicola Pero - Fri Oct 26 22:39:32 BST 2001 */
> #include <objc/objc.h>
>
> /* Test calling a class method when there is an instance method
> with conflicting types */
>
> /* This class should be unused but on broken compilers its instance
> method might get picked up and used instead of the class method of
> another class ! */
> struct d
> {
> int a;
> };
>
> @interface UnusedClass
> {
> Class isa;
> }
> - (struct d) method;
> @end
>
> @implementation UnusedClass
> - (struct d) method
> {
> struct d u;
> u.a = 0;
>
> return u;
> }
> @end
>
> /* The real class */
> @interface TestClass
> {
> Class isa;
> }
> + (void) test;
> + (int) method;
> @end
>
> @implementation TestClass
> + (void) test
> {
> if ([self method] != 4)
> {
> abort ();
> }
> }
>
> + (int) method
> {
> return 4;
> }
> @end
>
>
> int main (void)
> {
> [TestClass test];
>
> return 0;
> }
>
> gcc/gcc/testsuite/objc/execute/class_self-2.m:
> ==============================================
> /* Contributed by Nicola Pero - Fri Oct 26 22:39:32 BST 2001 */
> #include <objc/objc.h>
>
> /* Test calling a class method on self where self has been redefined
> to be another class - the call requires a cast */
>
>
> /* The first class */
> struct d
> {
> int a;
> };
>
> @interface ClassA
> {
> Class isa;
> }
> + (Class) class;
> + (struct d) method;
> @end
>
> @implementation ClassA
> + (Class) class
> {
> return self;
> }
>
> + (struct d) method
> {
> struct d u;
> u.a = 5;
>
> return u;
> }
> @end
>
> /* The second class */
> @interface TestClass
> {
> Class isa;
> }
> + (void) test;
> @end
>
> @implementation TestClass
> + (void) test
> {
> self = [ClassA class];
>
>
> if ([(Class)self method].a != 5)
> {
> abort ();
> }
> }
>
> @end
>
>
> int main (void)
> {
> [TestClass test];
>
> return 0;
> }
>
>
--------------------------------------------------------------
Ziemowit Laski Apple Computer, Inc.
zlaski@apple.com 2 Infinite Loop, MS 302-4SN
+1.408.974.6229 Fax .1344 Cupertino, CA 95014-2085