OSDN Git Service

In gcc/objc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Nov 2010 13:14:55 +0000 (13:14 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 6 Nov 2010 13:14:55 +0000 (13:14 +0000)
2010-11-05  Nicola Pero  <nicola.pero@meta-innovation.com>

        Fixed using the Objective-C 2.0 syntax with self and super.
        * objc-act.c (OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS): New.
        (maybe_make_artificial_property_decl): Added 'implementation'
        argument.  Use OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS when
        looking up getters or setters for a class.  If an implementation
        is specified, search it as well for a getter or setter.
        (objc_maybe_build_component_ref): Updated calls to
        maybe_make_artificial_property_decl; added code to deal with
        'self' and 'super' and with methods declared locally in the
        implementation.  Store the getter call expression in the
        PROPERTY_REF instead of throwing it away.
        (objc_build_class_component_ref): Updated calls to
        maybe_make_artificial_property_decl, and store the getter call
        expression in PROPERTY_REF instead of throwing it away.
        (lookup_method_static): Implemented
        OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS option.
        (objc_gimplify_property_ref): Do not build the getter method call
        here; instead use the one stored in the PROPERTY_REF.  If it's not
        there, produce helpful error messages.
        * objc-tree.def (PROPERTY_REF): Increased the number of operands
        from 2 to 3.  Updated comments.
        * objc-act.h (PROPERTY_REF_GETTER_CALL): New.

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

        Fixed using the Objective-C 2.0 dot-syntax with self and super.
        * objc.dg/property/dotsyntax-5.m: New.
        * objc.dg/property/dotsyntax-6.m: New.
        * objc.dg/property/dotsyntax-7.m: New.
        * objc.dg/property/dotsyntax-8.m: New.
        * objc.dg/property/dotsyntax-9.m: New.
        * objc.dg/property/dotsyntax-10.m: New.
        * objc.dg/property/dotsyntax-11.m: New.
        * obj-c++.dg/property/dotsyntax-5.mm: New.
        * obj-c++.dg/property/dotsyntax-6.mm: New.
        * obj-c++.dg/property/dotsyntax-7.mm: New.
        * obj-c++.dg/property/dotsyntax-8.mm: New.
        * obj-c++.dg/property/dotsyntax-9.mm: New.
        * obj-c++.dg/property/dotsyntax-10.mm: New.
        * obj-c++.dg/property/dotsyntax-11.mm: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166402 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/objc/objc-tree.def
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/property/dotsyntax-10.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-11.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-6.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-7.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-8.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-9.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-10.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-11.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-5.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-6.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-7.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-8.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-9.m [new file with mode: 0644]

index 104948b..9bde682 100644 (file)
@@ -1,3 +1,28 @@
+2010-11-06  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Fixed using the Objective-C 2.0 syntax with self and super.
+       * objc-act.c (OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS): New.
+       (maybe_make_artificial_property_decl): Added 'implementation'
+       argument.  Use OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS when
+       looking up getters or setters for a class.  If an implementation
+       is specified, search it as well for a getter or setter.
+       (objc_maybe_build_component_ref): Updated calls to
+       maybe_make_artificial_property_decl; added code to deal with
+       'self' and 'super' and with methods declared locally in the
+       implementation.  Store the getter call expression in the
+       PROPERTY_REF instead of throwing it away.
+       (objc_build_class_component_ref): Updated calls to
+       maybe_make_artificial_property_decl, and store the getter call
+       expression in PROPERTY_REF instead of throwing it away.
+       (lookup_method_static): Implemented
+       OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS option.
+       (objc_gimplify_property_ref): Do not build the getter method call
+       here; instead use the one stored in the PROPERTY_REF.  If it's not
+       there, produce helpful error messages.
+       * objc-tree.def (PROPERTY_REF): Increased the number of operands
+       from 2 to 3.  Updated comments.
+       * objc-act.h (PROPERTY_REF_GETTER_CALL): New.
+       
 2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
 
        PR target/44981
index 02966a8..fd5244e 100644 (file)
@@ -377,8 +377,14 @@ static const char *default_constant_string_class_name;
 #define TAG_GNUINIT                    "__objc_gnu_init"
 
 /* Flags for lookup_method_static().  */
-#define OBJC_LOOKUP_CLASS      1       /* Look for class methods.  */
-#define OBJC_LOOKUP_NO_SUPER   2       /* Do not examine superclasses.  */
+
+/* Look for class methods.  */
+#define OBJC_LOOKUP_CLASS      1
+/* Do not examine superclasses.  */
+#define OBJC_LOOKUP_NO_SUPER   2
+/* Disable returning an instance method of a root class when a class
+   method can't be found.  */
+#define OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS 4 
 
 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
 tree objc_global_trees[OCTI_MAX];
@@ -1085,32 +1091,58 @@ lookup_property (tree interface_type, tree property)
 }
 
 /* This is a subroutine of objc_maybe_build_component_ref.  Search the
-   list of methods in the interface (and, failing that, protocol list)
+   list of methods in the interface (and, failing that, the local list
+   in the implementation, and failing that, the protocol list)
    provided for a 'setter' or 'getter' for 'component' with default
    names (ie, if 'component' is "name", then search for "name" and
    "setName:").  If any is found, then create an artificial property
    that uses them.  Return NULL_TREE if 'getter' or 'setter' could not
    be found.  */
 static tree
-maybe_make_artificial_property_decl (tree interface, tree protocol_list, tree component, bool is_class)
+maybe_make_artificial_property_decl (tree interface, tree implementation, 
+                                    tree protocol_list, tree component, bool is_class)
 {
   tree getter_name = component;
   tree setter_name = get_identifier (objc_build_property_setter_name (component));
   tree getter = NULL_TREE;
   tree setter = NULL_TREE;
 
+  /* First, check the @interface and all superclasses.  */
   if (interface)
     {
       int flags = 0;
 
+      /* Using instance methods of the root class as accessors is most
+        likely unwanted and can be extremely confusing (and, most
+        importantly, other Objective-C 2.0 compilers do not do it).
+        Turn it off.  */
       if (is_class)
-       flags = OBJC_LOOKUP_CLASS;
+       flags = OBJC_LOOKUP_CLASS | OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS;
       
       getter = lookup_method_static (interface, getter_name, flags);
       setter = lookup_method_static (interface, setter_name, flags);
     }
 
-  /* Try the protocol_list if we didn't find anything in the interface.  */
+  /* Second, check the local @implementation context.  */
+  if (!getter && !setter)
+    {
+      if (implementation)
+       {
+         if (is_class)
+           {
+             getter = lookup_method (CLASS_CLS_METHODS (implementation), getter_name);
+             setter = lookup_method (CLASS_CLS_METHODS (implementation), setter_name);
+           }
+         else
+           {
+             getter = lookup_method (CLASS_NST_METHODS (implementation), getter_name);
+             setter = lookup_method (CLASS_NST_METHODS (implementation), setter_name);       
+           }
+       }
+    }
+
+  /* Try the protocol_list if we didn't find anything in the
+     @interface and in the @implementation.  */
   if (!getter && !setter)
     {
       getter = lookup_method_in_protocol_list (protocol_list, getter_name, is_class);
@@ -1186,13 +1218,13 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
   tree x = NULL_TREE;
   tree rtype;
 
-  /* If we are in Objective-C 1.0 mode, properties are not
-     available.  */
+  /* If we are in Objective-C 1.0 mode, dot-syntax and properties are
+     not available.  */
   if (flag_objc1_only)
     return NULL_TREE;
 
-  /* Try to determine quickly if 'object' is an Objective-C object or
-     not.  If not, return.  */
+  /* Try to determine if 'object' is an Objective-C object or not.  If
+     not, return.  */
   if (object == NULL_TREE || object == error_mark_node 
       || (rtype = TREE_TYPE (object)) == NULL_TREE)
     return NULL_TREE;
@@ -1201,37 +1233,118 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
       || TREE_CODE (property_ident) != IDENTIFIER_NODE)
     return NULL_TREE;
 
-  /* TODO: Implement super.property.  */
-  
-  /* TODO: Carefully review the following code.  */
+  /* The following analysis of 'object' is similar to the one used for
+     the 'receiver' of a method invocation.  We need to determine what
+     'object' is and find the appropriate property (either declared,
+     or artificial) for it (in the same way as we need to find the
+     appropriate method prototype for a method invocation).  There are
+     some simplifications here though: "object.property" is invalid if
+     "object" has a type of "id" or "Class"; it must at least have a
+     protocol attached to it, and "object" is never a class name as
+     that is done by objc_build_class_component_ref.  Finally, we
+     don't know if this really is a dot-syntax expression, so we want
+     to make a quick exit if it is not; for this reason, we try to
+     postpone checks after determining that 'object' looks like an
+     Objective-C object.  */
+
   if (objc_is_id (rtype))
     {
-      tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
-                     ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
-                     : NULL_TREE);
-      if (rprotos)
-       x = lookup_property_in_protocol_list (rprotos, property_ident);
+      /* This is the case that the 'object' is of type 'id' or
+        'Class'.  */
 
-      if (x == NULL_TREE)
+      /* Check if at least it is of type 'id <Protocol>' or 'Class
+        <Protocol>'; if so, look the property up in the
+        protocols.  */
+      if (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype)))
        {
-         /* Ok, no property.  Maybe it was an object.component
-            dot-syntax without a declared property.  Look for
-            getter/setter methods and internally declare an artifical
-            property based on them if found.  */
-         x = maybe_make_artificial_property_decl (NULL_TREE, rprotos, 
-                                                  property_ident,
-                                                  false);
+         tree rprotos = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype));
+         
+         if (rprotos)
+           {
+             /* No point looking up declared @properties if we are
+                dealing with a class.  Classes have no declared
+                properties.  */
+             if (!IS_CLASS (rtype))
+               x = lookup_property_in_protocol_list (rprotos, property_ident);
+             
+             if (x == NULL_TREE)
+               {
+                 /* Ok, no property.  Maybe it was an
+                    object.component dot-syntax without a declared
+                    property (this is valid for classes too).  Look
+                    for getter/setter methods and internally declare
+                    an artifical property based on them if found.  */
+                 x = maybe_make_artificial_property_decl (NULL_TREE,
+                                                          NULL_TREE,
+                                                          rprotos, 
+                                                          property_ident,
+                                                          IS_CLASS (rtype));
+               }
+           }
+       }
+      else if (objc_method_context)
+       {
+         /* Else, if we are inside a method it could be the case of
+            'super' or 'self'.  */
+         tree interface_type = NULL_TREE;
+         tree t = object;
+         while (TREE_CODE (t) == COMPOUND_EXPR
+                || TREE_CODE (t) == MODIFY_EXPR
+                || CONVERT_EXPR_P (t)
+                || TREE_CODE (t) == COMPONENT_REF)
+           t = TREE_OPERAND (t, 0);
+         
+         if (t == UOBJC_SUPER_decl)
+           interface_type = lookup_interface (CLASS_SUPER_NAME (implementation_template));
+         else if (t == self_decl)
+           interface_type = lookup_interface (CLASS_NAME (implementation_template));
+
+         /* TODO: Protocols.  */
+
+         if (interface_type)
+           {
+             if (TREE_CODE (objc_method_context) != CLASS_METHOD_DECL)
+               {
+                 x = lookup_property (interface_type, property_ident);
+                 /* TODO: Protocols.  */
+               }
+       
+             if (x == NULL_TREE)
+               {
+                 /* Try the dot-syntax without a declared property.
+                    If this is an access to 'self', it is possible
+                    that they may refer to a setter/getter that is
+                    not declared in the interface, but exists locally
+                    in the implementation.  In that case, get the
+                    implementation context and use it.  */
+                 tree implementation = NULL_TREE;
+
+                 if (t == self_decl)
+                   implementation = objc_implementation_context;
+                 
+                 /* TODO: Protocols.  */
+
+                 x = maybe_make_artificial_property_decl 
+                   (interface_type, implementation, NULL_TREE,
+                    property_ident,
+                    (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL));
+               }
+           }
        }
     }
   else
     {
+      /* This is the case where we have more information on 'rtype'.  */
       tree basetype = TYPE_MAIN_VARIANT (rtype);
 
+      /* Skip the pointer - if none, it's not an Objective-C object or
+        class.  */
       if (basetype != NULL_TREE && TREE_CODE (basetype) == POINTER_TYPE)
        basetype = TREE_TYPE (basetype);
       else
        return NULL_TREE;
 
+      /* Traverse typedefs.  */
       while (basetype != NULL_TREE
             && TREE_CODE (basetype) == RECORD_TYPE 
             && OBJC_TYPE_NAME (basetype)
@@ -1243,58 +1356,91 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
        {
          tree interface_type = TYPE_OBJC_INTERFACE (basetype);
          tree protocol_list = TYPE_OBJC_PROTOCOL_LIST (basetype);
-         
-         x = lookup_property (interface_type, property_ident);
-
-         if (x == NULL_TREE)
-           x = lookup_property_in_protocol_list (protocol_list, property_ident);
 
-         if (x == NULL_TREE)
+         if (interface_type 
+             && (TREE_CODE (interface_type) == CLASS_INTERFACE_TYPE
+                 || TREE_CODE (interface_type) == CATEGORY_INTERFACE_TYPE
+                 || TREE_CODE (interface_type) == PROTOCOL_INTERFACE_TYPE))
            {
-             /* Ok, no property.  Try the dot-syntax without a
-                declared property.  */
-             x = maybe_make_artificial_property_decl (interface_type, protocol_list, 
-                                                      property_ident, false);
+             /* Not sure 'rtype' could ever be a class here!  Just
+                for safety we keep the checks.  */
+             if (!IS_CLASS (rtype))
+               {
+                 x = lookup_property (interface_type, property_ident);
+                 
+                 if (x == NULL_TREE)
+                   x = lookup_property_in_protocol_list (protocol_list, 
+                                                         property_ident);
+               }
+             
+             if (x == NULL_TREE)
+               {
+                 /* Try the dot-syntax without a declared property.
+                    If we are inside a method implementation, it is
+                    possible that they may refer to a setter/getter
+                    that is not declared in the interface, but exists
+                    locally in the implementation.  In that case, get
+                    the implementation context and use it.  */
+                 tree implementation = NULL_TREE;
+
+                 if (objc_implementation_context
+                     && CLASS_NAME (objc_implementation_context) 
+                     == OBJC_TYPE_NAME (interface_type))
+                   implementation = objc_implementation_context;
+                 
+                 x = maybe_make_artificial_property_decl (interface_type,
+                                                          implementation,
+                                                          protocol_list, 
+                                                          property_ident,
+                                                          IS_CLASS (rtype));
+               }
            }
        }
     }
 
+  /* TODO: Fix compiling super.accessor.  */
+
   if (x)
     {
       tree expression;
-
-      if (TREE_DEPRECATED (x))
-       warn_deprecated_use (x, NULL_TREE);
-
-      expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
-      SET_EXPR_LOCATION (expression, input_location);
-      TREE_SIDE_EFFECTS (expression) = 1;
+      tree getter_call;
 
       /* We have an additional nasty problem here; if this
         PROPERTY_REF needs to become a 'getter', then the conversion
         from PROPERTY_REF into a getter call happens in gimplify,
-        after the selector table has already been generated and it is
-        too late to add another selector to it.  To work around the
-        problem, we always put the selector in the table at this
-        stage, as if we were building the method call here.  And the
-        easiest way to do this is precisely to build the method call,
-        then discard it.  Note that if the PROPERTY_REF becomes a
-        'setter' instead of a 'getter', then we have added a selector
-        too many to the selector table.  This is a little
-        inefficient.
-
-        TODO: This can be made more efficient; in particular we don't
-        need to build the whole message call, we could just work on
-        the selector.
+        after the selector table has already been generated and when
+        it is too late to add another selector to it.  To work around
+        the problem, we always create the getter call at this stage,
+        which puts the selector in the table.  Note that if the
+        PROPERTY_REF becomes a 'setter' instead of a 'getter', then
+        we have added a selector too many to the selector table.
+        This is a little inefficient.
+
+        Also note that method calls to 'self' and 'super' require the
+        context (self_decl, UOBJS_SUPER_decl,
+        objc_implementation_context etc) to be built correctly; this
+        is yet another reason why building the call at the gimplify
+        stage (when this context has been lost) is not very
+        practical.  If we build it at this stage, we know it will
+        always be built correctly.
 
         If the PROPERTY_HAS_NO_GETTER() (ie, it is an artificial
         property decl created to deal with a dotsyntax not really
         referring to an existing property) then do not try to build a
         call to the getter as there is no getter.  */
-      if (!PROPERTY_HAS_NO_GETTER (x))
-       objc_finish_message_expr (object,
-                                 PROPERTY_GETTER_NAME (x),
-                                 NULL_TREE);
+      if (PROPERTY_HAS_NO_GETTER (x))
+       getter_call = NULL_TREE;
+      else
+       getter_call = objc_finish_message_expr (object,
+                                               PROPERTY_GETTER_NAME (x),
+                                               NULL_TREE);
+
+      if (TREE_DEPRECATED (x))
+       warn_deprecated_use (x, NULL_TREE);
+
+      expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call);
+      SET_EXPR_LOCATION (expression, input_location);
+      TREE_SIDE_EFFECTS (expression) = 1;
       
       return expression;
     }
@@ -1341,26 +1487,28 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
       return error_mark_node;
     }
 
-  x = maybe_make_artificial_property_decl (rtype, NULL_TREE,
+  x = maybe_make_artificial_property_decl (rtype, NULL_TREE, NULL_TREE,
                                           property_ident,
                                           true);
   
   if (x)
     {
       tree expression;
+      tree getter_call;
 
+      if (PROPERTY_HAS_NO_GETTER (x))
+       getter_call = NULL_TREE;
+      else
+       getter_call = objc_finish_message_expr (object,
+                                               PROPERTY_GETTER_NAME (x),
+                                               NULL_TREE);
       if (TREE_DEPRECATED (x))
        warn_deprecated_use (x, NULL_TREE);
 
-      expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
+      expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call);
       SET_EXPR_LOCATION (expression, input_location);
       TREE_SIDE_EFFECTS (expression) = 1;
-      /* See above for why we do this.  */
-      if (!PROPERTY_HAS_NO_GETTER (x))
-       objc_finish_message_expr (object,
-                                 PROPERTY_GETTER_NAME (x),
-                                 NULL_TREE);
-      
+
       return expression;
     }
   else
@@ -7957,13 +8105,16 @@ lookup_method (tree mchain, tree method)
   return NULL_TREE;
 }
 
