diff options
author | Nicola Pero <nicola.pero@meta-innovation.com> | 2010-11-03 10:39:15 +0000 |
---|---|---|
committer | Nicola Pero <nicola@gcc.gnu.org> | 2010-11-03 10:39:15 +0000 |
commit | 43236c265b65d3e9447f84272300db648416d37e (patch) | |
tree | 343b86bc8aefd1ff013b186a12e04ffedd18269c /gcc | |
parent | 87c20fe7623b31c72d31b015254fd7f7964f2ead (diff) | |
download | gcc-43236c265b65d3e9447f84272300db648416d37e.zip gcc-43236c265b65d3e9447f84272300db648416d37e.tar.gz gcc-43236c265b65d3e9447f84272300db648416d37e.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/objc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 134 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 23 | ||||
-rw-r--r-- | gcc/objc/objc-tree.def | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm | 62 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm | 71 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/dotsyntax-1.m | 62 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/dotsyntax-2.m | 71 |
9 files changed, 435 insertions, 13 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index e9e5592..1d78c0c 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -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. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 768215e..cfbcb3c 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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. - - At the moment this only implements properties (not non-fragile - ivars yet), ie 'object.property'. */ + 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 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), diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index 4c10c01..9478d72 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -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) diff --git a/gcc/objc/objc-tree.def b/gcc/objc/objc-tree.def index 5da2671..7316675 100644 --- a/gcc/objc/objc-tree.def +++ b/gcc/objc/objc-tree.def @@ -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) /* diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d97167a..a8851e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm new file mode 100644 index 0000000..8bc3b3a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm @@ -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; +} + + diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm new file mode 100644 index 0000000..ba615a3 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm @@ -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; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-1.m b/gcc/testsuite/objc.dg/property/dotsyntax-1.m new file mode 100644 index 0000000..8bc3b3a --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-1.m @@ -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; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-2.m b/gcc/testsuite/objc.dg/property/dotsyntax-2.m new file mode 100644 index 0000000..ba615a3 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-2.m @@ -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; +} + + |