Commit 4741888d by Nicola Pero Committed by Nicola Pero

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

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.

From-SVN: r166456
parent 4ca5d2a7
2010-11-08 Nicola Pero <nicola.pero@meta-innovation.com> 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 * objc-act.c (lookup_property): When checking categories, also
check the protocols attached to each. check the protocols attached to each.
(objc_add_property_declaration): Determine the (objc_add_property_declaration): Determine the
......
...@@ -9363,7 +9363,7 @@ lookup_ivar (tree interface, tree instance_variable_name) ...@@ -9363,7 +9363,7 @@ lookup_ivar (tree interface, tree instance_variable_name)
/* This routine synthesizes a 'getter' method. This is only called /* This routine synthesizes a 'getter' method. This is only called
for @synthesize properties. */ for @synthesize properties. */
static void 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); location_t location = DECL_SOURCE_LOCATION (property);
tree fn, decl; tree fn, decl;
...@@ -9375,9 +9375,9 @@ objc_synthesize_getter (tree klass, tree class_method, tree property) ...@@ -9375,9 +9375,9 @@ objc_synthesize_getter (tree klass, tree class_method, tree property)
PROPERTY_GETTER_NAME (property))) PROPERTY_GETTER_NAME (property)))
return; return;
/* Find declaration of the property getter in the interface. There /* Find declaration of the property getter in the interface (or
must be one. TODO: Search superclasses as well. */ superclass, or protocol). There must be one. */
decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_GETTER_NAME (property)); decl = lookup_method_static (klass, PROPERTY_GETTER_NAME (property), 0);
/* If one not declared in the interface, this condition has already /* If one not declared in the interface, this condition has already
been reported as user error (because property was not declared in 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) ...@@ -9542,7 +9542,7 @@ objc_synthesize_getter (tree klass, tree class_method, tree property)
/* This routine synthesizes a 'setter' method. */ /* This routine synthesizes a 'setter' method. */
static void 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); location_t location = DECL_SOURCE_LOCATION (property);
tree fn, decl; tree fn, decl;
...@@ -9554,9 +9554,9 @@ objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro ...@@ -9554,9 +9554,9 @@ objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro
PROPERTY_SETTER_NAME (property))) PROPERTY_SETTER_NAME (property)))
return; return;
/* Find declaration of the property setter in the interface. There /* Find declaration of the property setter in the interface (or
must be one. TODO: Search superclasses as well. */ superclass, or protocol). There must be one. */
decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_SETTER_NAME (property)); decl = lookup_method_static (klass, PROPERTY_SETTER_NAME (property), 0);
/* If one not declared in the interface, this condition has already /* If one not declared in the interface, this condition has already
been reported as user error (because property was not declared in 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 ...@@ -9736,10 +9736,11 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac
{ {
/* Find the @property declaration. */ /* Find the @property declaration. */
tree property; tree property;
tree x;
/* Check that synthesize or dynamic has not already been used for /* Check that synthesize or dynamic has not already been used for
the same property. */ 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) if (PROPERTY_NAME (property) == property_name)
{ {
location_t original_location = DECL_SOURCE_LOCATION (property); location_t original_location = DECL_SOURCE_LOCATION (property);
...@@ -9756,12 +9757,9 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac ...@@ -9756,12 +9757,9 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac
return; return;
} }
/* Check that the property is declared in the interface. */ /* Check that the property is declared in the interface. It could
/* TODO: This only check the immediate class; we need to check the also be declared in a superclass or protocol. */
superclass (and categories ?) as well. */ property = lookup_property (interface, property_name);
for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
if (PROPERTY_NAME (property) == property_name)
break;
if (!property) if (!property)
{ {
...@@ -9783,18 +9781,37 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac ...@@ -9783,18 +9781,37 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac
if (ivar_name == NULL_TREE) if (ivar_name == NULL_TREE)
ivar_name = property_name; ivar_name = property_name;
/* Check that the instance variable exists. You can only use an /* Check that the instance variable exists. You can only use a
instance variable from the same class, not one from the non-private instance variable from the same class, not one from
superclass. */ 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)) 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 /* TODO: Check that the types of the instance variable and of the
property match. */ property match. */
/* TODO: Check that no other property is using the same instance /* Check that no other property is using the same instance
variable. */ 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 /* Note that a @synthesize (and only a @synthesize) always sets
PROPERTY_IVAR_NAME to a non-NULL_TREE. You can recognize a 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, ...@@ -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 /* Check that synthesize or dynamic has not already been used for
the same property. */ 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) if (PROPERTY_NAME (property) == property_name)
{ {
location_t original_location = DECL_SOURCE_LOCATION (property); location_t original_location = DECL_SOURCE_LOCATION (property);
...@@ -9912,9 +9929,10 @@ objc_add_dynamic_declaration_for_property (location_t location, tree interface, ...@@ -9912,9 +9929,10 @@ objc_add_dynamic_declaration_for_property (location_t location, tree interface,
METHOD_PROPERTY_CONTEXT that points to the original METHOD_PROPERTY_CONTEXT that points to the original
PROPERTY_DECL; when we check that these methods have been PROPERTY_DECL; when we check that these methods have been
implemented, we need to easily find that they are associated implemented, we need to easily find that they are associated
with a dynamic property. TODO: Clean this up; maybe the with a dynamic property. TODO: Remove this hack; it will not
@property PROPERTY_DECL should contain a reference to the work with properties in a protocol that may be implemented by
@dynamic PROPERTY_DECL ? */ different classes and be @dynamic in some, and non-@dynamic
in other ones. */
PROPERTY_DYNAMIC (property) = 1; PROPERTY_DYNAMIC (property) = 1;
/* We have to copy the property, because we want to chain it to /* We have to copy the property, because we want to chain it to
......
2010-11-08 Nicola Pero <nicola.pero@meta-innovation.com> 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-5.m: Updated test.
* objc.dg/property/at-property-16.m: New. * objc.dg/property/at-property-16.m: New.
* objc.dg/property/at-property-17.m: New. * objc.dg/property/at-property-17.m: New.
......
/* 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;
}
/* 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;
}
/* 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 } */
/* 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 } */
/* 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;
}
/* 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;
}
/* 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 } */
/* 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 } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment