In gcc/objc/: 2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (maybe_make_artificial_property_decl): New. (objc_maybe_build_component_ref): Call maybe_make_artificial_property_decl if a property can not be found. Do not call objc_finish_message_expr if PROPERTY_HAS_NO_GETTER. * objc-act.h Updated comments. (PROPERTY_HAS_NO_GETTER): New. (PROPERTY_HAS_NO_SETTER): New. * objc-tree.def: Updated comment. In gcc/testsuite/: 2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/property/dotsyntax-1.m: New. * objc.dg/property/dotsyntax-2.m: New. * obj-c++.dg/property/dotsyntax-1.mm: New. * obj-c++.dg/property/dotsyntax-2.mm: New. From-SVN: r166237
This commit is contained in:
parent
87c20fe762
commit
43236c265b
@ -1,3 +1,15 @@
|
||||
2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc-act.c (maybe_make_artificial_property_decl): New.
|
||||
(objc_maybe_build_component_ref): Call
|
||||
maybe_make_artificial_property_decl if a property can not be
|
||||
found. Do not call objc_finish_message_expr if
|
||||
PROPERTY_HAS_NO_GETTER.
|
||||
* objc-act.h Updated comments.
|
||||
(PROPERTY_HAS_NO_GETTER): New.
|
||||
(PROPERTY_HAS_NO_SETTER): New.
|
||||
* objc-tree.def: Updated comment.
|
||||
|
||||
2010-11-01 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
Implemented format and noreturn attributes for Objective-C methods.
|
||||
|
@ -1053,16 +1053,102 @@ lookup_property (tree interface_type, tree property)
|
||||
return inter;
|
||||
}
|
||||
|
||||
/* This is a subroutine of objc_maybe_build_component_ref. Search the
|
||||
list of methods in the interface (and, failing that, 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. */
|
||||
static tree
|
||||
maybe_make_artificial_property_decl (tree interface, tree protocol_list, tree component, bool is_class)
|
||||
{
|
||||
tree getter_name = component;
|
||||
tree setter_name = get_identifier (objc_build_property_setter_name (component));
|
||||
tree getter = NULL_TREE;
|
||||
tree setter = NULL_TREE;
|
||||
|
||||
if (interface)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (is_class)
|
||||
flags = OBJC_LOOKUP_CLASS;
|
||||
|
||||
getter = lookup_method_static (interface, getter_name, flags);
|
||||
setter = lookup_method_static (interface, setter_name, flags);
|
||||
}
|
||||
|
||||
/* Try the protocol_list if we didn't find anything in the interface. */
|
||||
if (!getter && !setter)
|
||||
{
|
||||
getter = lookup_method_in_protocol_list (protocol_list, getter_name, is_class);
|
||||
setter = lookup_method_in_protocol_list (protocol_list, setter_name, is_class);
|
||||
}
|
||||
|
||||
/* There needs to be at least a getter or setter for this to be a
|
||||
valid 'object.component' syntax. */
|
||||
if (getter || setter)
|
||||
{
|
||||
/* Yes ... determine the type of the expression. */
|
||||
tree property_decl;
|
||||
tree type;
|
||||
|
||||
if (getter)
|
||||
type = TREE_VALUE (TREE_TYPE (getter));
|
||||
else
|
||||
type = TREE_VALUE (TREE_TYPE (METHOD_SEL_ARGS (setter)));
|
||||
|
||||
/* Create an artificial property declaration with the
|
||||
information we collected on the type and getter/setter
|
||||
names. */
|
||||
property_decl = make_node (PROPERTY_DECL);
|
||||
|
||||
TREE_TYPE (property_decl) = type;
|
||||
DECL_SOURCE_LOCATION (property_decl) = input_location;
|
||||
TREE_DEPRECATED (property_decl) = 0;
|
||||
DECL_ARTIFICIAL (property_decl) = 1;
|
||||
|
||||
/* Add property-specific information. Note that one of
|
||||
PROPERTY_GETTER_NAME or PROPERTY_SETTER_NAME may refer to a
|
||||
non-existing method; this will generate an error when the
|
||||
expression is later compiled. At this stage we don't know if
|
||||
the getter or setter will be used, so we can't generate an
|
||||
error. */
|
||||
PROPERTY_NAME (property_decl) = component;
|
||||
PROPERTY_GETTER_NAME (property_decl) = getter_name;
|
||||
PROPERTY_SETTER_NAME (property_decl) = setter_name;
|
||||
PROPERTY_READONLY (property_decl) = 0;
|
||||
PROPERTY_NONATOMIC (property_decl) = 0;
|
||||
PROPERTY_ASSIGN_SEMANTICS (property_decl) = 0;
|
||||
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
|
||||
PROPERTY_DYNAMIC (property_decl) = 0;
|
||||
|
||||
if (!getter)
|
||||
PROPERTY_HAS_NO_GETTER (property_decl) = 1;
|
||||
|
||||
/* The following is currently unused, but it's nice to have
|
||||
there. We may use it if we need in the future. */
|
||||
if (!setter)
|
||||
PROPERTY_HAS_NO_SETTER (property_decl) = 1;
|
||||
|
||||
return property_decl;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* This hook routine is invoked by the parser when an expression such
|
||||
as 'xxx.yyy' is parsed. We get a chance to process these
|
||||
expressions in a way that is specified to Objective-C (to implement
|
||||
properties, or non-fragile ivars). If the expression is not an
|
||||
Objective-C specified expression, we should return NULL_TREE; else
|
||||
we return the expression.
|
||||
the Objective-C 2.0 dot-syntax, properties, or non-fragile ivars).
|
||||
If the expression is not an Objective-C specified expression, we
|
||||
should return NULL_TREE; else we return the expression.
|
||||
|
||||
At the moment this only implements properties (not non-fragile
|
||||
ivars yet), ie 'object.property'. */
|
||||
At the moment this only implements dot-syntax and properties (not
|
||||
non-fragile ivars yet), ie 'object.property' or 'object.component'
|
||||
where 'component' is not a declared property, but a valid getter or
|
||||
setter for it could be found. */
|
||||
tree
|
||||
objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
{
|
||||
@ -1089,6 +1175,17 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
: NULL_TREE);
|
||||
if (rprotos)
|
||||
x = lookup_property_in_protocol_list (rprotos, property_ident);
|
||||
|
||||
if (x == NULL_TREE)
|
||||
{
|
||||
/* Ok, no property. Maybe it was an object.component
|
||||
dot-syntax without a declared property. Look for
|
||||
getter/setter methods and internally declare an artifical
|
||||
property based on them if found. */
|
||||
x = maybe_make_artificial_property_decl (NULL_TREE, rprotos,
|
||||
property_ident,
|
||||
false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1115,6 +1212,14 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
|
||||
if (x == NULL_TREE)
|
||||
x = lookup_property_in_protocol_list (protocol_list, property_ident);
|
||||
|
||||
if (x == NULL_TREE)
|
||||
{
|
||||
/* Ok, no property. Try the dot-syntax without a
|
||||
declared property. */
|
||||
x = maybe_make_artificial_property_decl (interface_type, protocol_list,
|
||||
property_ident, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,10 +1249,16 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
|
||||
TODO: This can be made more efficient; in particular we don't
|
||||
need to build the whole message call, we could just work on
|
||||
the selector. */
|
||||
objc_finish_message_expr (object,
|
||||
PROPERTY_GETTER_NAME (x),
|
||||
NULL_TREE);
|
||||
the selector.
|
||||
|
||||
If the PROPERTY_HAS_NO_GETTER() (ie, it is an artificial
|
||||
property decl created to deal with a dotsyntax not really
|
||||
referring to an existing property) then do not try to build a
|
||||
call to the getter as there is no getter. */
|
||||
if (!PROPERTY_HAS_NO_GETTER (x))
|
||||
objc_finish_message_expr (object,
|
||||
PROPERTY_GETTER_NAME (x),
|
||||
NULL_TREE);
|
||||
|
||||
return expression;
|
||||
}
|
||||
@ -1197,6 +1308,9 @@ objc_maybe_build_modify_expr (tree lhs, tree rhs)
|
||||
{
|
||||
tree setter_argument = build_tree_list (NULL_TREE, rhs);
|
||||
tree setter;
|
||||
|
||||
/* TODO: Check that the setter return type is 'void'. */
|
||||
|
||||
/* TODO: Decay argument in C. */
|
||||
setter = objc_finish_message_expr (object_expr,
|
||||
PROPERTY_SETTER_NAME (property_decl),
|
||||
|
@ -62,6 +62,11 @@ tree objc_eh_personality (void);
|
||||
|
||||
/* TREE_TYPE is the type (int, float, etc) of the property. */
|
||||
|
||||
/* DECL_ARTIFICIAL is set to 1 if the PROPERTY_DECL is an artificial
|
||||
property declaration created when the dot-syntax object.component
|
||||
is used with no actual @property matching the component, but a
|
||||
valid getter/setter. */
|
||||
|
||||
/* PROPERTY_NAME is the name of the property. */
|
||||
#define PROPERTY_NAME(DECL) DECL_NAME(DECL)
|
||||
|
||||
@ -99,9 +104,21 @@ typedef enum objc_property_assign_semantics {
|
||||
declaration has been parsed); otherwise, it is set to 0. */
|
||||
#define PROPERTY_DYNAMIC(DECL) DECL_LANG_FLAG_2 (DECL)
|
||||
|
||||
/* PROPERTY_HAS_NO_GETTER can be 0 or 1. Normally it is 0, but if
|
||||
this is an artificial PROPERTY_DECL that we generate even without a
|
||||
getter, it is set to 1. */
|
||||
#define PROPERTY_HAS_NO_GETTER(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||
|
||||
/* PROPERTY_HAS_NO_SETTER can be 0 or 1. Normally it is 0, but if
|
||||
this is an artificial PROPERTY_DECL that we generate even without a
|
||||
setter, it is set to 1. */
|
||||
#define PROPERTY_HAS_NO_SETTER(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
|
||||
/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
|
||||
expression. */
|
||||
expression. It is normally used for property access, but when
|
||||
the Objective-C 2.0 "dot-syntax" (object.component) is used
|
||||
with no matching property, a PROPERTY_REF is still created to
|
||||
represent it, with an artificial PROPERTY_DECL. */
|
||||
|
||||
/* PROPERTY_REF_OBJECT is the object whose property we are
|
||||
accessing. */
|
||||
@ -109,7 +126,9 @@ typedef enum objc_property_assign_semantics {
|
||||
|
||||
/* PROPERTY_REF_PROPERTY_DECL is the PROPERTY_DECL for the property
|
||||
used in the expression. From it, you can get the property type,
|
||||
and the getter/setter names. */
|
||||
and the getter/setter names. This PROPERTY_DECL could be artificial
|
||||
if we are processing an 'object.component' syntax with no matching
|
||||
declared property. */
|
||||
#define PROPERTY_REF_PROPERTY_DECL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 1)
|
||||
|
||||
|
||||
|
@ -55,7 +55,11 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
|
||||
* else, it will remain as a PROPERTY_REF until we get to
|
||||
gimplification; at that point, we convert each PROPERTY_REF into
|
||||
a 'getter' call during ObjC/ObjC++ gimplify.
|
||||
*/
|
||||
|
||||
Please note that when the Objective-C 2.0 "dot-syntax" 'object.component'
|
||||
is encountered, where 'component' is not a property but there are valid
|
||||
setter/getter methods for it, an artificial PROPERTY_DECL is generated
|
||||
and used in the PROPERTY_REF. */
|
||||
DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 2)
|
||||
|
||||
/*
|
||||
|
@ -1,3 +1,10 @@
|
||||
2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc.dg/property/dotsyntax-1.m: New.
|
||||
* objc.dg/property/dotsyntax-2.m: New.
|
||||
* obj-c++.dg/property/dotsyntax-1.mm: New.
|
||||
* obj-c++.dg/property/dotsyntax-2.mm: New.
|
||||
|
||||
2010-11-03 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/46165
|
||||
|
62
gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm
Normal file
62
gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm
Normal file
@ -0,0 +1,62 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Test the 'dot syntax' without a declarated property. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
int a;
|
||||
id b;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
- (int) count;
|
||||
- (void) setCount: (int)value;
|
||||
- (id) next;
|
||||
- (void) setNext: (id)value;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
- (int) count
|
||||
{
|
||||
return a;
|
||||
}
|
||||
- (void) setCount: (int)value
|
||||
{
|
||||
a = value;
|
||||
}
|
||||
- (id) next
|
||||
{
|
||||
return b;
|
||||
}
|
||||
- (void) setNext: (id)value
|
||||
{
|
||||
b = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MyRootClass *object = [[MyRootClass alloc] init];
|
||||
|
||||
object.count = 40;
|
||||
if (object.count != 40)
|
||||
abort ();
|
||||
|
||||
object.next = object;
|
||||
if (object.next != object)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
71
gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm
Normal file
71
gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm
Normal file
@ -0,0 +1,71 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Test the 'dot syntax' without a declarated property. This tests the case where
|
||||
only the setter (or only the getter) exists. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
int a;
|
||||
id b;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
- (int) a;
|
||||
- (void) setCount: (int)value;
|
||||
- (id) b;
|
||||
- (void) setNext: (id)value;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
- (int) a
|
||||
{
|
||||
return a;
|
||||
}
|
||||
- (void) setCount: (int)value
|
||||
{
|
||||
a = value;
|
||||
}
|
||||
- (id) b
|
||||
{
|
||||
return b;
|
||||
}
|
||||
- (void) setNext: (id)value
|
||||
{
|
||||
b = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MyRootClass *object = [[MyRootClass alloc] init];
|
||||
|
||||
/* This should work because -setCount: exists (even if -count does
|
||||
not). */
|
||||
object.count = 40;
|
||||
|
||||
/* This should work because -a exists (even if -setA: does not). */
|
||||
if (object.a != 40)
|
||||
abort ();
|
||||
|
||||
/* This should work because -setNext: exists (even if -next does
|
||||
not). */
|
||||
object.next = object;
|
||||
|
||||
/* This should work because -b exists (even if -setB: does not). */
|
||||
if (object.b != object)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
62
gcc/testsuite/objc.dg/property/dotsyntax-1.m
Normal file
62
gcc/testsuite/objc.dg/property/dotsyntax-1.m
Normal file
@ -0,0 +1,62 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Test the 'dot syntax' without a declarated property. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
int a;
|
||||
id b;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
- (int) count;
|
||||
- (void) setCount: (int)value;
|
||||
- (id) next;
|
||||
- (void) setNext: (id)value;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
- (int) count
|
||||
{
|
||||
return a;
|
||||
}
|
||||
- (void) setCount: (int)value
|
||||
{
|
||||
a = value;
|
||||
}
|
||||
- (id) next
|
||||
{
|
||||
return b;
|
||||
}
|
||||
- (void) setNext: (id)value
|
||||
{
|
||||
b = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MyRootClass *object = [[MyRootClass alloc] init];
|
||||
|
||||
object.count = 40;
|
||||
if (object.count != 40)
|
||||
abort ();
|
||||
|
||||
object.next = object;
|
||||
if (object.next != object)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
71
gcc/testsuite/objc.dg/property/dotsyntax-2.m
Normal file
71
gcc/testsuite/objc.dg/property/dotsyntax-2.m
Normal file
@ -0,0 +1,71 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
|
||||
/* Test the 'dot syntax' without a declarated property. This tests the case where
|
||||
only the setter (or only the getter) exists. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MyRootClass
|
||||
{
|
||||
Class isa;
|
||||
int a;
|
||||
id b;
|
||||
}
|
||||
+ (id) initialize;
|
||||
+ (id) alloc;
|
||||
- (id) init;
|
||||
- (int) a;
|
||||
- (void) setCount: (int)value;
|
||||
- (id) b;
|
||||
- (void) setNext: (id)value;
|
||||
@end
|
||||
|
||||
@implementation MyRootClass
|
||||
+ (id) initialize { return self; }
|
||||
+ (id) alloc { return class_createInstance (self, 0); }
|
||||
- (id) init { return self; }
|
||||
- (int) a
|
||||
{
|
||||
return a;
|
||||
}
|
||||
- (void) setCount: (int)value
|
||||
{
|
||||
a = value;
|
||||
}
|
||||
- (id) b
|
||||
{
|
||||
return b;
|
||||
}
|
||||
- (void) setNext: (id)value
|
||||
{
|
||||
b = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MyRootClass *object = [[MyRootClass alloc] init];
|
||||
|
||||
/* This should work because -setCount: exists (even if -count does
|
||||
not). */
|
||||
object.count = 40;
|
||||
|
||||
/* This should work because -a exists (even if -setA: does not). */
|
||||
if (object.a != 40)
|
||||
abort ();
|
||||
|
||||
/* This should work because -setNext: exists (even if -next does
|
||||
not). */
|
||||
object.next = object;
|
||||
|
||||
/* This should work because -b exists (even if -setB: does not). */
|
||||
if (object.b != object)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user