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

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

        Implemented optional properties.
        * objc-act.h (PROPERTY_OPTIONAL): New.
        * objc-act.c (objc_add_property_declaration): Set
        PROPERTY_OPTIONAL if appropriate.
        (finish_class): When generating definitions of setter and getter
        methods associated with a property for a protocol, mark them as
        optional if the property is optional.
        (maybe_make_artificial_property_decl): Added 'getter_name'
        argument.  Set PROPERTY_OPTIONAL.
        (objc_maybe_build_component_ref): Updated calls to
        maybe_make_artificial_property_decl.  Added code for optional,
        readonly properties.
        (objc_build_class_component_ref): Updated call to
        maybe_make_artificial_property_decl.

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

        * objc.dg/property/at-property-24.m: New.
        * objc.dg/property/at-property-25.m: New.
        * obj-c++.dg/property/at-property-24.mm: New.
        * obj-c++.dg/property/at-property-25.mm: New.

From-SVN: r167197
This commit is contained in:
Nicola Pero 2010-11-27 10:06:59 +00:00 committed by Nicola Pero
parent c5589aa7e1
commit 2dd24dbdfe
8 changed files with 520 additions and 13 deletions

View File

@ -1,3 +1,20 @@
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented optional properties.
* objc-act.h (PROPERTY_OPTIONAL): New.
* objc-act.c (objc_add_property_declaration): Set
PROPERTY_OPTIONAL if appropriate.
(finish_class): When generating definitions of setter and getter
methods associated with a property for a protocol, mark them as
optional if the property is optional.
(maybe_make_artificial_property_decl): Added 'getter_name'
argument. Set PROPERTY_OPTIONAL.
(objc_maybe_build_component_ref): Updated calls to
maybe_make_artificial_property_decl. Added code for optional,
readonly properties.
(objc_build_class_component_ref): Updated call to
maybe_make_artificial_property_decl.
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (objc_build_struct): Fixed loops that save and

View File

@ -1181,7 +1181,7 @@ objc_add_property_declaration (location_t location, tree decl,
/* An existing property was found; check that it has the same
types, or it is compatible. */
location_t original_location = DECL_SOURCE_LOCATION (x);
if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic)
{
warning_at (location, 0,
@ -1293,6 +1293,13 @@ objc_add_property_declaration (location_t location, tree decl,
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
PROPERTY_DYNAMIC (property_decl) = 0;
/* Remember the fact that the property was found in the @optional
section in a @protocol, or not. */
if (objc_method_optional_flag)
PROPERTY_OPTIONAL (property_decl) = 1;
else
PROPERTY_OPTIONAL (property_decl) = 0;
/* Note that PROPERTY_GETTER_NAME is always set for all
PROPERTY_DECLs, and PROPERTY_SETTER_NAME is always set for all
PROPERTY_DECLs where PROPERTY_READONLY == 0. Any time we deal
@ -1310,18 +1317,22 @@ objc_add_property_declaration (location_t location, tree decl,
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. */
"setName:"). It is also possible to specify a different
'getter_name' (this is used for @optional readonly properties). 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 implementation,
tree protocol_list, tree component, bool is_class)
tree protocol_list, tree component, bool is_class,
tree getter_name)
{
tree getter_name = component;
tree setter_name = get_identifier (objc_build_property_setter_name (component));
tree getter = NULL_TREE;
tree setter = NULL_TREE;
if (getter_name == NULL_TREE)
getter_name = component;
/* First, check the @interface and all superclasses. */
if (interface)
{
@ -1401,6 +1412,7 @@ maybe_make_artificial_property_decl (tree interface, tree implementation,
PROPERTY_ASSIGN_SEMANTICS (property_decl) = 0;
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
PROPERTY_DYNAMIC (property_decl) = 0;
PROPERTY_OPTIONAL (property_decl) = 0;
if (!getter)
PROPERTY_HAS_NO_GETTER (property_decl) = 1;
@ -1481,7 +1493,7 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
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
@ -1493,7 +1505,25 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
NULL_TREE,
rprotos,
property_ident,
IS_CLASS (rtype));
IS_CLASS (rtype),
NULL_TREE);
}
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
{
/* This is a special, complicated case. If the
property is optional, and is read-only, then the
property is always used for reading, but an
eventual existing non-property setter can be used
for writing. We create an artificial property
decl copying the getter from the optional
property, and looking up the setter in the
interface. */
x = maybe_make_artificial_property_decl (NULL_TREE,
NULL_TREE,
rprotos,
property_ident,
false,
PROPERTY_GETTER_NAME (x));
}
}
}
@ -1538,7 +1568,22 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
x = maybe_make_artificial_property_decl
(interface_type, implementation, NULL_TREE,
property_ident,
(TREE_CODE (objc_method_context) == CLASS_METHOD_DECL));
(TREE_CODE (objc_method_context) == CLASS_METHOD_DECL),
NULL_TREE);
}
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
{
tree implementation = NULL_TREE;
if (t == self_decl)
implementation = objc_implementation_context;
x = maybe_make_artificial_property_decl (interface_type,
implementation,
NULL_TREE,
property_ident,
false,
PROPERTY_GETTER_NAME (x));
}
}
}
@ -1603,8 +1648,25 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
implementation,
protocol_list,
property_ident,
IS_CLASS (rtype));
IS_CLASS (rtype),
NULL_TREE);
}
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
{
tree implementation = NULL_TREE;
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,
false,
PROPERTY_GETTER_NAME (x));
}
}
}
}
@ -1703,7 +1765,7 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
x = maybe_make_artificial_property_decl (rtype, NULL_TREE, NULL_TREE,
property_ident,
true);
true, NULL_TREE);
if (x)
{
@ -10534,7 +10596,10 @@ finish_class (tree klass)
getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
rettype, PROPERTY_GETTER_NAME (x),
NULL_TREE, false);
objc_add_method (objc_interface_context, getter_decl, false, false);
if (PROPERTY_OPTIONAL (x))
objc_add_method (objc_interface_context, getter_decl, false, true);
else
objc_add_method (objc_interface_context, getter_decl, false, false);
METHOD_PROPERTY_CONTEXT (getter_decl) = x;
}
@ -10574,7 +10639,10 @@ finish_class (tree klass)
ret_type, selector,
build_tree_list (NULL_TREE, NULL_TREE),
false);
objc_add_method (objc_interface_context, setter_decl, false, false);
if (PROPERTY_OPTIONAL (x))
objc_add_method (objc_interface_context, setter_decl, false, true);
else
objc_add_method (objc_interface_context, setter_decl, false, false);
METHOD_PROPERTY_CONTEXT (setter_decl) = x;
}
}

