diff -rupN --exclude=.svn trunk4/gcc/objc/ChangeLog trunk8/gcc/objc/ChangeLog
--- trunk4/gcc/objc/ChangeLog	2010-11-06 23:31:09.000000000 +0000
+++ trunk8/gcc/objc/ChangeLog	2010-11-07 12:44:04.000000000 +0000
@@ -1,5 +1,23 @@
 2010-11-07  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* objc-act.c (objc_add_synthesize_declaration_for_property):
+	Iterate over IMPL_PROPERTY_DECL, not CLASS_PROPERTY_DECL, when
+	checking for an existing @synthesize or @dynamic declaration.
+	Search for an inherited @property declaration if none is found in
+	the local interface.  If the required instance variable does not
+	exist, return instead of trying to continue to prevent a compiler
+	crash later.  Check that the instance variable is not already
+	being used by another @synthesize.
+	(objc_add_dynamic_declaration_for_property): Iterate over
+	IMPL_PROPERTY_DECL, not CLASS_PROPERTY_DECL, when checking for an
+	existing @synthesize or @dynamic declaration.
+	(objc_synthesize_getter): Search for the getter declaration in
+	protocols and superclasses as well.
+	(objc_synthesize_setter): Search for the setter declaration in
+	protocols and superclasses as well.
+	
+2010-11-07  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* objc-act.c (lookup_property): When checking categories, also
 	check the protocols attached to each.
 	(objc_add_property_declaration): Determine the
diff -rupN --exclude=.svn trunk4/gcc/objc/objc-act.c trunk8/gcc/objc/objc-act.c
--- trunk4/gcc/objc/objc-act.c	2010-11-06 22:53:18.000000000 +0000
+++ trunk8/gcc/objc/objc-act.c	2010-11-07 12:34:17.000000000 +0000
@@ -9363,7 +9363,7 @@ lookup_ivar (tree interface, tree instan
 /* This routine synthesizes a 'getter' method.  This is only called
    for @synthesize properties.  */
 static void
-objc_synthesize_getter (tree klass, tree class_method, tree property)
+objc_synthesize_getter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree property)
 {
   location_t location = DECL_SOURCE_LOCATION (property);
   tree fn, decl;
@@ -9375,9 +9375,9 @@ objc_synthesize_getter (tree klass, tree
 		     PROPERTY_GETTER_NAME (property)))
     return;
 
-  /* Find declaration of the property getter in the interface. There
-     must be one.  TODO: Search superclasses as well.  */
-  decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_GETTER_NAME (property));
+  /* Find declaration of the property getter in the interface (or
+     superclass, or protocol). There must be one.  */
+  decl = lookup_method_static (klass, PROPERTY_GETTER_NAME (property), 0);
 
   /* If one not declared in the interface, this condition has already
      been reported as user error (because property was not declared in
@@ -9542,7 +9542,7 @@ objc_synthesize_getter (tree klass, tree
 /* This routine synthesizes a 'setter' method.  */
 
 static void
-objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
+objc_synthesize_setter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree property)
 {
   location_t location = DECL_SOURCE_LOCATION (property);
   tree fn, decl;
@@ -9554,9 +9554,9 @@ objc_synthesize_setter (tree klass ATTRI
 		     PROPERTY_SETTER_NAME (property)))
     return;
 
-  /* Find declaration of the property setter in the interface. There
-     must be one.  TODO: Search superclasses as well.  */
-  decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_SETTER_NAME (property));
+  /* Find declaration of the property setter in the interface (or
+     superclass, or protocol). There must be one.  */
+  decl = lookup_method_static (klass, PROPERTY_SETTER_NAME (property), 0);
 
   /* If one not declared in the interface, this condition has already
      been reported as user error (because property was not declared in
@@ -9736,10 +9736,11 @@ objc_add_synthesize_declaration_for_prop
 {
   /* Find the @property declaration.  */
   tree property;
+  tree x;
 
   /* Check that synthesize or dynamic has not already been used for
      the same property.  */
