This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

objc.dg/method-2.m fix with the GNU runtime



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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]