Patchwork =?UTF-8?Q?libobjc=20-=20more=20modern=20Objective-C=20runtime=20API=20(1?= =?UTF-8?Q?1)?=

login
register
mail settings
Submitter Nicola Pero
Date Oct. 16, 2010, 2:09 p.m.
Message ID <1287238165.765419778@192.168.2.227>
Download mbox | patch
Permalink /patch/68032/
State New
Headers show

Comments

Nicola Pero - Oct. 16, 2010, 2:09 p.m.
This patch fixes a problem where class_setSuperclass() and class_getInstanceVariable() wouldn't work for classes that had not been resolved by the runtime yet.

It also include a new testcase for all the new ivar_xxx functions.

Committed to trunk.

Thanks

In libobjc/:
2010-10-16  Nicola Pero  <nicola.pero@meta-innovation.com>

        * class.c (class_getSuperclass): Call __objc_resolve_class_links
        if the class is not resolved yet.
        * ivars.c (class_getInstanceVariable): Use class_getSuperclass.
     
In gcc/testsuite/:
2010-10-16  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc.dg/gnu-api-2-ivar.m: New.

Index: class.c
===================================================================
--- class.c	(revision 165525)
+++ class.c	(working copy)
@@ -500,7 +500,7 @@ objc_getClass (const char *name)
   
   if (class)
     return class;
-  
+
   if (__objc_get_unknown_class_handler)
     return (*__objc_get_unknown_class_handler) (name);
 
@@ -796,12 +796,24 @@ class_isMetaClass (Class class_)
   return CLS_ISMETA (class_);
 }
 
+/* Even inside libobjc it may be worth using class_getSuperclass
+   instead of accessing class_->super_class directly because it
+   resolves the class links if needed.  If you access
+   class_->super_class directly, make sure to deal with the situation
+   where the class is not resolved yet!  */
 Class
 class_getSuperclass (Class class_)
 {
   if (class_ == Nil)
     return Nil;
 
+  /* If the class is not resolved yet, super_class would point to a
+     string (the name of the super class) as opposed to the actual
+     super class.  In that case, we need to resolve the class links
+     before we can return super_class.  */
+  if (! CLS_ISRESOLV (class_))
+    __objc_resolve_class_links ();
+  
   return class_->super_class;
 }
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165533)
+++ ChangeLog	(working copy)
@@ -1,5 +1,11 @@
 2010-10-16  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* class.c (class_getSuperclass): Call __objc_resolve_class_links
+	if the class is not resolved yet.
+	* ivars.c (class_getInstanceVariable): Use class_getSuperclass.
+	
+2010-10-16  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* objc/runtime.h (class_getIvarLayout): New.
 	(class_getWeakIvarLayout): New.
 	(class_setIvarLayout): New.
Index: ivars.c
===================================================================
--- ivars.c	(revision 165533)
+++ ivars.c	(working copy)
@@ -53,7 +53,7 @@ class_getInstanceVariable (Class class_, const cha
 		    }
 		}
 	    }
-	  class_ = class_->super_class;
+	  class_ = class_getSuperclass (class_);
 	}
       objc_mutex_unlock (__objc_runtime_mutex);
     }

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165541)
+++ ChangeLog	(working copy)
@@ -1,3 +1,7 @@ 
+2010-10-16  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc.dg/gnu-api-2-ivar.m: New.
+
 2010-10-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc.dg/gnu-api-2-property.m: New.
Index: objc.dg/gnu-api-2-ivar.m
===================================================================
--- objc.dg/gnu-api-2-ivar.m	(revision 0)
+++ objc.dg/gnu-api-2-ivar.m	(revision 0)
@@ -0,0 +1,80 @@ 
+/* Test the Modern GNU Objective-C Runtime API.
+
+  This is test 'ivar', covering all functions starting with 'ivar'.  */
+
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+
+/* To get the modern GNU Objective-C Runtime API, you include
+   objc/runtime.h.  */
+#include <objc/runtime.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+@interface MyRootClass
+{ Class isa; }
++ alloc;
+- init;
+@end
+
+@implementation MyRootClass
++ alloc { return class_createInstance (self, 0); }
+- init  { return self; }
+@end
+
+@protocol MyProtocol
+- (id) variable;
+@end
+
+@protocol MySecondProtocol
+- (id) setVariable: (id)value;
+@end
+
+@interface MySubClass : MyRootClass <MyProtocol>
+{ id variable_ivar; }
+- (void) setVariable: (id)value;
+- (id) variable;
+@end
+
+@implementation MySubClass
+- (void) setVariable: (id)value { variable_ivar = value; }
+- (id) variable { return variable_ivar; }
+@end
+
+
+int main(int argc, void **args)
+{
+  /* Functions are tested in alphabetical order.  */
+
+  printf ("Testing ivar_getName () ...\n");
+  {
+    Ivar ivar = class_getInstanceVariable (objc_getClass ("MySubClass"),
+					   "variable_ivar");
+   if (strcmp (ivar_getName (ivar), "variable_ivar") != 0)
+      abort ();
+
+   ivar = class_getInstanceVariable (objc_getClass ("MySubClass"),
+				     "variable");
+   if (ivar != 0)
+      abort ();
+  }
+
+  printf ("Testing ivar_getOffset () ...\n");
+  {
+    Ivar ivar = class_getInstanceVariable (objc_getClass ("MyRootClass"),
+					   "isa");
+    if (ivar_getOffset (ivar) != 0)
+      abort ();
+  }
+
+  printf ("Testing ivar_getTypeEncoding () ...\n");
+  {
+    Ivar ivar = class_getInstanceVariable (objc_getClass ("MySubClass"),
+					   "variable_ivar");
+    if (strcmp (ivar_getTypeEncoding (ivar), "@") != 0)
+      abort ();
+  }
+
+  return 0;
+}