-/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
-   in INTERFACE, along with any categories and protocols attached thereto.
-   If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
-   recursively examine the INTERFACE's superclass.  If OBJC_LOOKUP_CLASS is
-   set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
-   be found in INTERFACE or any of its superclasses, look for an _instance_
-   method of the same name in the root class as a last resort.
+/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance
+   method in INTERFACE, along with any categories and protocols
+   attached thereto.  If method is not found, and the
+   OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS, recursively examine the
+   INTERFACE's superclass.  If OBJC_LOOKUP_CLASS is set,
+   OBJC_LOOKUP_NO_SUPER is clear, and no suitable class method could
+   be found in INTERFACE or any of its superclasses, look for an
+   _instance_ method of the same name in the root class as a last
+   resort.  This behaviour can be turned off by using
+   OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS.
 
    If a suitable method cannot be found, return NULL_TREE.  */
 
@@ -7974,6 +8125,7 @@ lookup_method_static (tree interface, tree ident, int flags)
   tree inter = interface;
   int is_class = (flags & OBJC_LOOKUP_CLASS);
   int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
+  int no_instance_methods_of_root_class = (flags & OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS);
 
   while (inter)
     {
@@ -8020,11 +8172,18 @@ lookup_method_static (tree interface, tree ident, int flags)
     }
   while (inter);
 
