From patchwork Fri Feb 25 00:48:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 84499 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 78EF7B7088 for ; Fri, 25 Feb 2011 11:48:29 +1100 (EST) Received: (qmail 5206 invoked by alias); 25 Feb 2011 00:48:27 -0000 Received: (qmail 5194 invoked by uid 22791); 25 Feb 2011 00:48:23 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_00, 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, 25 Feb 2011 00:48:14 +0000 Received: from eggs.gnu.org ([140.186.70.92]:38595) by fencepost.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1Pslqu-0001Nn-EG for gcc-patches@gnu.org; Thu, 24 Feb 2011 19:48:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pslqr-0005rx-Vo for gcc-patches@gnu.org; Thu, 24 Feb 2011 19:48:12 -0500 Received: from smtp181.iad.emailsrvr.com ([207.97.245.181]:59251) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pslqr-0005rt-Ph for gcc-patches@gnu.org; Thu, 24 Feb 2011 19:48:09 -0500 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp38.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id CF48B348469 for ; Thu, 24 Feb 2011 19:48:08 -0500 (EST) Received: by smtp38.relay.iad1a.emailsrvr.com (Authenticated sender: nicola.pero-AT-meta-innovation.com) with ESMTPA id 056F7348393 for ; Thu, 24 Feb 2011 19:48:07 -0500 (EST) Message-Id: From: Nicola Pero To: gcc-patches@gnu.org Mime-Version: 1.0 (Apple Message framework v936) Subject: ObjC/ObjC++: Fix property encoding on Apple Date: Fri, 25 Feb 2011 00:48:07 +0000 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 207.97.245.181 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 removes another big FIXME that was introduced with the last big ObjC patch, which is the fact that the property encoding is not working. This patch fixes it. The patch includes two testcases. I ran them manually a few times on an Apple 32-bit with the stock Apple compiler to study the output and make sure the output of our own compiler matches the output of the stock compiler. At the moment, the testcases are conditional on #ifdef __OBJC2__, which currently means only Apple 64-bit with the NeXT runtime (ABI 2). In the future, it will also mean the GNU runtime (when a new ABI is implemented). It would be nice to run these (and many/all other!) testcases with -fobjc-abi-version=1 on Apple, but that is a separate change/rework of the ObjC testsuite. Ok to commit ? Thanks PS: I tested on Apple m32. I don't have an Apple m64. I'd be grateful if someone could try out the patch on there before I commit to confirm that it all looks good there. Thank! :-) { /* The Apple/NeXT runtime seems to crash on the following. */ @@ -68,6 +79,22 @@ int main () if (property_getName (NULL) != NULL) abort (); #endif + + /* The GNU runtime doesn't support looking up properties at + runtime yet. */ +#ifdef __OBJC2__ + { + objc_property_t property; + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyA"); + if (std::strcmp (property_getName (property), "propertyA") != 0) + abort (); + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyB"); + if (std::strcmp (property_getName (property), "propertyB") != 0) + abort (); + } +#endif } return (0); Index: objc/ChangeLog =================================================================== --- objc/ChangeLog (revision 170464) +++ objc/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2011-02-25 Nicola Pero + + * objc-act.c (objc_v2_encode_prop_attr): Rewritten. + 2011-02-23 Nicola Pero * objc-act.c (build_private_template): Do not copy the @@ -16,7 +20,8 @@ 2011-02-21 Mike Stump - * Make-lang.in (check_objc_parallelize): Refine for 4 processor machines. + * Make-lang.in (check_objc_parallelize): Refine for 4 processor + machines. 2011-02-20 Nicola Pero Index: objc/objc-act.c =================================================================== --- objc/objc-act.c (revision 170464) +++ objc/objc-act.c (working copy) @@ -10495,47 +10495,79 @@ encode_field_decl (tree field_decl, int kPropertyGetter = 'G', kPropertySetter = 'S', kPropertyInstanceVariable = 'V', - kPropertyType = 't', + kPropertyType = 'T', kPropertyWeak = 'W', - kPropertyStrong = 'S', + kPropertyStrong = 'P', kPropertyNonAtomic = 'N' - }; - - FIXME: Update the implementation to match. */ + }; */ tree objc_v2_encode_prop_attr (tree property) { const char *string; tree type = TREE_TYPE (property); - obstack_1grow (&util_obstack, 't'); + + obstack_1grow (&util_obstack, 'T'); encode_type (type, obstack_object_size (&util_obstack), OBJC_ENCODE_INLINE_DEFS); + if (PROPERTY_READONLY (property)) - obstack_grow (&util_obstack, ",r", 2); + obstack_grow (&util_obstack, ",R", 2); + + switch (PROPERTY_ASSIGN_SEMANTICS (property)) + { + case OBJC_PROPERTY_COPY: + obstack_grow (&util_obstack, ",C", 2); + break; + case OBJC_PROPERTY_RETAIN: + obstack_grow (&util_obstack, ",&", 2); + break; + case OBJC_PROPERTY_ASSIGN: + default: + break; + } - if (PROPERTY_ASSIGN_SEMANTICS (property) == OBJC_PROPERTY_COPY) - obstack_grow (&util_obstack, ",c", 2); + if (PROPERTY_DYNAMIC (property)) + obstack_grow (&util_obstack, ",D", 2); - if (PROPERTY_GETTER_NAME (property)) + if (PROPERTY_NONATOMIC (property)) + obstack_grow (&util_obstack, ",N", 2); + + /* Here we want to encode the getter name, but only if it's not the + standard one. */ + if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property)) { - obstack_grow (&util_obstack, ",g", 2); + obstack_grow (&util_obstack, ",G", 2); string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property)); obstack_grow (&util_obstack, string, strlen (string)); } - if (PROPERTY_SETTER_NAME (property)) + + if (!PROPERTY_READONLY (property)) { - obstack_grow (&util_obstack, ",s", 2); - string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property)); - obstack_grow (&util_obstack, string, strlen (string)); + /* Here we want to encode the setter name, but only if it's not + the standard one. */ + tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property))); + if (PROPERTY_SETTER_NAME (property) != standard_setter) + { + obstack_grow (&util_obstack, ",S", 2); + string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property)); + obstack_grow (&util_obstack, string, strlen (string)); + } } - if (PROPERTY_IVAR_NAME (property)) + + /* TODO: Encode strong ('P'), weak ('W') for garbage collection. */ + + if (!PROPERTY_DYNAMIC (property)) { - obstack_grow (&util_obstack, ",i", 2); - string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property)); + obstack_grow (&util_obstack, ",V", 2); + if (PROPERTY_IVAR_NAME (property)) + string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property)); + else + string = IDENTIFIER_POINTER (PROPERTY_NAME (property)); obstack_grow (&util_obstack, string, strlen (string)); } - - obstack_1grow (&util_obstack, 0); /* null terminate string */ + + /* NULL-terminate string. */ + obstack_1grow (&util_obstack, 0); string = XOBFINISH (&util_obstack, char *); obstack_free (&util_obstack, util_firstobj); return get_identifier (string); Index: testsuite/ChangeLog =================================================================== --- testsuite/ChangeLog (revision 170464) +++ testsuite/ChangeLog (working copy) @@ -1,3 +1,11 @@ +2011-02-25 Nicola Pero + + * objc.dg/gnu-api-2-property.m: Added tests for property_getName() + and property_getAttributes() if __OBJC2__. + * obj-c++.dg/gnu-api-2-property.mm: Likewise. + * objc.dg/property/property-encoding-1.m: New. + * obj-c++.dg/property/property-encoding-1.mm: New. + 2011-02-24 Richard Guenther PR fortran/47839 Index: testsuite/objc.dg/property/property-encoding-1.m =================================================================== --- testsuite/objc.dg/property/property-encoding-1.m (revision 0) +++ testsuite/objc.dg/property/property-encoding-1.m (revision 0) @@ -0,0 +1,160 @@ +/* Contributed by Nicola Pero , February 2011. */ +/* Test encoding properties. */ +/* { dg-do run } */ +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- runtime" } { "" } } */ + +#include +#include +#include +#include + +@interface MyRootClass +{ Class isa; } ++ alloc; +- init; ++ initialize; +@end + +@implementation MyRootClass ++ alloc { return class_createInstance (self, 0); } +- init { return self; } ++ initialize { return self; } +@end + +@interface MySubClass : MyRootClass +{ + char char_property; + short short_property; + int int_property; + long long_property; + float float_property; + double double_property; + int *int_pointer_property; + + id propertyA; + id propertyB; + id propertyC; + id propertyD; + int propertyE; + id propertyF; + + id other_variable; +} +@property char char_property; +@property short short_property; +@property int int_property; +@property long long_property; +@property float float_property; +@property double double_property; +@property int *int_pointer_property; + +@property (assign, getter=getP, setter=setP:) id propertyA; +@property (assign) id propertyB; +@property (copy) id propertyC; +@property (retain) id propertyD; +@property (nonatomic) int propertyE; +@property (nonatomic, readonly, copy) id propertyF; + +@property (assign) id propertyG; +@property (assign, readonly, getter=X) id propertyH; +@end + +@implementation MySubClass +@synthesize char_property; +@synthesize short_property; +@synthesize int_property; +@synthesize long_property; +@synthesize float_property; +@synthesize double_property; +@synthesize int_pointer_property; + +@synthesize propertyA; +@synthesize propertyB; +@synthesize propertyC; +@synthesize propertyD; +@synthesize propertyE; +@synthesize propertyF; + +@synthesize propertyG = other_variable; +@dynamic propertyH; +@end + +#ifdef __OBJC2__ +void error (objc_property_t p) +{ + printf ("Error - property_getAttributes (\"%s\") returns \"%s\"\n", + property_getName (p), + property_getAttributes (p)); + abort (); +} +#endif + +int main(int argc, void **args) +{ +#ifdef __OBJC2__ + Class c = objc_getClass ("MySubClass"); + objc_property_t p; + + p = class_getProperty (c, "char_property"); + if (strcmp ("Tc,Vchar_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "short_property"); + if (strcmp ("Ts,Vshort_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_property"); + if (strcmp ("Ti,Vint_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "long_property"); + if (strcmp ("Tl,Vlong_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "float_property"); + if (strcmp ("Tf,Vfloat_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "double_property"); + if (strcmp ("Td,Vdouble_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_pointer_property"); + if (strcmp ("T^i,Vint_pointer_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyA"); + if (strcmp ("T@,GgetP,SsetP:,VpropertyA", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyB"); + if (strcmp ("T@,VpropertyB", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyC"); + if (strcmp ("T@,C,VpropertyC", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyD"); + if (strcmp ("T@,&,VpropertyD", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyE"); + if (strcmp ("Ti,N,VpropertyE", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyF"); + if (strcmp ("T@,R,C,N,VpropertyF", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyG"); + if (strcmp ("T@,Vother_variable", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyH"); + if (strcmp ("T@,R,D,GX", property_getAttributes (p)) != 0) + error (p); +#endif + + return 0; +} Index: testsuite/objc.dg/gnu-api-2-property.m =================================================================== --- testsuite/objc.dg/gnu-api-2-property.m (revision 170464) +++ testsuite/objc.dg/gnu-api-2-property.m (working copy) @@ -25,23 +25,18 @@ + initialize { 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; +@interface MySubClass : MyRootClass +{ + id propertyA; + id propertyB; +} +@property (assign, getter=getP, setter=setP:) id propertyA; +@property (assign, nonatomic) id propertyB; @end @implementation MySubClass -- (void) setVariable: (id)value { variable_ivar = value; } -- (id) variable { return variable_ivar; } +@synthesize propertyA; +@synthesize propertyB; @end @@ -49,7 +44,6 @@ int main(int argc, void **args) { /* Functions are tested in alphabetical order. */ - /* TODO: Test new ABI (when available). */ printf ("Testing property_getAttributes () ...\n"); { /* The Apple/NeXT runtime seems to crash on the following. */ @@ -57,9 +51,26 @@ int main(int argc, void **args) if (property_getAttributes (NULL) != NULL) abort (); #endif + + /* The GNU runtime doesn't support looking up properties at + runtime yet. */ +#ifdef __OBJC2__ + { + objc_property_t property; + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyA"); + if (strcmp (property_getAttributes (property), + "T@,GgetP,SsetP:,VpropertyA") != 0) + abort (); + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyB"); + if (strcmp (property_getAttributes (property), + "T@,N,VpropertyB") != 0) + abort (); + } +#endif } - /* TODO: Test new ABI (when available). */ printf ("Testing property_getName () ...\n"); { /* The Apple/NeXT runtime seems to crash on the following. */ @@ -67,6 +78,22 @@ int main(int argc, void **args) if (property_getName (NULL) != NULL) abort (); #endif + + /* The GNU runtime doesn't support looking up properties at + runtime yet. */ +#ifdef __OBJC2__ + { + objc_property_t property; + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyA"); + if (strcmp (property_getName (property), "propertyA") != 0) + abort (); + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyB"); + if (strcmp (property_getName (property), "propertyB") != 0) + abort (); + } +#endif } return 0; Index: testsuite/obj-c++.dg/property/property-encoding-1.mm =================================================================== --- testsuite/obj-c++.dg/property/property-encoding-1.mm (revision 0) +++ testsuite/obj-c++.dg/property/property-encoding-1.mm (revision 0) @@ -0,0 +1,160 @@ +/* Contributed by Nicola Pero , February 2011. */ +/* Test encoding properties. */ +/* { dg-do run } */ +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- runtime" } { "" } } */ + +#include +#include +#include +#include + +@interface MyRootClass +{ Class isa; } ++ alloc; +- init; ++ initialize; +@end + +@implementation MyRootClass ++ alloc { return class_createInstance (self, 0); } +- init { return self; } ++ initialize { return self; } +@end + +@interface MySubClass : MyRootClass +{ + char char_property; + short short_property; + int int_property; + long long_property; + float float_property; + double double_property; + int *int_pointer_property; + + id propertyA; + id propertyB; + id propertyC; + id propertyD; + int propertyE; + id propertyF; + + id other_variable; +} +@property char char_property; +@property short short_property; +@property int int_property; +@property long long_property; +@property float float_property; +@property double double_property; +@property int *int_pointer_property; + +@property (assign, getter=getP, setter=setP:) id propertyA; +@property (assign) id propertyB; +@property (copy) id propertyC; +@property (retain) id propertyD; +@property (nonatomic) int propertyE; +@property (nonatomic, readonly, copy) id propertyF; + +@property (assign) id propertyG; +@property (assign, readonly, getter=X) id propertyH; +@end + +@implementation MySubClass +@synthesize char_property; +@synthesize short_property; +@synthesize int_property; +@synthesize long_property; +@synthesize float_property; +@synthesize double_property; +@synthesize int_pointer_property; + +@synthesize propertyA; +@synthesize propertyB; +@synthesize propertyC; +@synthesize propertyD; +@synthesize propertyE; +@synthesize propertyF; + +@synthesize propertyG = other_variable; +@dynamic propertyH; +@end + +#ifdef __OBJC2__ +void error (objc_property_t p) +{ + printf ("Error - property_getAttributes (\"%s\") returns \"%s\"\n", + property_getName (p), + property_getAttributes (p)); + abort (); +} +#endif + +int main(int argc, char **args) +{ +#ifdef __OBJC2__ + Class c = objc_getClass ("MySubClass"); + objc_property_t p; + + p = class_getProperty (c, "char_property"); + if (strcmp ("Tc,Vchar_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "short_property"); + if (strcmp ("Ts,Vshort_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_property"); + if (strcmp ("Ti,Vint_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "long_property"); + if (strcmp ("Tl,Vlong_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "float_property"); + if (strcmp ("Tf,Vfloat_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "double_property"); + if (strcmp ("Td,Vdouble_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_pointer_property"); + if (strcmp ("T^i,Vint_pointer_property", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyA"); + if (strcmp ("T@,GgetP,SsetP:,VpropertyA", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyB"); + if (strcmp ("T@,VpropertyB", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyC"); + if (strcmp ("T@,C,VpropertyC", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyD"); + if (strcmp ("T@,&,VpropertyD", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyE"); + if (strcmp ("Ti,N,VpropertyE", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyF"); + if (strcmp ("T@,R,C,N,VpropertyF", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyG"); + if (strcmp ("T@,Vother_variable", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyH"); + if (strcmp ("T@,R,D,GX", property_getAttributes (p)) != 0) + error (p); +#endif + + return 0; +} Index: testsuite/obj-c++.dg/gnu-api-2-property.mm =================================================================== --- testsuite/obj-c++.dg/gnu-api-2-property.mm (revision 170464) +++ testsuite/obj-c++.dg/gnu-api-2-property.mm (working copy) @@ -25,23 +25,18 @@ + initialize { 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; +@interface MySubClass : MyRootClass +{ + id propertyA; + id propertyB; +} +@property (assign, getter=getP, setter=setP:) id propertyA; +@property (assign, nonatomic) id propertyB; @end @implementation MySubClass -- (void) setVariable: (id)value { variable_ivar = value; } -- (id) variable { return variable_ivar; } +@synthesize propertyA; +@synthesize propertyB; @end @@ -49,7 +44,6 @@ int main () { /* Functions are tested in alphabetical order. */ - /* TODO: Test new ABI (when available). */ std::cout << "Testing property_getAttributes () ...\n"; { /* The Apple/NeXT runtime seems to crash on the following. */ @@ -57,9 +51,26 @@ int main () if (property_getAttributes (NULL) != NULL) abort (); #endif + + /* The GNU runtime doesn't support looking up properties at + runtime yet. */ +#ifdef __OBJC2__ + { + objc_property_t property; + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyA"); + if (std::strcmp (property_getAttributes (property), + "T@,GgetP,SsetP:,VpropertyA") != 0) + abort (); + + property = class_getProperty (objc_getClass ("MySubClass"), "propertyB"); + if (std::strcmp (property_getAttributes (property), + "T@,N,VpropertyB") != 0) + abort (); + } +#endif } - /* TODO: Test new ABI (when available). */ std::cout << "Testing property_getName () ...\n";