-  for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+  for (property = IMPL_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
     if (PROPERTY_NAME (property) == property_name)
       {
 	location_t original_location = DECL_SOURCE_LOCATION (property);
@@ -9756,12 +9757,9 @@ objc_add_synthesize_declaration_for_prop
 	return;
       }
 
-  /* Check that the property is declared in the interface.  */
-  /* TODO: This only check the immediate class; we need to check the
-     superclass (and categories ?) as well.  */
-  for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
-    if (PROPERTY_NAME (property) == property_name)
-      break;
+  /* Check that the property is declared in the interface.  It could
+     also be declared in a superclass or protocol.  */
+  property = lookup_property (interface, property_name);
 
   if (!property)
     {
@@ -9783,18 +9781,37 @@ objc_add_synthesize_declaration_for_prop
   if (ivar_name == NULL_TREE)
     ivar_name = property_name;
 
-  /* Check that the instance variable exists.  You can only use an
-     instance variable from the same class, not one from the
-     superclass.  */
+  /* Check that the instance variable exists.  You can only use a
+     non-private instance variable from the same class, not one from
+     the superclass (this makes sense as it allows us to check that an
+     instance variable is only used in one synthesized property).  */
   if (!is_ivar (CLASS_IVARS (interface), ivar_name))
-    error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", 
-	      IDENTIFIER_POINTER (property_name));
+    {
+      error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", 
+		IDENTIFIER_POINTER (property_name));
+      return;
+    }
 
   /* TODO: Check that the types of the instance variable and of the
      property match.  */
 
-  /* TODO: Check that no other property is using the same instance
+  /* Check that no other property is using the same instance
      variable.  */
+  for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
+    if (PROPERTY_IVAR_NAME (x) == ivar_name)
+      {
+	location_t original_location = DECL_SOURCE_LOCATION (x);
+	
+	error_at (location, "property %qs is using the same instance variable as property %qs",
+		  IDENTIFIER_POINTER (property_name),
+		  IDENTIFIER_POINTER (PROPERTY_NAME (x)));
+	
+	if (original_location != UNKNOWN_LOCATION)
+	  inform (original_location, "originally specified here");
+	
+	/* We keep going on.  This won't cause the compiler to fail;
+	   the failure would most likely be at runtime.  */
+      }
 
   /* Note that a @synthesize (and only a @synthesize) always sets
      PROPERTY_IVAR_NAME to a non-NULL_TREE.  You can recognize a
@@ -9876,7 +9893,7 @@ objc_add_dynamic_declaration_for_propert
 
   /* Check that synthesize or dynamic has not already been used for
      the same property.  */
