aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-11-03 10:39:15 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-11-03 10:39:15 +0000
commit43236c265b65d3e9447f84272300db648416d37e (patch)
tree343b86bc8aefd1ff013b186a12e04ffedd18269c /gcc
parent87c20fe7623b31c72d31b015254fd7f7964f2ead (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/objc/objc-act.c134
-rw-r--r--gcc/objc/objc-act.h23
-rw-r--r--gcc/objc/objc-tree.def6
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dotsyntax-1.mm62
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dotsyntax-2.mm71
-rw-r--r--gcc/testsuite/objc.dg/property/dotsyntax-1.m62
-rw-r--r--gcc/testsuite/objc.dg/property/dotsyntax-2.m71
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;
+}
+
+