Patchwork ObjC/ObjC++: Fix property encoding on Apple

login
register
mail settings
Submitter Nicola Pero
Date Feb. 25, 2011, 12:48 a.m.
Message ID <F07948F2-25A6-4489-918F-B0AFD79FE86A@meta-innovation.com>
Download mbox | patch
Permalink /patch/84499/
State New
Headers show

Comments

Nicola Pero - Feb. 25, 2011, 12:48 a.m.
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);
Jack Howarth - Feb. 25, 2011, 2:29 a.m.
On Fri, Feb 25, 2011 at 12:48:07AM +0000, Nicola Pero wrote:
> 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! :-)

Nicola,
   Can you repost the patch as an attachment? Your emailer seems to 
have reformatted the patch so that it is considered as malformed by
patch and can't be applied against gcc trunk.
           Jack

>
> Index: objc/ChangeLog
> ===================================================================
> --- objc/ChangeLog      (revision 170464)
> +++ objc/ChangeLog      (working copy)
> @@ -1,3 +1,7 @@
> +2011-02-25  Nicola Pero  <nicola.pero@meta-innovation.com>
> +
> +       * objc-act.c (objc_v2_encode_prop_attr): Rewritten.
> +
>  2011-02-23  Nicola Pero  <nicola.pero@meta-innovation.com>
>
>         * objc-act.c (build_private_template): Do not copy the
> @@ -16,7 +20,8 @@
>
>  2011-02-21  Mike Stump  <mikestump@comcast.net>
>
> -       * 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  <nicola.pero@meta-innovation.com>
>
> 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  <nicola.pero@meta-innovation.com>
> +
> +       * 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  <rguenther@suse.de>
>
>         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 <nicola.pero@meta-innovation.com>,  
> February 2011.  */
> +/* Test encoding properties.  */
> +/* { dg-do run } */
> +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- 
> runtime" } { "" } } */
> +
> +#include <objc/runtime.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +@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 <MyProtocol>
> -{ 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 <nicola.pero@meta-innovation.com>,  
> February 2011.  */
> +/* Test encoding properties.  */
> +/* { dg-do run } */
> +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- 
> runtime" } { "" } } */
> +
> +#include <objc/runtime.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +@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 <MyProtocol>
> -{ 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";
>    {
>      /* 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);

Patch

Index: objc/ChangeLog
===================================================================
--- objc/ChangeLog      (revision 170464)
+++ objc/ChangeLog      (working copy)
@@ -1,3 +1,7 @@ 
+2011-02-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-act.c (objc_v2_encode_prop_attr): Rewritten.
+
  2011-02-23  Nicola Pero  <nicola.pero@meta-innovation.com>

         * objc-act.c (build_private_template): Do not copy the
@@ -16,7 +20,8 @@ 

  2011-02-21  Mike Stump  <mikestump@comcast.net>

-       * 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  <nicola.pero@meta-innovation.com>

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  <nicola.pero@meta-innovation.com>
+
+       * 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  <rguenther@suse.de>

         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 <nicola.pero@meta-innovation.com>,  
February 2011.  */
+/* Test encoding properties.  */
+/* { dg-do run } */
+/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- 
runtime" } { "" } } */
+
+#include <objc/runtime.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+@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 <MyProtocol>
-{ 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 <nicola.pero@meta-innovation.com>,  
February 2011.  */
+/* Test encoding properties.  */
+/* { dg-do run } */
+/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext- 
runtime" } { "" } } */
+
+#include <objc/runtime.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+@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 <MyProtocol>
-{ 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";