diff mbox

ObjC/ObjC++ - fixes for @synthesize

Message ID 1289134750.960211160@192.168.2.227
State New
Headers show

Commit Message

Nicola Pero Nov. 7, 2010, 12:59 p.m. UTC
This patch (to be applied on top of my other recent patch) fixes a number of issues with @synthesize:

 * it fixes @synthesize to find @property declarations in protocols or superclasses (not necessarily
just in the immediate @interface).  Without this fix, having a @property in a @protocol and then
using @synthesize to implement it in your class would not work.

 * it fixes an ICE when @synthesize is used with a non-existing ivar.  We were already detecting
the error and printing an error message, but we'd attempt to continue, which would cause it to ICE
when synthesizing the method.  We now make a quick exit.

 * it adds a check that two properties are not being synthesized for the same ivar.  That is an error,
which we now detect.

8 testcases are included, covering all the above plus a couple of other unusual cases that I looked at,
and which already worked fine, but for which it is worth having testcases to be sure they won't break
when further changes are being made. :-)

Ok to commit to trunk ?

Thanks

PS: @dynamic does not work with @property declared in @protocols yet; that will be yet another patch.

In gcc/objc/:
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.

In gcc/testsuite/:
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.

Comments

Mike Stump Nov. 8, 2010, 9:04 p.m. UTC | #1
On Nov 7, 2010, at 4:59 AM, Nicola Pero wrote:
> This patch (to be applied on top of my other recent patch) fixes a number of issues with @synthesize:

> Ok to commit to trunk ?

Ok.
diff mbox

Patch

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 } */