summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-08 22:04:03 +0000
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-08 22:04:03 +0000
commitc84ce30ab797252d51a4e5366be0d8cc6ade7057 (patch)
treee521b56c661feaac63138566fed5a623b044b767 /gcc
parent7f5203a813f3a6eeace3f7517a567e38f14b2290 (diff)
downloadgcc-c84ce30ab797252d51a4e5366be0d8cc6ade7057.tar.gz
In gcc/objc/:
2010-11-08 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-08 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166456 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/objc/ChangeLog18
-rw-r--r--gcc/objc/objc-act.c68
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-3.mm66
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-4.mm67
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-5.mm18
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-6.mm32
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-3.m66
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-4.m67
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-5.m18
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-6.m32
11 files changed, 438 insertions, 25 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 93c9f3e544a..6ba9514af10 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,5 +1,23 @@
2010-11-08 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-08 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 --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index db41dcab0ac..ff694147ce2 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -9363,7 +9363,7 @@ lookup_ivar (tree interface, tree instance_variable_name)
/* 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 class_method, tree property)
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 class_method, tree property)
/* 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 ATTRIBUTE_UNUSED, tree class_method, tree pro
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_property (location_t location, tree interfac
{
/* 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_property (location_t location, tree interfac
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_property (location_t location, tree interfac
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_property (location_t location, tree interface,
/* 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_property (location_t location, tree interface,
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 --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 97b3f51ddd4..d4d274a04d4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,16 @@
2010-11-08 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-08 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 --git a/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm
new file mode 100644
index 00000000000..8669905316a
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-3.mm
@@ -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 --git a/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm
new file mode 100644
index 00000000000..602dc68b468
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-4.mm
@@ -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 --git a/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm
new file mode 100644
index 00000000000..0871b63ee21
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-5.mm
@@ -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 --git a/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm
new file mode 100644
index 00000000000..2d039279430
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm
@@ -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 --git a/gcc/testsuite/objc.dg/property/synthesize-3.m b/gcc/testsuite/objc.dg/property/synthesize-3.m
new file mode 100644
index 00000000000..8669905316a
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-3.m
@@ -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 --git a/gcc/testsuite/objc.dg/property/synthesize-4.m b/gcc/testsuite/objc.dg/property/synthesize-4.m
new file mode 100644
index 00000000000..602dc68b468
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-4.m
@@ -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 --git a/gcc/testsuite/objc.dg/property/synthesize-5.m b/gcc/testsuite/objc.dg/property/synthesize-5.m
new file mode 100644
index 00000000000..0871b63ee21
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-5.m
@@ -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 --git a/gcc/testsuite/objc.dg/property/synthesize-6.m b/gcc/testsuite/objc.dg/property/synthesize-6.m
new file mode 100644
index 00000000000..19f7c953491
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-6.m
@@ -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 } */