-  /* If no class (factory) method was found, check if an _instance_
-     method of the same name exists in the root class.  This is what
-     the Objective-C runtime will do.  If an instance method was not
-     found, return 0.  */
-  return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
+  if (is_class && !no_instance_methods_of_root_class)
+    {
+      /* If no class (factory) method was found, check if an _instance_
+        method of the same name exists in the root class.  This is what
+        the Objective-C runtime will do.  */
+      return lookup_method_static (root_inter, ident, 0);
+    }
+  else
+    {
+      /* If an instance method was not found, return 0.  */      
+      return NULL_TREE;
+    }
 }
 
 /* Add the method to the hash list if it doesn't contain an identical
@@ -12038,15 +12197,24 @@ objc_rewrite_function_call (tree function, tree first_param)
 static void
 objc_gimplify_property_ref (tree *expr_p)
 {
-  tree object_expression = PROPERTY_REF_OBJECT (*expr_p);
-  tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
-  tree call_exp, getter;
-
-  /* TODO: Implement super.property.  */
+  tree getter = PROPERTY_REF_GETTER_CALL (*expr_p);
+  tree call_exp;
+
+  if (getter == NULL_TREE)
+    {
+      tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
+      /* This can happen if DECL_ARTIFICIAL (*expr_p), but
+        should be impossible for real properties, which always
+        have a getter.  */
+      error_at (EXPR_LOCATION (*expr_p), "no %qs getter found",
+               IDENTIFIER_POINTER (PROPERTY_NAME (property_decl)));
+      /* Try to recover from the error to prevent an ICE.  We take
+        zero and cast it to the type of the property.  */
+      *expr_p = convert (TREE_TYPE (property_decl),
+                        integer_zero_node);
+      return;
+    }
 
-  getter = objc_finish_message_expr (object_expression, 
-                                    PROPERTY_GETTER_NAME (property_decl),
-                                    NULL_TREE);
   call_exp = getter;
 #ifdef OBJCPLUS
   /* In C++, a getter which returns an aggregate value results in a
index 9478d72..9a9cacd 100644 (file)
@@ -131,6 +131,15 @@ typedef enum objc_property_assign_semantics {
    declared property.  */
 #define PROPERTY_REF_PROPERTY_DECL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 1)
 
+/* PROPERTY_REF_GETTER_CALL is the getter call expression, ready to
+   use at gimplify time if needed.  Generating the getter call
+   requires modifying the selector table, and, in the case of
+   self/super, requires the context to be generated correctly.  The
+   gimplify stage is too late to do these things, so we generate the
+   getter call earlier instead, and keep it here in case we need to
+   use it.  */
+#define PROPERTY_REF_GETTER_CALL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 2)
+
 
 /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
    CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
index 7316675..e33fc78 100644 (file)
@@ -44,9 +44,11 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
    where 'object' is an Objective-C object and 'property' is an
    Objective-C property.  Operand 0 is the object (the tree
    representing the expression), and Operand 1 is the property (the
-   PROPERTY_DECL).  A PROPERTY_REF tree needs to be transformed into
-   'setter' and 'getter' calls at some point; at the moment this
-   happens in two places:
+   PROPERTY_DECL).  Operand 2 is the 'getter' call, ready to be used;
+   we pregenerate it because it is hard to generate it properly later
+   on.  A PROPERTY_REF tree needs to be transformed into 'setter' and
+   'getter' calls at some point; at the moment this happens in two
+   places:
 
      * if we detect that a modify expression is being applied to a
        PROPERTY_REF, then we transform that into a 'getter' call (this
@@ -54,13 +56,15 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
 
     * else, it will remain as a PROPERTY_REF until we get to
       gimplification; at that point, we convert each PROPERTY_REF into
-      a 'getter' call during ObjC/ObjC++ gimplify.
+      a 'getter' call during ObjC/ObjC++ gimplify.  At that point, it
+      is quite hard to build a 'getter' call, but we have already built
+      it and we just need to swap Operand 2 in.
 
   Please note that when the Objective-C 2.0 "dot-syntax" 'object.component' 
   is encountered, where 'component' is not a property but there are valid
   setter/getter methods for it, an artificial PROPERTY_DECL is generated
   and used in the PROPERTY_REF.  */
-DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 2)
+DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 3)
 
 /*
 Local variables:
index c9a0dc6..fc8fc74 100644 (file)
@@ -1,3 +1,21 @@
+2010-11-06  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Fixed using the Objective-C 2.0 dot-syntax with self and super.
+       * objc.dg/property/dotsyntax-5.m: New.
+       * objc.dg/property/dotsyntax-6.m: New.
+       * objc.dg/property/dotsyntax-7.m: New.
+       * objc.dg/property/dotsyntax-8.m: New.
+       * objc.dg/property/dotsyntax-9.m: New.
+       * objc.dg/property/dotsyntax-10.m: New.
+       * objc.dg/property/dotsyntax-11.m: New.
+       * obj-c++.dg/property/dotsyntax-5.mm: New.
+       * obj-c++.dg/property/dotsyntax-6.mm: New.
+       * obj-c++.dg/property/dotsyntax-7.mm: New.
+       * obj-c++.dg/property/dotsyntax-8.mm: New.
+       * obj-c++.dg/property/dotsyntax-9.mm: New.
+       * obj-c++.dg/property/dotsyntax-10.mm: New.
+       * obj-c++.dg/property/dotsyntax-11.mm: New.
+
 2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
 
        * obj-c++.dg/encode-3.mm: Provide a different string check for the
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-10.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-10.mm
new file mode 100644 (file)
index 0000000..433595f
--- /dev/null
@@ -0,0 +1,86 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot-syntax with 'super'.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+@interface MySubClass : MyRootClass
++ (int) testMe;
+- (int) testMe;
+@end
+
+@implementation MySubClass
+- (int) testMe
+{
+  super.count = 400;
+  if (super.count != 400)
+    abort ();
+
+  return super.count;
+}
++ (int) testMe
+{
+  super.classCount = 4000;
+  if (super.classCount != 4000)
+    abort ();
+
+  return super.classCount;
+}
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MySubClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-11.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-11.mm
new file mode 100644 (file)
index 0000000..6c9d924
--- /dev/null
@@ -0,0 +1,61 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test the error reporting for the dot-syntax in the scenario where
+   we have a setter, but not a getter, yet a getter is requested.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (void) setCount: (int)count;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+@interface MySubClass : MyRootClass
++ (int) testMe;
+- (int) testMe;
+@end
+
+@implementation MySubClass
+- (int) testMe
+{
+  super.count = 400;
+  if (super.count != 400) /* { dg-error "no .count. getter found" } */
+    abort ();             
+
+  return super.count;     /* { dg-error "no .count. getter found" } */
+}
++ (int) testMe
+{
+  super.classCount = 4000;
+  if (super.classCount != 4000) /* { dg-error "no .classCount. getter found" } */
+    abort ();
+
+  return super.classCount;      /* { dg-error "no .classCount. getter found" } */
+}
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-5.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-5.mm
new file mode 100644 (file)
index 0000000..06e1130
--- /dev/null
@@ -0,0 +1,78 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test the 'dot syntax' with self, both in instance and class methods.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+- (int) testMe
+{
+  self.count = 400;
+  if (self.count != 400)
+    abort ();
+
+  return self.count;
+}
++ (int) testMe
+{
+  self.classCount = 4000;
+  if (self.classCount != 4000)
+    abort ();
+
+  return self.classCount;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MyRootClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-6.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-6.mm
new file mode 100644 (file)
index 0000000..cc8c567
--- /dev/null
@@ -0,0 +1,107 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test nested 'dot syntax' (xxx.yyy.zzz or [xxx yyy].zzz).  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@class MyRootClass;
+
+static int c;
+static MyRootClass *shared_root = nil;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+  int b;
+  MyRootClass *next;
+}
+@property int b;
+@property (assign) MyRootClass *next;
++ (id) initialize;
++ (MyRootClass *)sharedInstance;
++ (id) alloc;
+- (id) init;
+- (MyRootClass *)same;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
+@synthesize b;
+@synthesize next;
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
++ (MyRootClass *)sharedInstance
+{
+  if (!shared_root)
+    shared_root = [[self alloc] init];
+
+  return shared_root;
+}
+- (MyRootClass *)same
+{
+  return self;
+}
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  /* Test ClassName.accessor.accessor.  */
+  MyRootClass.sharedInstance.count = 500;
+  if (MyRootClass.sharedInstance.count != 500)
+    abort ();
+
+  /* Test object.accessor.accessor.  */
+  object.same.count = 1000;
+  if (object.same.count != 1000)
+    abort ();
+
+  /* Test object.accessor.property.  */
+  object.same.next = object;
+  if (object.same.next != object)
+    abort ();
+
+  /* Test lots of nesting.  */
+  if (object.next.next.same.same.next.next.same != object)
+    abort ();
+
+  /* Test more nesting.  */
+  MyRootClass.sharedInstance.next = object;
+  MyRootClass.sharedInstance.next.next.next.next.next.count = 2000;
+  if (MyRootClass.sharedInstance.next.next.next.next.next.count != 2000)
+    abort ();
+
+  /* Test more nesting.  */
+  MyRootClass.sharedInstance.same.same.same.same.same.count = 3000;
+  if (MyRootClass.sharedInstance.same.same.same.same.same.count != 3000)
+    abort ();
+
+  /* Test [object method].property.  */
+  [MyRootClass sharedInstance].count = 5000;
+  if ([MyRootClass sharedInstance].count != 5000)
+    abort ();
+
+  /* Just a final check.  */
+  if (shared_root.count != 5000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-7.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-7.mm
new file mode 100644 (file)
index 0000000..15c1725
--- /dev/null
@@ -0,0 +1,48 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot syntax of a casted expression.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  id object = [[MyRootClass alloc] init];
+
+  ((MyRootClass *)object).count = 200;
+  if (((MyRootClass *)object).count != 200)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-8.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-8.mm
new file mode 100644 (file)
index 0000000..35dfda4
--- /dev/null
@@ -0,0 +1,62 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test the 'dot syntax' with typedefs.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+typedef MyRootClass MyType;
+
+int main (void)
+{
+  MyType *object = [[MyRootClass alloc] init];
+
+  object.count = 1974;
+  if (object.count != 1974)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-9.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-9.mm
new file mode 100644 (file)
index 0000000..61a5c0e
--- /dev/null
@@ -0,0 +1,77 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test that setter/getters for dot-syntax are properly found even if
+   not declared in the @interface, but available in the local
+   @implementation before the current line (ie, [object name] can be
+   compiled in that case, so object.name should be compiled too).  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+- (int) testMe
+{
+  self.count = 400;
+  if (self.count != 400)
+    abort ();
+
+  return self.count;
+}
++ (int) testMe
+{
+  self.classCount = 4000;
+  if (self.classCount != 4000)
+    abort ();
+
+  return self.classCount;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MyRootClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-10.m b/gcc/testsuite/objc.dg/property/dotsyntax-10.m
new file mode 100644 (file)
index 0000000..433595f
--- /dev/null
@@ -0,0 +1,86 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot-syntax with 'super'.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+@interface MySubClass : MyRootClass
++ (int) testMe;
+- (int) testMe;
+@end
+
+@implementation MySubClass
+- (int) testMe
+{
+  super.count = 400;
+  if (super.count != 400)
+    abort ();
+
+  return super.count;
+}
++ (int) testMe
+{
+  super.classCount = 4000;
+  if (super.classCount != 4000)
+    abort ();
+
+  return super.classCount;
+}
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MySubClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-11.m b/gcc/testsuite/objc.dg/property/dotsyntax-11.m
new file mode 100644 (file)
index 0000000..6c9d924
--- /dev/null
@@ -0,0 +1,61 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test the error reporting for the dot-syntax in the scenario where
+   we have a setter, but not a getter, yet a getter is requested.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (void) setCount: (int)count;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+@interface MySubClass : MyRootClass
++ (int) testMe;
+- (int) testMe;
+@end
+
+@implementation MySubClass
+- (int) testMe
+{
+  super.count = 400;
+  if (super.count != 400) /* { dg-error "no .count. getter found" } */
+    abort ();             
+
+  return super.count;     /* { dg-error "no .count. getter found" } */
+}
++ (int) testMe
+{
+  super.classCount = 4000;
+  if (super.classCount != 4000) /* { dg-error "no .classCount. getter found" } */
+    abort ();
+
+  return super.classCount;      /* { dg-error "no .classCount. getter found" } */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-5.m b/gcc/testsuite/objc.dg/property/dotsyntax-5.m
new file mode 100644 (file)
index 0000000..06e1130
--- /dev/null
@@ -0,0 +1,78 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test the 'dot syntax' with self, both in instance and class methods.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+- (int) testMe
+{
+  self.count = 400;
+  if (self.count != 400)
+    abort ();
+
+  return self.count;
+}
++ (int) testMe
+{
+  self.classCount = 4000;
+  if (self.classCount != 4000)
+    abort ();
+
+  return self.classCount;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MyRootClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-6.m b/gcc/testsuite/objc.dg/property/dotsyntax-6.m
new file mode 100644 (file)
index 0000000..cc8c567
--- /dev/null
@@ -0,0 +1,107 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test nested 'dot syntax' (xxx.yyy.zzz or [xxx yyy].zzz).  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@class MyRootClass;
+
+static int c;
+static MyRootClass *shared_root = nil;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+  int b;
+  MyRootClass *next;
+}
+@property int b;
+@property (assign) MyRootClass *next;
++ (id) initialize;
++ (MyRootClass *)sharedInstance;
++ (id) alloc;
+- (id) init;
+- (MyRootClass *)same;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
+@synthesize b;
+@synthesize next;
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
++ (MyRootClass *)sharedInstance
+{
+  if (!shared_root)
+    shared_root = [[self alloc] init];
+
+  return shared_root;
+}
+- (MyRootClass *)same
+{
+  return self;
+}
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  /* Test ClassName.accessor.accessor.  */
+  MyRootClass.sharedInstance.count = 500;
+  if (MyRootClass.sharedInstance.count != 500)
+    abort ();
+
+  /* Test object.accessor.accessor.  */
+  object.same.count = 1000;
+  if (object.same.count != 1000)
+    abort ();
+
+  /* Test object.accessor.property.  */
+  object.same.next = object;
+  if (object.same.next != object)
+    abort ();
+
+  /* Test lots of nesting.  */
+  if (object.next.next.same.same.next.next.same != object)
+    abort ();
+
+  /* Test more nesting.  */
+  MyRootClass.sharedInstance.next = object;
+  MyRootClass.sharedInstance.next.next.next.next.next.count = 2000;
+  if (MyRootClass.sharedInstance.next.next.next.next.next.count != 2000)
+    abort ();
+
+  /* Test more nesting.  */
+  MyRootClass.sharedInstance.same.same.same.same.same.count = 3000;
+  if (MyRootClass.sharedInstance.same.same.same.same.same.count != 3000)
+    abort ();
+
+  /* Test [object method].property.  */
+  [MyRootClass sharedInstance].count = 5000;
+  if ([MyRootClass sharedInstance].count != 5000)
+    abort ();
+
+  /* Just a final check.  */
+  if (shared_root.count != 5000)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-7.m b/gcc/testsuite/objc.dg/property/dotsyntax-7.m
new file mode 100644 (file)
index 0000000..15c1725
--- /dev/null
@@ -0,0 +1,48 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot syntax of a casted expression.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  id object = [[MyRootClass alloc] init];
+
+  ((MyRootClass *)object).count = 200;
+  if (((MyRootClass *)object).count != 200)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-8.m b/gcc/testsuite/objc.dg/property/dotsyntax-8.m
new file mode 100644 (file)
index 0000000..35dfda4
--- /dev/null
@@ -0,0 +1,62 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test the 'dot syntax' with typedefs.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
++ (int) classCount;
++ (void) setClassCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+@end
+
+typedef MyRootClass MyType;
+
+int main (void)
+{
+  MyType *object = [[MyRootClass alloc] init];
+
+  object.count = 1974;
+  if (object.count != 1974)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-9.m b/gcc/testsuite/objc.dg/property/dotsyntax-9.m
new file mode 100644 (file)
index 0000000..61a5c0e
--- /dev/null
@@ -0,0 +1,77 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test that setter/getters for dot-syntax are properly found even if
+   not declared in the @interface, but available in the local
+   @implementation before the current line (ie, [object name] can be
+   compiled in that case, so object.name should be compiled too).  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+static int c;
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
++ (int) classCount
+{
+  return c;
+}
++ (void) setClassCount: (int)count
+{
+  c = count;
+}
+- (int) testMe
+{
+  self.count = 400;
+  if (self.count != 400)
+    abort ();
+
+  return self.count;
+}
++ (int) testMe
+{
+  self.classCount = 4000;
+  if (self.classCount != 4000)
+    abort ();
+
+  return self.classCount;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if ([object testMe] != 400)
+    abort ();
+
+  if ([MyRootClass testMe] != 4000)
+    abort ();
+
+  return 0;
+}
+
+