From patchwork Fri Oct 15 10:39:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 67925 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 7DFE9B70E6 for ; Fri, 15 Oct 2010 21:39:40 +1100 (EST) Received: (qmail 14868 invoked by alias); 15 Oct 2010 10:39:38 -0000 Received: (qmail 14227 invoked by uid 22791); 15 Oct 2010 10:39:31 -0000 X-SWARE-Spam-Status: No, hits=0.1 required=5.0 tests=AWL, BAYES_50, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 15 Oct 2010 10:39:12 +0000 Received: from eggs.gnu.org ([140.186.70.92]:48317) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P6hgs-0003T7-1I for gcc-patches@gnu.org; Fri, 15 Oct 2010 06:39:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P6hgp-0007KP-UK for gcc-patches@gnu.org; Fri, 15 Oct 2010 06:39:10 -0400 Received: from smtp131.iad.emailsrvr.com ([207.97.245.131]:46566) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P6hgp-0007KK-QO for gcc-patches@gnu.org; Fri, 15 Oct 2010 06:39:07 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp43.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 14EB62D0509 for ; Fri, 15 Oct 2010 06:39:07 -0400 (EDT) X-Orig-To: gcc-patches@gnu.org Received: from dynamic1.wm-web.iad.mlsrvr.com (dynamic1.wm-web.iad1a.rsapps.net [192.168.2.150]) by smtp43.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 00A232D082E for ; Fri, 15 Oct 2010 06:39:06 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic1.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id E298BC98070 for ; Fri, 15 Oct 2010 06:39:06 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Fri, 15 Oct 2010 12:39:06 +0200 (CEST) Date: Fri, 15 Oct 2010 12:39:06 +0200 (CEST) Subject: libobjc - fixed initializing protocols and tests for modern Objective-C API From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1287139146.924112944@192.168.2.230> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * objc.dg/gnu-api-2-protocol.m: New. * objc.dg/gnu-api-2-sel.m: New. In libobjc/: 2010-10-15 Nicola Pero * 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 + + * objc.dg/gnu-api-2-protocol.m: New. + * objc.dg/gnu-api-2-sel.m: New. + 2010-10-15 Ramana Radhakrishnan * 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 +#include +#include +#include + +@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 +- (id) setAnotherVariable: (id)value; +@end + +@interface MySubClass : MyRootClass +{ 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 +#include +#include +#include + +@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 +{ 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), "") != 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; +} 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 + + * 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 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);