-  for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+  for (property = IMPL_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
     if (PROPERTY_NAME (property) == property_name)
       {
 	location_t original_location = DECL_SOURCE_LOCATION (property);
@@ -9912,9 +9929,10 @@ objc_add_dynamic_declaration_for_propert
 	 METHOD_PROPERTY_CONTEXT that points to the original
 	 PROPERTY_DECL; when we check that these methods have been
 	 implemented, we need to easily find that they are associated
-	 with a dynamic property.  TODO: Clean this up; maybe the
-	 @property PROPERTY_DECL should contain a reference to the
-	 @dynamic PROPERTY_DECL ? */
+	 with a dynamic property.  TODO: Remove this hack; it will not
+	 work with properties in a protocol that may be implemented by
+	 different classes and be @dynamic in some, and non-@dynamic
+	 in other ones.  */
       PROPERTY_DYNAMIC (property) = 1;
 
       /* We have to copy the property, because we want to chain it to
diff -rupN --exclude=.svn trunk4/gcc/testsuite/ChangeLog trunk8/gcc/testsuite/ChangeLog
--- trunk4/gcc/testsuite/ChangeLog	2010-11-06 23:42:14.000000000 +0000
+++ trunk8/gcc/testsuite/ChangeLog	2010-11-07 12:47:16.000000000 +0000
@@ -1,5 +1,16 @@
 2010-11-07  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* objc.dg/property/synthesize-3.m: New.
+	* objc.dg/property/synthesize-4.m: New.
+	* objc.dg/property/synthesize-5.m: New.
+	* objc.dg/property/synthesize-6.m: New.
+	* obj-c++.dg/property/synthesize-3.mm: New.
+	* obj-c++.dg/property/synthesize-4.mm: New.
+	* obj-c++.dg/property/synthesize-5.mm: New.
+	* obj-c++.dg/property/synthesize-6.mm: New.	
+	
+2010-11-07  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* objc.dg/property/at-property-5.m: Updated test.	
 	* objc.dg/property/at-property-16.m: New.
 	* objc.dg/property/at-property-17.m: New.
diff -rupN --exclude=.svn trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm
--- trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm	2010-11-07 12:47:32.000000000 +0000
@@ -0,0 +1,66 @@
+/* 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 @synthesize for a @property which is not declared directly in
+   the @interface, but in a @protocol that the @interface conforms
+   to.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@protocol MyProtocol
+@property int v1;
+@end
+
+@protocol MyProtocol2
+@property int v2;
+@end
+
+@interface Test : MyRootClass <MyProtocol, MyProtocol2>
+{
+  int v1;
+  int _v2;
+}
+@end
+
+@implementation Test
+@synthesize v1;
+@synthesize v2 = _v2;
+@end
+
+int main (void)
+{
+  Test *object = [[Test alloc] init];
+
+  /* Check that the synthesized methods exist and work.  Do not invoke
+     them via property syntax - that is another test.  Here we just
+     want to test the synthesis of the methods.  */
+  [object setV1: 400];
+
+  if ([object v1] != 400)
+    abort ();
+
+  [object setV2: 31];
+
+  if ([object v2] != 31)
+    abort ();
+
+  return 0;
+}
diff -rupN --exclude=.svn trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm
--- trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm	2010-11-07 12:47:35.000000000 +0000
@@ -0,0 +1,67 @@
+/* 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 @synthesize for a @property where the setter/getter are also
+   declared by the user.  This is fine.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@protocol MyProtocol
+@property int v1;
+@end
+
+@protocol MyProtocol2
+@property int v2;
+@end
+
+@interface Test : MyRootClass <MyProtocol, MyProtocol2>
+{
+  int v1;
+  int _v2;
+}
+- (int)v1;
+- (void)setV1: (int)aNumber;
+- (int)v2;
+@end
+
+@implementation Test
+@synthesize v1;
+@synthesize v2 = _v2;
+@end
+
+int main (void)
+{
+  Test *object = [[Test alloc] init];
+
+  /* We use dot-syntax here as this is just a general test that
+     user-declared setters/getters don't cause confusion.  */
+  object.v1 = 400;
+
+  if (object.v1 != 400)
+    abort ();
+
+  object.v2 = 31;
+
+  if (object.v2 != 31)
+    abort ();
+
+  return 0;
+}
diff -rupN --exclude=.svn trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm
--- trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm	2010-11-07 12:47:39.000000000 +0000
@@ -0,0 +1,18 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that @synthesize does not ICE if asked to use a non-existing
+   ivar.  */
+
+#include <objc/objc.h>
+
+@interface Test
+@property int v1;
+@end
+
+@implementation Test
+@synthesize v1;       /* { dg-error "must be an existing ivar" } */
+@end
+/* { dg-warning "incomplete implementation" "" { target *-*-* } 15 } */
+/* { dg-warning "method definition for .-setV1:. not found" "" { target *-*-* } 15 } */
+/* { dg-warning "method definition for .-v1. not found" "" { target *-*-* } 15 } */
diff -rupN --exclude=.svn trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm
--- trunk4/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm	2010-11-07 12:52:35.000000000 +0000
@@ -0,0 +1,32 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that each @synthesize is using a different instance variable,
+   and that it must belong to the class (not to a superclass).  */
+
+#include <objc/objc.h>
+
+@interface Test
+{
+  int v;
+  int w;
+}
+@property int v1;
+@property int v2;
+@end
+#if 0 /* This is a problem in the testsuite; the compiler is fine, but the testsuite still barfs on the following.  */
+@implementation Test
+@synthesize v1 = v;  /* dg-message "originally specified here" */
+@synthesize v2 = v;  /* dg-error "property .v2. is using the same instance variable as property .v1." */
+@end
+#endif
+@interface Test2 : Test
+@property int w1;
+@end
+
+@implementation Test2
+@synthesize w1;      /* { dg-error "ivar .w1. used by .@synthesize. declaration must be an existing ivar" } */
+@end
+/* { dg-warning "incomplete implementation" "" { target *-*-* } 29 } */
+/* { dg-warning "method definition for .-setW1:. not found" "" { target *-*-* } 29 } */
+/* { dg-warning "method definition for .-w1. not found" "" { target *-*-* } 29 } */
diff -rupN --exclude=.svn trunk4/gcc/testsuite/objc.dg/property/synthesize-3.m trunk8/gcc/testsuite/objc.dg/property/synthesize-3.m
--- trunk4/gcc/testsuite/objc.dg/property/synthesize-3.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/objc.dg/property/synthesize-3.m	2010-11-07 11:24:22.000000000 +0000
@@ -0,0 +1,66 @@
+/* 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 @synthesize for a @property which is not declared directly in
+   the @interface, but in a @protocol that the @interface conforms
+   to.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@protocol MyProtocol
+@property int v1;
+@end
+
+@protocol MyProtocol2
+@property int v2;
+@end
+
+@interface Test : MyRootClass <MyProtocol, MyProtocol2>
+{
+  int v1;
+  int _v2;
+}
+@end
+
+@implementation Test
+@synthesize v1;
+@synthesize v2 = _v2;
+@end
+
+int main (void)
+{
+  Test *object = [[Test alloc] init];
+
+  /* Check that the synthesized methods exist and work.  Do not invoke
+     them via property syntax - that is another test.  Here we just
+     want to test the synthesis of the methods.  */
+  [object setV1: 400];
+
+  if ([object v1] != 400)
+    abort ();
+
+  [object setV2: 31];
+
+  if ([object v2] != 31)
+    abort ();
+
+  return 0;
+}
diff -rupN --exclude=.svn trunk4/gcc/testsuite/objc.dg/property/synthesize-4.m trunk8/gcc/testsuite/objc.dg/property/synthesize-4.m
--- trunk4/gcc/testsuite/objc.dg/property/synthesize-4.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/objc.dg/property/synthesize-4.m	2010-11-07 11:24:23.000000000 +0000
@@ -0,0 +1,67 @@
+/* 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 @synthesize for a @property where the setter/getter are also
+   declared by the user.  This is fine.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@protocol MyProtocol
+@property int v1;
+@end
+
+@protocol MyProtocol2
+@property int v2;
+@end
+
+@interface Test : MyRootClass <MyProtocol, MyProtocol2>
+{
+  int v1;
+  int _v2;
+}
+- (int)v1;
+- (void)setV1: (int)aNumber;
+- (int)v2;
+@end
+
+@implementation Test
+@synthesize v1;
+@synthesize v2 = _v2;
+@end
+
+int main (void)
+{
+  Test *object = [[Test alloc] init];
+
+  /* We use dot-syntax here as this is just a general test that
+     user-declared setters/getters don't cause confusion.  */
+  object.v1 = 400;
+
+  if (object.v1 != 400)
+    abort ();
+
+  object.v2 = 31;
+
+  if (object.v2 != 31)
+    abort ();
+
+  return 0;
+}
diff -rupN --exclude=.svn trunk4/gcc/testsuite/objc.dg/property/synthesize-5.m trunk8/gcc/testsuite/objc.dg/property/synthesize-5.m
--- trunk4/gcc/testsuite/objc.dg/property/synthesize-5.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/objc.dg/property/synthesize-5.m	2010-11-07 12:09:26.000000000 +0000
@@ -0,0 +1,18 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that @synthesize does not ICE if asked to use a non-existing
+   ivar.  */
+
+#include <objc/objc.h>
+
+@interface Test
+@property int v1;
+@end
+
+@implementation Test
+@synthesize v1;       /* { dg-error "must be an existing ivar" } */
+@end
+/* { dg-warning "incomplete implementation" "" { target *-*-* } 15 } */
+/* { dg-warning "method definition for .-setV1:. not found" "" { target *-*-* } 15 } */
+/* { dg-warning "method definition for .-v1. not found" "" { target *-*-* } 15 } */
diff -rupN --exclude=.svn trunk4/gcc/testsuite/objc.dg/property/synthesize-6.m trunk8/gcc/testsuite/objc.dg/property/synthesize-6.m
--- trunk4/gcc/testsuite/objc.dg/property/synthesize-6.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/objc.dg/property/synthesize-6.m	2010-11-07 12:20:31.000000000 +0000
@@ -0,0 +1,32 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test that each @synthesize is using a different instance variable,
+   and that it must belong to the class (not to a superclass).  */
+
+#include <objc/objc.h>
+
+@interface Test
+{
+  int v;
+  int w;
+}
+@property int v1;
+@property int v2;
+@end
+
+@implementation Test
+@synthesize v1 = v;  /* { dg-message "originally specified here" } */
+@synthesize v2 = v;  /* { dg-error "property .v2. is using the same instance variable as property .v1." } */
+@end
+
+@interface Test2 : Test
+@property int w1;
+@end
+
+@implementation Test2
+@synthesize w1;      /* { dg-error "ivar .w1. used by .@synthesize. declaration must be an existing ivar" } */
+@end
+/* { dg-warning "incomplete implementation" "" { target *-*-* } 29 } */
+/* { dg-warning "method definition for .-setW1:. not found" "" { target *-*-* } 29 } */
+/* { dg-warning "method definition for .-w1. not found" "" { target *-*-* } 29 } */
