diff mbox

libobjc - fixed initializing protocols and tests for modern Objective-C API

Message ID 1287139146.924112944@192.168.2.230
State New
Headers show

Commit Message

Nicola Pero Oct. 15, 2010, 10:39 a.m. UTC
This patch includes two testcases, one testing all the new protocol_xxx API functions, and the other one testing all the new sel_xxx API functions.  I have about 8 testcases which will test all the functions in the new API in alphabetical order.  This batch commits the first two.  :-)

The testcases were very useful because they found a number of bugs.  First of all, I had to fix a typo in a function declaration (for sel_xxx functions) but then I also had to revamp how protocol static instances are initialied (for the protocol_xxx functions).

The initialization of static protocol instances was really unfinished in the GNU Objective-C runtime and the only reason nobody reported it is (IMO) because in my experience nobody actually inspects the list of methods implemented by a protocol at runtime (but we need it to properly and completely support the new API and it could actually be very useful; I'm happy to have fixed it). :-)

Committed to trunk.

Thanks

In gcc/testsuite/:
2010-10-15  Nicola Pero  <nicola.pero@meta-innovation.com>

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

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

        * init.c (__objc_init_protocol): New function which fixes up a
        protocol's class pointer, registers it with the runtime, register
        all protocol selectors and registers associated protocols too.
        (objc_init_statics): Detect if we are initializing protocols, and
        if so, use __objc_init_protocol instead of only fixing up the
        class pointer.
        (__objc_init_protocls): Use __objc_init_protocol.
        * objc-private/module-abi-8.h: Updated comments.
        * objc-private/runtime.h
        (__objc_register_selectors_from_description_list): New.
        * selector.c (__objc_register_selectors_from_description_list):
        New.  (struct objc_method_description_list): Declare.
        * Protocol.m ([-descriptionForInstanceMethod:]): Use sel_get_name
        when accessing the name of a method, which is now correctly a SEL.
        ([-descriptionForClassMethod:]): Same change.
        * protocols.c (protocol_getMethodDescription): Same change.
        * objc/runtime.h: Updated comments.
        (sel_registerTypedName): Fixed typo in function name.

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165498)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2010-10-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc.dg/gnu-api-2-protocol.m: New.
+	* objc.dg/gnu-api-2-sel.m: New.
+
 2010-10-15  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
        * g++.dg/torture/stackalign/eh-vararg-2.C: Fix dg-options for
