Patchwork ObjC/ObjC++ - fixed Objective-C 2.0 dot-syntax with 'self' and 'super'

login
register
mail settings
Submitter Nicola Pero
Date Nov. 5, 2010, 7:18 p.m.
Message ID <1288984732.439114586@192.168.2.227>
Download mbox | patch
Permalink /patch/70285/
State New
Headers show

Comments

Nicola Pero - Nov. 5, 2010, 7:18 p.m.
This patch fixes using the Objective-C 2.0 dot-syntax with 'self' and 'super', both in class 
and instance methods.

This was nasty for a number of reasons.  The main is that properly building method calls to 'self' and 'super'
requires knowledge of the context (interface/method being compiled, etc); but our getter calls were generated 
at gimplify stage when this information is not there any more.  I experimented for a while saving/restoring
such information for the gimplification stage and it was messy and fragile as I kept realizing there was yet
another piece of information to save/restore to get all testcases to work.

Now since we were already generating a getter call expression when the 'object.accessor' expression is compiled 
(to get the getter selector in the selector table, which you can't do at gimplify stage) I finally decided to simply 
put that getter call expression into the PROPERTY_REF instead of throwing it away, so that at gimplify stage all 
there is to do is swap the PROPERTY_REF with the getter call expression (already built) available as its Operand 2.
It's a little inefficient, because if the PROPERTY_REF becomes a setter we have built a getter call but never used it
(which I was planning to maybe get rid of), but at least the getter call is always built correctly with no hacks required
and that is guaranteed because it's built at the right time in the right context.  All my testcases now work correctly. :-)

Anyway, with this patch, the following things are now fixed:

 * using the Objective-C 2.0 dot-syntax with 'self' in a class method, ie, using "self.accessor" in a class method.

 * using the Objective-C 2.0 dot-syntax with 'super' in an instance or class method, ie, using "super.accessor"
or "super.property" in an instance method, and "super.accessor" in a class method.

 * using the Objective-C 2.0 dot-syntax with 'self' in an instance/class method, and using an accessor which is not 
declared in the @interface, but was implemented in the same @implementation (exactly like it works for methods, where 
you can use [self name] if -name was implemented in the same @implementation a few lines above, even if it's not declared 
in the @interface)

As a final note, we have a testcase (property-neg-4.m) with a class and an attempt to use a class accessor which matched 
an instance accessor of the same class but no class accessor; the testcase was expected to produce an error.  But, in
the testcase the class was a root class, which means that assuming we're looking up accessors in the normal way that methods 
are looked up (which is what I implemented), the testcase would pass and run because if a class method is not found, 
the instance methods of the root class are looked up.  I was tempted to fix the testcase to have it pass, but then I 
checked the testcases for Apple's llvm-gcc and they still have the same testcase, so I assume it was intended to work 
that way (and it's not just a bug) and I changed our implementation to match that behaviour.  It should rarely matter anyway,
so I just decided to do whatever the Apple compiler does.

I added 12 testcases, covering all of the above and a number of other dot-syntax situations (cast, typedef, etc) that I looked
at while developing the patch.  They all pass with this patch. :-)

We are getting there ... 

Ok to commit to trunk ?

Thanks

In gcc/objc/:
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.
Mike Stump - Nov. 5, 2010, 7:51 p.m.
On Nov 5, 2010, at 12:18 PM, Nicola Pero wrote:
> As a final note, we have a testcase (property-neg-4.m) with a class and an attempt to use a class accessor which matched 
> an instance accessor of the same class but no class accessor; the testcase was expected to produce an error.  But, in
> the testcase the class was a root class, which means that assuming we're looking up accessors in the normal way that methods 
> are looked up (which is what I implemented), the testcase would pass and run because if a class method is not found, 
> the instance methods of the root class are looked up.  I was tempted to fix the testcase to have it pass, but then I 
> checked the testcases for Apple's llvm-gcc and they still have the same testcase, so I assume it was intended to work 
> that way (and it's not just a bug) and I changed our implementation to match that behaviour.

As time wears one, you'll want to try the code on clang for A/B comparisons and checking your understanding of Apple's understanding of the spec...

> Ok to commit to trunk ?

Ok.

Patch

Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 166333)
+++ objc/objc-act.c	(working copy)
@@ -376,9 +376,15 @@  static const char *default_constant_string_class_n
 #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];
 
@@ -1084,34 +1090,60 @@  lookup_property (tree interface_type, tree propert
 }
 
 /* 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);
       setter = lookup_method_in_protocol_list (protocol_list, setter_name, is_class);
     }
@@ -1185,13 +1217,13 @@  objc_maybe_build_component_ref (tree object, tree
   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;
@@ -1200,37 +1232,118 @@  objc_maybe_build_component_ref (tree object, tree
       || 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)
@@ -1242,58 +1355,91 @@  objc_maybe_build_component_ref (tree object, tree
 	{
 	  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 (interface_type 
+	      && (TREE_CODE (interface_type) == CLASS_INTERFACE_TYPE
+		  || TREE_CODE (interface_type) == CATEGORY_INTERFACE_TYPE
+		  || TREE_CODE (interface_type) == PROTOCOL_INTERFACE_TYPE))
+	    {
+	      /* 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 (x == NULL_TREE)
-	    {
-	      /* Ok, no property.  Try the dot-syntax without a
-		 declared property.  */
-	      x = maybe_make_artificial_property_decl (interface_type, protocol_list, 
-						       property_ident, false);
+		  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;
+      tree getter_call;
 
-      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;
-
       /* 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.
+	 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.
 
-	 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.
+	 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;
     }
@@ -1340,26 +1486,28 @@  objc_build_class_component_ref (tree class_name, t
       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
@@ -7956,13 +8104,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.  */
 
@@ -7973,6 +8124,7 @@  lookup_method_static (tree interface, tree ident,
   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)
     {
@@ -8019,11 +8171,18 @@  lookup_method_static (tree interface, tree ident,
     }
   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
@@ -12037,15 +12196,24 @@  objc_rewrite_function_call (tree function, tree fi
 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;
+  tree getter = PROPERTY_REF_GETTER_CALL (*expr_p);
+  tree call_exp;
 
-  /* TODO: Implement super.property.  */
+  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: objc/ChangeLog
===================================================================
--- objc/ChangeLog	(revision 166333)
+++ objc/ChangeLog	(working copy)
@@ -1,3 +1,28 @@ 
+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.
+	
 2010-11-04  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Fixed using the Objective-C 2.0 dot-syntax with class names.	
Index: objc/objc-tree.def
===================================================================
--- objc/objc-tree.def	(revision 166333)
+++ objc/objc-tree.def	(working copy)
@@ -44,9 +44,11 @@  DEFTREECODE (CLASS_REFERENCE_EXPR, "class_referenc
    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_referenc
 
     * 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: objc/objc-act.h
===================================================================
--- objc/objc-act.h	(revision 166333)
+++ objc/objc-act.h	(working copy)
@@ -131,7 +131,16 @@  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,
    PROTOCOL_INTERFACE_TYPE */
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 166333)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,21 @@ 
+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.
+
 2010-11-04  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Fixed using the Objective-C 2.0 dot-syntax with class names.
Index: testsuite/objc.dg/property/dotsyntax-10.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-10.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-10.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/objc.dg/property/dotsyntax-11.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-11.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-11.m	(revision 0)
@@ -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
Index: testsuite/objc.dg/property/dotsyntax-5.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-5.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-5.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/objc.dg/property/dotsyntax-6.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-6.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-6.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/objc.dg/property/dotsyntax-7.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-7.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-7.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/objc.dg/property/dotsyntax-8.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-8.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-8.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/objc.dg/property/dotsyntax-9.m
===================================================================
--- testsuite/objc.dg/property/dotsyntax-9.m	(revision 0)
+++ testsuite/objc.dg/property/dotsyntax-9.m	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-11.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-11.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-11.mm	(revision 0)
@@ -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
Index: testsuite/obj-c++.dg/property/dotsyntax-6.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-6.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-6.mm	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-8.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-8.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-8.mm	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-10.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-10.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-10.mm	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-5.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-5.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-5.mm	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-7.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-7.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-7.mm	(revision 0)
@@ -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;
+}
+
+
Index: testsuite/obj-c++.dg/property/dotsyntax-9.mm
===================================================================
--- testsuite/obj-c++.dg/property/dotsyntax-9.mm	(revision 0)
+++ testsuite/obj-c++.dg/property/dotsyntax-9.mm	(revision 0)
@@ -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;
+}
+
+