View File

@ -113,6 +113,11 @@ typedef enum objc_property_assign_semantics {
setter, it is set to 1. */
#define PROPERTY_HAS_NO_SETTER(DECL) DECL_LANG_FLAG_4 (DECL)
/* PROPERTY_OPTIONAL can be 0 or 1. Normally it is 0, but if this is
a property declared as @optional in a @protocol, then it is set to
1. */
#define PROPERTY_OPTIONAL(DECL) DECL_LANG_FLAG_5 (DECL)
/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
expression. It is normally used for property access, but when
the Objective-C 2.0 "dot-syntax" (object.component) is used

View File

@ -1,3 +1,10 @@
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/property/at-property-24.m: New.
* objc.dg/property/at-property-25.m: New.
* obj-c++.dg/property/at-property-24.mm: New.
* obj-c++.dg/property/at-property-25.mm: New.
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/protocol-qualifier-1.m: New.

View File

@ -0,0 +1,118 @@
/* 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 @optional @properties. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.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
/* Use a different getters/setters, so that the only way to compile
object.countX is to find the actual @property. */
@protocol count
@required
/* @required + @synthesize. */
@property (getter=number1, setter=setNumber1:) int count1;
/* @required + manual setters/getters. */
@property (getter=number2, setter=setNumber2:) int count2;
@optional
/* @optional + @synthesize. */
@property (getter=number3, setter=setNumber3:) int count3;
/* @optional + manual setters/getters. */
@property (getter=number4, setter=setNumber4:) int count4;
@optional
/* @optional + readonly, with a setter added in the class itself. */
@property (readonly, getter=number5) int count5;
@end
@interface MySubClass : MyRootClass <count>
{
int count1;
int count2;
int count3;
int count4;
int count5;
}
- (void) setCount5: (int)value;
@end
@implementation MySubClass
@synthesize count1;
- (int) number2
{
return count2;
}
- (void) setNumber2: (int)value
{
count2 = value;
}
@synthesize count3;
- (int) number4
{
return count4;
}
- (void) setNumber4: (int)value
{
count4 = value;
}
- (int) number5
{
return count5;
}
- (void) setCount5: (int)value
{
count5 = value;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
/* First, test that @required and @optional properties work as
expected if implemented either via @synthesize or manually. */
object.count1 = 44;
if (object.count1 != 44)
abort ();
object.count2 = 88;
if (object.count2 != 88)
abort ();
object.count3 = 77;
if (object.count3 != 77)
abort ();
object.count4 = 11;
if (object.count4 != 11)
abort ();
/* Now, test the complication: @optional @property which is
readonly, but which has a setter manually implemented.
Apparently it is possible to use the dotsyntax and the @optional
@property getter is used when reading, while the manual setter is
used when writing. */
object.count5 = 99;
if (object.count5 != 99)
abort ();
return 0;
}

View File

@ -0,0 +1,87 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test warnings and non-warnings with @optional @properties. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.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 count
@optional
@property int count1;
@property (readonly) int count2;
@end
/* A class that implements all the properties. */
@interface MySubClass1 : MyRootClass <count>
{
int count1;
int count2;
}
@end
@implementation MySubClass1
@synthesize count1;
@synthesize count2;
@end
/* A class that implements nothing; no warnings as the properties are
all optional. */
@interface MySubClass2 : MyRootClass <count>
@end
@implementation MySubClass2
@end
@protocol count2
@required
@property int count1;
@property (readonly) int count2;
@end
/* A class that implements all the properties. */
@interface MySubClass3 : MyRootClass <count2>
{
int count1;
int count2;
}
@end
@implementation MySubClass3
@synthesize count1;
@synthesize count2;
@end
/* A class that implements nothing; warnings as the properties are
all required. */
@interface MySubClass4 : MyRootClass <count2>
@end
@implementation MySubClass4
@end
/* { dg-warning "incomplete implementation of class" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..setCount1:. not found" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..count1. not found" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..count2. not found" "" { target *-*-* } 81 } */
/* { dg-warning "class .MySubClass4. does not fully implement the .count2. protocol" "" { target *-*-* } 81 } */

View File

@ -0,0 +1,118 @@
/* 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 @optional @properties. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.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
/* Use a different getters/setters, so that the only way to compile
object.countX is to find the actual @property. */
@protocol count
@required
/* @required + @synthesize. */
@property (getter=number1, setter=setNumber1:) int count1;
/* @required + manual setters/getters. */
@property (getter=number2, setter=setNumber2:) int count2;
@optional
/* @optional + @synthesize. */
@property (getter=number3, setter=setNumber3:) int count3;
/* @optional + manual setters/getters. */
@property (getter=number4, setter=setNumber4:) int count4;
@optional
/* @optional + readonly, with a setter added in the class itself. */
@property (readonly, getter=number5) int count5;
@end
@interface MySubClass : MyRootClass <count>
{
int count1;
int count2;
int count3;
int count4;
int count5;
}
- (void) setCount5: (int)value;
@end
@implementation MySubClass
@synthesize count1;
- (int) number2
{
return count2;
}
- (void) setNumber2: (int)value
{
count2 = value;
}
@synthesize count3;
- (int) number4
{
return count4;
}
- (void) setNumber4: (int)value
{
count4 = value;
}
- (int) number5
{
return count5;
}
- (void) setCount5: (int)value
{
count5 = value;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
/* First, test that @required and @optional properties work as
expected if implemented either via @synthesize or manually. */
object.count1 = 44;
if (object.count1 != 44)
abort ();
object.count2 = 88;
if (object.count2 != 88)
abort ();
object.count3 = 77;
if (object.count3 != 77)
abort ();
object.count4 = 11;
if (object.count4 != 11)
abort ();
/* Now, test the complication: @optional @property which is
readonly, but which has a setter manually implemented.
Apparently it is possible to use the dotsyntax and the @optional
@property getter is used when reading, while the manual setter is
used when writing. */
object.count5 = 99;
if (object.count5 != 99)
abort ();
return 0;
}

View File

@ -0,0 +1,87 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test warnings and non-warnings with @optional @properties. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.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 count
@optional
@property int count1;
@property (readonly) int count2;
@end
/* A class that implements all the properties. */
@interface MySubClass1 : MyRootClass <count>
{
int count1;
int count2;
}
@end
@implementation MySubClass1
@synthesize count1;
@synthesize count2;
@end
/* A class that implements nothing; no warnings as the properties are
all optional. */
@interface MySubClass2 : MyRootClass <count>
@end
@implementation MySubClass2
@end
@protocol count2
@required
@property int count1;
@property (readonly) int count2;
@end
/* A class that implements all the properties. */
@interface MySubClass3 : MyRootClass <count2>
{
int count1;
int count2;
}
@end
@implementation MySubClass3
@synthesize count1;
@synthesize count2;
@end
/* A class that implements nothing; warnings as the properties are
all required. */
@interface MySubClass4 : MyRootClass <count2>
@end
@implementation MySubClass4
@end
/* { dg-warning "incomplete implementation of class" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..setCount1:. not found" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..count1. not found" "" { target *-*-* } 81 } */
/* { dg-warning "method definition for ..count2. not found" "" { target *-*-* } 81 } */
/* { dg-warning "class .MySubClass4. does not fully implement the .count2. protocol" "" { target *-*-* } 81 } */