Index: objc.dg/gnu-api-2-protocol.m
===================================================================
--- objc.dg/gnu-api-2-protocol.m	(revision 0)
+++ objc.dg/gnu-api-2-protocol.m	(revision 0)
@@ -0,0 +1,160 @@
+/* Test the Modern GNU Objective-C Runtime API.
+
+  This is test 'protocol', covering all functions starting with 'protocol'.  */
+
+/* { 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
+
+@protocol MyThirdProtocol <MySecondProtocol>
+- (id) setAnotherVariable: (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 protocol_conformsToProtocol ()...\n");
+  {
+    if (!protocol_conformsToProtocol (@protocol (MyProtocol),
+				      @protocol (MyProtocol)))
+      abort ();
+
+    if (!protocol_conformsToProtocol (@protocol (MyThirdProtocol),
+				      @protocol (MySecondProtocol)))
+      abort ();
+
+    if (protocol_conformsToProtocol (@protocol (MyProtocol),
+				     @protocol (MySecondProtocol)))
+      abort ();
+  }
+
+  printf ("Testing protocol_copyMethodDescriptionList ()...\n");
+  {
+    unsigned int count;
+    struct objc_method_description *list;
+
+    list = protocol_copyMethodDescriptionList (@protocol (MyThirdProtocol),
+					       YES, YES, &count);
+    
+    if (count != 1)
+      abort ();
+
+    if (strcmp (sel_getName (list[0].name), "setAnotherVariable:") != 0)
+      abort ();
+    
+    if (list[1].name != NULL  &&  list[1].types != NULL)
+      abort ();
+  }
+
+  /* TODO: Test new ABI (when available).  */
+  printf ("Testing protocol_copyPropertyList ()...\n");
+  {
+    unsigned int count;
+    Property *list;
+
+    list = protocol_copyPropertyList (@protocol (MyProtocol), &count);
+
+    if (count != 0  ||  list != NULL)
+      abort ();
+  }
+
+  printf ("Testing protocol_copyProtocolList ()...\n");
+  {
+    unsigned int count;
+    Protocol **list;
+
+    list = protocol_copyProtocolList (@protocol (MyThirdProtocol), &count);
+    
+    if (count != 1)
+      abort ();
+
+    if (strcmp (protocol_getName (list[0]), "MySecondProtocol") != 0)
+      abort ();
+    
+    if (list[1] != NULL)
+      abort ();
+  }
+
+  printf ("Testing protocol_getMethodDescription ()...\n");
+  {
+    struct objc_method_description description;
+
+    description = protocol_getMethodDescription (@protocol (MySecondProtocol),
+						 @selector (setVariable:),
+						 YES, YES);
+    if (description.name == NULL  &&  description.types == NULL)
+      abort ();
+
+    if (strcmp (sel_getName (description.name), "setVariable:") != 0)
+      abort ();
+  }
+
+  printf ("Testing protocol_getName ()...\n");
+  {
+    if (strcmp (protocol_getName (@protocol (MyProtocol)), "MyProtocol") != 0)
+      abort ();
+  }
+
+  /* TODO: Test new ABI (when available).  */
+  printf ("Testing protocol_getProperty ()...\n");
+  {
+    Property property;
+
+    property = protocol_getProperty (objc_getProtocol ("MyProtocol"), "someProperty",
+				     YES, YES);
+
+    if (property != NULL)
+      abort ();
+  }
+
+  printf ("Testing protocol_isEqual ()...\n");
+  {
+    if (!protocol_isEqual (@protocol (MyProtocol),
+			   @protocol (MyProtocol)))
+      abort ();
+
+    if (!protocol_isEqual (@protocol (MyProtocol),
+			   objc_getProtocol ("MyProtocol")))
+      abort ();
+  }
+
+  return 0;
+}
Index: objc.dg/gnu-api-2-sel.m
===================================================================
--- objc.dg/gnu-api-2-sel.m	(revision 0)
+++ objc.dg/gnu-api-2-sel.m	(revision 0)
@@ -0,0 +1,103 @@
+/* Test the Modern GNU Objective-C Runtime API.
+
+  This is test 'sel', covering all functions starting with 'sel'.  */
+
+/* { 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 sel_getName () ...\n");
+  {
+    if (strcmp (sel_getName (@selector (variable)), "variable") != 0)
+      abort ();
+
+    if (strcmp (sel_getName (NULL), "<null selector>") != 0)
+      abort ();
+  }
+
+  printf ("Testing sel_getType () ...\n");
+  {
+    /* Get a selector from a real class, so it has interesting
+       types.  */
+    Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
+					     @selector (variable));
+    
+    if (strcmp (sel_getType (method_getName (method)), method_getTypeEncoding (method)) != 0)
+      abort ();
+  }
+
+  printf ("Testing sel_getUid () ...\n");
+  {
+    if (strcmp (sel_getName (sel_getUid ("myMethod")), "myMethod") != 0)
+      abort ();
+  }
+
+  printf ("Testing sel_isEqual () ...\n");
+  {
+    if (! sel_isEqual (@selector (setVariable:), @selector (setVariable:)))
+      abort ();
+  }
+  
+  printf ("Testing sel_registerName () ...\n");
+  {
+    if (strcmp (sel_getName (sel_registerName ("myMethod")), "myMethod") != 0)
+      abort ();
+  }
+
+  printf ("Testing set_registerTypedName () ...\n");
+  {
+    const char *types = method_getTypeEncoding (class_getInstanceMethod 
+						(objc_getClass ("MySubClass"),
+						 @selector (variable)));
+    SEL selector = sel_registerTypedName ("aMethod", types);
+    
+    if (strcmp (sel_getName (selector), "aMethod") != 0)
+      abort ();
+
+    if (strcmp (sel_getType (selector), types) != 0)
+      abort ();
+  }
+
+  return 0;
+}
diff mbox

Patch

Index: init.c
===================================================================
--- init.c	(revision 165474)
+++ init.c	(working copy)
@@ -32,7 +32,9 @@  see the files COPYING3 and COPYING.RUNTIME respect
 #include "objc-private/objc-list.h" 
 #include "objc-private/runtime.h"
 #include "objc-private/objc-sync.h" /* For __objc_sync_init() */
-#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
+#include "objc-private/protocols.h" /* For __objc_protocols_init(),
+				       __objc_protocols_add_protocol()
+				       __objc_protocols_register_selectors() */
 
 /* The version number of this runtime.  This must match the number 
    defined in gcc (objc-act.c).  */
