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]

Re: 3.0.1 PATCH: Avoid link failure of Objective-C testsuite on Solaris2/Intel



> In class-tests-1.h (test_instances), id object is created by
> class_create_instance(), which finally allocates a 4-byte (in the
> Solaris/Intel case) instance and returns its address.  This (object) is
> passed to object_is_class(), which casts object into a Class (i.e. struct
> objc_class *, where struct objc_class is much larger than 4 bytes), and
> tests (via CLS_ISCLASS) the info member to determine if _CLS_CLASS is set.

Looks like a bug in the Objective-C runtime ... should be testing
CLS_ISMETA on the class_pointer ...  thanks for spotting this out.


> But this test is completely bogus, 

No - the test is perfectly correct.

If you look into Object.m, for example, you will see that
class_create_instance() is used in the implementation of +alloc, and
object_is_class() is used in the implementation of -isClass, which means
that when you do

id object = [Object new];

if ([object isClass])
  {
     // ...     
  }

you are basically performing the same calls that the test does.  And no
matter what the internals or the functions, but of course this code is
correct and must work.  Btw, I just checked, and NSObject implements
-isClass in the same way, so we really want to fix object_is_class() if
it's broken.  object_is_meta_class has the same problem but it is never
used anywhere.


> since info never got initialized in the first place.  So it's completely 
> arbitrary if this test passes or not.

Yes - you seem to be right ...

Here is a complete patch fixing libobjc:

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/libobjc/ChangeLog,v
retrieving revision 1.63
diff -u -r1.63 ChangeLog
--- ChangeLog	2001/06/09 20:32:56	1.63
+++ ChangeLog	2001/07/02 11:40:46
@@ -1,3 +1,8 @@
+Mon Jul  2 10:45:36 2001  Nicola Pero  <nicola@brainstorm.co.uk>
+
+	* objc/objc-api.h (object_is_class), (object_is_meta_class):
+	Fixed.
+
 2001-06-09  Alexandre Oliva  <aoliva@redhat.com>, Stephen L Moshier  <moshier@mediaone.net>
 
 	* configure.in (AC_EXEEXT): Work around in case it expands to
Index: objc/objc-api.h
===================================================================
RCS file: /cvs/gcc/gcc/libobjc/objc/objc-api.h,v
retrieving revision 1.3
diff -u -r1.3 objc-api.h
--- objc-api.h	2001/01/03 08:49:34	1.3
+++ objc-api.h	2001/07/02 11:40:46
@@ -580,20 +580,23 @@
 static inline BOOL
 object_is_class(id object)
 {
-  return CLS_ISCLASS((Class)object);
+  return (object != nil)  &&  CLS_ISMETA (object->class_pointer);
 }
 
 static inline BOOL
 object_is_instance(id object)
 {
-  return (object!=nil)&&CLS_ISCLASS(object->class_pointer);
+  return (object != nil)  &&  CLS_ISCLASS (object->class_pointer);
 }
 
 static inline BOOL
 object_is_meta_class(id object)
 {
-  return CLS_ISMETA((Class)object);
+  return (object != nil)  
+    &&  !object_is_instance (object)  
+    &&  !object_is_class (object);
 }
+
 
 struct sarray* 
 objc_get_uninstalled_dtable(void);


and here is a new testcase object_is_class.m showing the bug in action.  
On my machine, the usual testcases pass before and after the patch, but
the following new testcase failed before the patch, and the patch fixes
it.  

/* Contributed by Nicola Pero - Mon Jul  2 11:03:26 BST 2001 */
#include <objc/objc.h>
#include <objc/objc-api.h>
#include <objc/Object.h>

/* This test demonstrate a failure in object_is_class which was fixed */

/* We allocate an object - but we also fill the memory after the object 
   with a sequence of 1 */
id allocate_object ()
{
  Class class = [Object class];

  /* Allocate an area of memory */
  id new_object = nil;
  
  /* Big enough to contain, say, ten objects */
  new_object = (id)(objc_malloc (sizeof (class->instance_size * 10)));
  
  if (new_object == nil)
    {
      printf ("Out of memory\n");
      abort ();
    }
  
  /* Now fill all this memory with 1 */
  memset (new_object, 1, class->instance_size * 10);
  
  /* Then use the beginning of that memory to store an object */
  memset (new_object, 0, class->instance_size);
  new_object->class_pointer = class;
  
  return new_object;
}


int main (void)
{
  /* Allocate an object (with the following memory containing 1s) */
  id new_object = allocate_object ();
  
  /* Now check that the object is not a class object */
  if (object_is_class (new_object))
    {
      printf ("object_is_class failed\n");
      abort ();
    }

  return 0;
}






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