@@ -70,6 +72,9 @@  static void init_check_module_version (Module_t);
 /* Assign isa links to protos.  */
 static void __objc_init_protocols (struct objc_protocol_list *protos);
 
+/* Assign isa link to a protocol, and register it.  */
+static void __objc_init_protocol (struct objc_protocol *protocol);
+
 /* Add protocol to class.  */
 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
 
@@ -490,11 +495,27 @@  objc_init_statics (void)
 		 they were attached to classes or categories, and the
 		 class/category loading code automatically fixes them
 		 up), and some of them may not.  We really need to go
-		 through the whole list to be sure!  */
+		 through the whole list to be sure!  Protocols are
+		 also special because we want to register them and
+		 register all their selectors.  */
 	      id *inst;
 
-	      for (inst = &statics->instances[0]; *inst; inst++)
-		(*inst)->class_pointer = class;
+	      if (strcmp (statics->class_name, "Protocol") == 0)
+		{
+		  /* Protocols are special, because not only we want
+		     to fix up their class pointers, but we also want
+		     to register them and their selectors with the
+		     runtime.  */
+		  for (inst = &statics->instances[0]; *inst; inst++)
+		    __objc_init_protocol ((struct objc_protocol *)*inst);
+		}
+	      else
+		{
+		  /* Other static instances (typically constant strings) are
+		     easier as we just fix up their class pointers.  */
+		  for (inst = &statics->instances[0]; *inst; inst++)		  
+		    (*inst)->class_pointer = class;
+		}
 	    }
 	}
       if (module_initialized)
@@ -843,7 +864,50 @@  init_check_module_version (Module_t module)
     }
 }
 
+/* __objc_init_protocol must be called with __objc_runtime_mutex
+   already locked, and the "Protocol" class already registered.  */
 static void
+__objc_init_protocol (struct objc_protocol *protocol)
+{
+  static Class proto_class = 0;
+
+  if (! proto_class)
+    proto_class = objc_get_class ("Protocol");
+
+  if (((size_t)protocol->class_pointer) == PROTOCOL_VERSION)
+    {
+      /* Assign class pointer */
+      protocol->class_pointer = proto_class;
+      
+      /* Register all the selectors in the protocol with the runtime.
+	 This both registers the selectors with the right types, and
+	 it also fixes up the 'struct objc_method' structures inside
+	 the protocol so that each method_name (a char * as compiled
+	 by the compiler) is replaced with the appropriate runtime
+	 SEL.  */
+      if (protocol->class_methods)
+	__objc_register_selectors_from_description_list (protocol->class_methods);
+
+      if (protocol->instance_methods)
+	__objc_register_selectors_from_description_list (protocol->instance_methods);
+
+      /* Register the protocol in the hashtable or protocols by
+	 name.  */
+      __objc_protocols_add_protocol (protocol->protocol_name, protocol);
+      
+      /* Init super protocols */
+      __objc_init_protocols (protocol->protocol_list);
+    }
+  else if (protocol->class_pointer != proto_class)
+    {
+      _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
+		   (int) ((char *) protocol->class_pointer
+			  - (char *) 0),
+		   PROTOCOL_VERSION);
+    }
+}
+
+static void
 __objc_init_protocols (struct objc_protocol_list *protos)
 {
   size_t i;
@@ -871,25 +935,7 @@  __objc_init_protocols (struct objc_protocol_list *
   for (i = 0; i < protos->count; i++)
     {
       struct objc_protocol *aProto = protos->list[i];
-      if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
-	{
-	  /* Assign class pointer */
-	  aProto->class_pointer = proto_class;
-
-	  /* Register the protocol in the hashtable or protocols by
-	     name.  */
-	  __objc_protocols_add_protocol (aProto->protocol_name, aProto);
-
-	  /* Init super protocols */
-	  __objc_init_protocols (aProto->protocol_list);
-	}
-      else if (protos->list[i]->class_pointer != proto_class)
-	{
-	  _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
-		       (int) ((char *) protos->list[i]->class_pointer
-			      - (char *) 0),
-		       PROTOCOL_VERSION);
-	}
+      __objc_init_protocol (aProto);
     }
 
   objc_mutex_unlock (__objc_runtime_mutex);
Index: objc-private/module-abi-8.h
===================================================================
--- objc-private/module-abi-8.h	(revision 165474)
+++ objc-private/module-abi-8.h	(working copy)
@@ -115,13 +115,15 @@  struct objc_ivar_list
    problem is a singly linked list of methods.  */
 struct objc_method
 {
-  SEL         method_name;  /* This variable is the method's name.  It
-			       is a char*.  The unique integer passed
-			       to objc_msg_send is a char* too.  It is
-			       compared against method_name using
-			       strcmp. */
+  SEL         method_name;  /* This variable is the method's name.
+			       The compiler puts a char* here, and
+			       it's replaced by a real SEL at runtime
+			       when the method is registered.  */
   const char* method_types; /* Description of the method's parameter
-			       list.  Useful for debuggers. */
+			       list.  Used when registering the
+			       selector with the runtime.  When that
+			       happens, method_name will contain the
+			       method's parameter list.  */
   IMP         method_imp;   /* Address of the method in the
 			       executable. */
 };
@@ -139,7 +141,12 @@  struct objc_method_list
 };
 
 /* Currently defined in Protocol.m (that definition should go away
-   once we include this file).  */
+   once we include this file).  Note that a 'struct
+   objc_method_description' as embedded inside a Protocol uses the
+   same trick as a 'struct objc_method': the method_name is a 'char *'
+   according to the compiler, who puts the method name as a string in
+   there.  At runtime, the selectors need to be registered, and the
+   method_name then becomes a SEL.  */
 struct objc_method_description_list
 {
   int count;
Index: objc-private/runtime.h
===================================================================
--- objc-private/runtime.h	(revision 165474)
+++ objc-private/runtime.h	(working copy)
@@ -60,6 +60,8 @@  extern void __objc_install_premature_dtable(Class)
 extern void __objc_resolve_class_links(void);  /* (objc-class.c) */
 extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
 extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */
+extern void __objc_register_selectors_from_description_list
+(struct objc_method_description_list *method_list); /* (selector.c) */
 extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
 
 extern int  __objc_init_thread_system(void);    /* thread.c */
Index: Protocol.m
===================================================================
--- Protocol.m	(revision 165474)
+++ Protocol.m	(working copy)
@@ -85,7 +85,7 @@  struct objc_method_description_list {
   if (instance_methods)
     for (i = 0; i < instance_methods->count; i++)
       {
-	if (!strcmp ((char*)instance_methods->list[i].name, name))
+	if (!strcmp (sel_get_name (instance_methods->list[i].name), name))
 	  return &(instance_methods->list[i]);
       }
 
@@ -113,7 +113,7 @@  struct objc_method_description_list {
   if (class_methods)
     for (i = 0; i < class_methods->count; i++)
       {
-	if (!strcmp ((char*)class_methods->list[i].name, name))
+	if (!strcmp (sel_get_name (class_methods->list[i].name), name))
 	  return &(class_methods->list[i]);
       }
 
Index: selector.c
===================================================================
--- selector.c	(revision 165474)
+++ selector.c	(working copy)
@@ -95,7 +95,41 @@  __objc_register_selectors_from_list (MethodList_t
   objc_mutex_unlock (__objc_runtime_mutex);
 }
 
+/* Temporary definition while we include objc/objc-api.h instead of
+   objc-private/module-abi-8.h.  It should go away once we include
+   module-abi-8.h.  */
+struct objc_method_description_list
+{
+  int count;
+  struct objc_method_description list[1];
+};
 
+/* The same as __objc_register_selectors_from_list, but works on a
+   struct objc_method_description_list* instead of a struct
+   objc_method_list*.  This is only used for protocols, which have
+   lists of method descriptions, not methods.
+   */
+void
+__objc_register_selectors_from_description_list 
+(struct objc_method_description_list *method_list)
+{
+  int i = 0;
+  
+  objc_mutex_lock (__objc_runtime_mutex);
+  while (i < method_list->count)
+    {
+      struct objc_method_description *method = &method_list->list[i];
+      if (method->name)
+	{
+	  method->name
+	    = __sel_register_typed_name ((const char *) method->name,
+					 method->types, 0, YES);
+	}
+      i += 1;
+    }
+  objc_mutex_unlock (__objc_runtime_mutex);
+}
+
 /* Register instance methods as class methods for root classes */
 void __objc_register_instance_methods_to_class (Class class)
 {
Index: protocols.c
===================================================================
--- protocols.c	(revision 165474)
+++ protocols.c	(working copy)
@@ -383,7 +383,7 @@  struct objc_method_description protocol_getMethodD
     {
       for (i = 0; i < methods->count; i++)
 	{
-	  if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
+	  if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
 	    return methods->list[i];
 	}
     }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165474)
+++ ChangeLog	(working copy)
@@ -1,3 +1,24 @@ 
+2010-10-14  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* init.c (__objc_init_protocol): New function which fixes up a
+	protocol's class pointer, registers it with the runtime, register
+	all protocol selectors and registers associated protocols too.
+	(objc_init_statics): Detect if we are initializing protocols, and
+	if so, use __objc_init_protocol instead of only fixing up the
+	class pointer.
+	(__objc_init_protocls): Use __objc_init_protocol.
+	* objc-private/module-abi-8.h: Updated comments.
+	* objc-private/runtime.h
+	(__objc_register_selectors_from_description_list): New.
+	* selector.c (__objc_register_selectors_from_description_list):
+	New.  (struct objc_method_description_list): Declare.
+	* Protocol.m ([-descriptionForInstanceMethod:]): Use sel_get_name
+	when accessing the name of a method, which is now correctly a SEL.
+	([-descriptionForClassMethod:]): Same change.
+	* protocols.c (protocol_getMethodDescription): Same change.
+	* objc/runtime.h: Updated comments.
+	(sel_registerTypedName): Fixed typo in function name.
+	
 2010-10-13  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	PR libobjc/23214
Index: objc/runtime.h
===================================================================
--- objc/runtime.h	(revision 165474)
+++ objc/runtime.h	(working copy)
@@ -195,7 +195,7 @@  objc_EXPORT SEL sel_registerName (const char *name
    Compatibility Note: the Apple/NeXT runtime has untyped selectors,
    so it does not have this function, which is specific to the GNU
    Runtime.  */
-objc_EXPORT SEL set_registerTypedName (const char *name, const char *type);
+objc_EXPORT SEL sel_registerTypedName (const char *name, const char *type);
 
 /* Return YES if first_selector is the same as second_selector, and NO
    if not.  */
@@ -505,7 +505,7 @@  objc_EXPORT Method * class_copyMethodList (Class c
 objc_EXPORT unsigned int method_getNumberOfArguments (Method method);
 
 /* Return the string encoding for the return type of method 'method'.
-   The string is a standard NULL-terminated string in an area of
+   The string is a standard zero-terminated string in an area of
    memory allocated with malloc(); you should free it with free() when
    you finish using it.  Return an empty string if method is NULL.  */
 objc_EXPORT char * method_copyReturnType (Method method);
@@ -513,7 +513,7 @@  objc_EXPORT char * method_copyReturnType (Method m
 /* Return the string encoding for the argument type of method
    'method', argument number 'argumentNumber' ('argumentNumber' is 0
    for self, 1 for _cmd, and 2 or more for the additional arguments if
-   any).  The string is a standard NULL-terminated string in an area
+   any).  The string is a standard zero-terminated string in an area
    of memory allocated with malloc(); you should free it with free()
    when you finish using it.  Return an empty string if method is NULL
    or if 'argumentNumber' refers to a non-existing argument.  */
@@ -524,10 +524,10 @@  objc_EXPORT char * method_copyArgumentType (Method
    'returnValue' string, which is of size 'returnValueSize'.  No more
    than 'returnValueSize' characters are copied; if the encoding is
    smaller than 'returnValueSize', the rest of 'returnValue' is filled
-   with NULLs.  If it is bigger, it is truncated (and would not be
-   NULL-terminated).  You should supply a big enough
+   with zeros.  If it is bigger, it is truncated (and would not be
+   zero-terminated).  You should supply a big enough
    'returnValueSize'.  If the method is NULL, returnValue is set to a
-   string of NULLs.  */
+   string of zeros.  */
 objc_EXPORT void method_getReturnType (Method method, char *returnValue, 
 				       size_t returnValueSize);
 
@@ -538,10 +538,10 @@  objc_EXPORT void method_getReturnType (Method meth
    'returnValue' string, which is of size 'returnValueSize'.  No more
    than 'returnValueSize' characters are copied; if the encoding is
    smaller than 'returnValueSize', the rest of 'returnValue' is filled
-   with NULLs.  If it is bigger, it is truncated (and would not be
-   NULL-terminated).  You should supply a big enough
+   with zeros.  If it is bigger, it is truncated (and would not be
+   zero-terminated).  You should supply a big enough
    'returnValueSize'.  If the method is NULL, returnValue is set to a
-   string of NULLs.  */
+   string of zeros.  */
 objc_EXPORT void method_getArgumentType (Method method, unsigned int argumentNumber,
 					 char *returnValue, size_t returnValueSize);