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

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

        Fixed using the Objective-C 2.0 syntax with self and super.
        * objc-act.c (OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS): New.
        (maybe_make_artificial_property_decl): Added 'implementation'
        argument.  Use OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS when
        looking up getters or setters for a class.  If an implementation
        is specified, search it as well for a getter or setter.
        (objc_maybe_build_component_ref): Updated calls to
        maybe_make_artificial_property_decl; added code to deal with
        'self' and 'super' and with methods declared locally in the
        implementation.  Store the getter call expression in the
        PROPERTY_REF instead of throwing it away.
        (objc_build_class_component_ref): Updated calls to
        maybe_make_artificial_property_decl, and store the getter call
        expression in PROPERTY_REF instead of throwing it away.
        (lookup_method_static): Implemented
        OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS option.
        (objc_gimplify_property_ref): Do not build the getter method call
        here; instead use the one stored in the PROPERTY_REF.  If it's not
        there, produce helpful error messages.
        * objc-tree.def (PROPERTY_REF): Increased the number of operands
        from 2 to 3.  Updated comments.
        * objc-act.h (PROPERTY_REF_GETTER_CALL): New.

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

        Fixed using the Objective-C 2.0 dot-syntax with self and super.
        * objc.dg/property/dotsyntax-5.m: New.
        * objc.dg/property/dotsyntax-6.m: New.
        * objc.dg/property/dotsyntax-7.m: New.
        * objc.dg/property/dotsyntax-8.m: New.
        * objc.dg/property/dotsyntax-9.m: New.
        * objc.dg/property/dotsyntax-10.m: New.
        * objc.dg/property/dotsyntax-11.m: New.
        * obj-c++.dg/property/dotsyntax-5.mm: New.
        * obj-c++.dg/property/dotsyntax-6.mm: New.
        * obj-c++.dg/property/dotsyntax-7.mm: New.
        * obj-c++.dg/property/dotsyntax-8.mm: New.
        * obj-c++.dg/property/dotsyntax-9.mm: New.
        * obj-c++.dg/property/dotsyntax-10.mm: New.
        * obj-c++.dg/property/dotsyntax-11.mm: New.

From-SVN: r166402
This commit is contained in:
Nicola Pero 2010-11-06 13:14:55 +00:00 committed by Nicola Pero
parent cd746c2704
commit a9625a91d2
19 changed files with 1353 additions and 91 deletions

View File

@ -1,3 +1,28 @@
2010-11-06 Nicola Pero <nicola.pero@meta-innovation.com>
Fixed using the Objective-C 2.0 syntax with self and super.
* objc-act.c (OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS): New.
(maybe_make_artificial_property_decl): Added 'implementation'
argument. Use OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS when
looking up getters or setters for a class. If an implementation
is specified, search it as well for a getter or setter.
(objc_maybe_build_component_ref): Updated calls to
maybe_make_artificial_property_decl; added code to deal with
'self' and 'super' and with methods declared locally in the
implementation. Store the getter call expression in the
PROPERTY_REF instead of throwing it away.
(objc_build_class_component_ref): Updated calls to
maybe_make_artificial_property_decl, and store the getter call
expression in PROPERTY_REF instead of throwing it away.
(lookup_method_static): Implemented
OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS option.
(objc_gimplify_property_ref): Do not build the getter method call
here; instead use the one stored in the PROPERTY_REF. If it's not
there, produce helpful error messages.
* objc-tree.def (PROPERTY_REF): Increased the number of operands
from 2 to 3. Updated comments.
* objc-act.h (PROPERTY_REF_GETTER_CALL): New.
2010-11-06 Iain Sandoe <iains@gcc.gnu.org>
PR target/44981

View File

@ -377,8 +377,14 @@ static const char *default_constant_string_class_name;
#define TAG_GNUINIT "__objc_gnu_init"
/* Flags for lookup_method_static(). */
#define OBJC_LOOKUP_CLASS 1 /* Look for class methods. */
#define OBJC_LOOKUP_NO_SUPER 2 /* Do not examine superclasses. */
/* Look for class methods. */
#define OBJC_LOOKUP_CLASS 1
/* Do not examine superclasses. */
#define OBJC_LOOKUP_NO_SUPER 2
/* Disable returning an instance method of a root class when a class
method can't be found. */
#define OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS 4
/* The OCTI_... enumeration itself is in objc/objc-act.h. */
tree objc_global_trees[OCTI_MAX];
@ -1085,32 +1091,58 @@ lookup_property (tree interface_type, tree property)
}
/* This is a subroutine of objc_maybe_build_component_ref. Search the
list of methods in the interface (and, failing that, protocol list)
list of methods in the interface (and, failing that, the local list
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. */
static tree
maybe_make_artificial_property_decl (tree interface, tree protocol_list, tree component, bool is_class)
maybe_make_artificial_property_decl (tree interface, tree implementation,
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;
/* First, check the @interface and all superclasses. */
if (interface)
{
int flags = 0;
/* Using instance methods of the root class as accessors is most
likely unwanted and can be extremely confusing (and, most
importantly, other Objective-C 2.0 compilers do not do it).
Turn it off. */
if (is_class)
flags = OBJC_LOOKUP_CLASS;
flags = OBJC_LOOKUP_CLASS | OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_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. */
/* Second, check the local @implementation context. */
if (!getter && !setter)
{
if (implementation)
{
if (is_class)
{
getter = lookup_method (CLASS_CLS_METHODS (implementation), getter_name);
setter = lookup_method (CLASS_CLS_METHODS (implementation), setter_name);
}
else
{
getter = lookup_method (CLASS_NST_METHODS (implementation), getter_name);
setter = lookup_method (CLASS_NST_METHODS (implementation), setter_name);
}
}
}
/* Try the protocol_list if we didn't find anything in the
@interface and in the @implementation. */
if (!getter && !setter)
{
getter = lookup_method_in_protocol_list (protocol_list, getter_name, is_class);
@ -1186,13 +1218,13 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
tree x = NULL_TREE;
tree rtype;
/* If we are in Objective-C 1.0 mode, properties are not
available. */
/* If we are in Objective-C 1.0 mode, dot-syntax and properties are
not available. */
if (flag_objc1_only)
return NULL_TREE;
/* Try to determine quickly if 'object' is an Objective-C object or
not. If not, return. */
/* Try to determine if 'object' is an Objective-C object or not. If
not, return. */
if (object == NULL_TREE || object == error_mark_node
|| (rtype = TREE_TYPE (object)) == NULL_TREE)
return NULL_TREE;
@ -1201,37 +1233,118 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|| TREE_CODE (property_ident) != IDENTIFIER_NODE)
return NULL_TREE;
/* TODO: Implement super.property. */
/* TODO: Carefully review the following code. */
/* The following analysis of 'object' is similar to the one used for
the 'receiver' of a method invocation. We need to determine what
'object' is and find the appropriate property (either declared,
or artificial) for it (in the same way as we need to find the
appropriate method prototype for a method invocation). There are
some simplifications here though: "object.property" is invalid if
"object" has a type of "id" or "Class"; it must at least have a
protocol attached to it, and "object" is never a class name as
that is done by objc_build_class_component_ref. Finally, we
don't know if this really is a dot-syntax expression, so we want
to make a quick exit if it is not; for this reason, we try to
postpone checks after determining that 'object' looks like an
Objective-C object. */
if (objc_is_id (rtype))
{
tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
: NULL_TREE);
if (rprotos)
x = lookup_property_in_protocol_list (rprotos, property_ident);
/* This is the case that the 'object' is of type 'id' or
'Class'. */
if (x == NULL_TREE)
/* Check if at least it is of type 'id <Protocol>' or 'Class
<Protocol>'; if so, look the property up in the
protocols. */
if (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype)))
{
/* 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);
tree rprotos = TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype));
if (rprotos)
{
/* No point looking up declared @properties if we are
dealing with a class. Classes have no declared
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
object.component dot-syntax without a declared
property (this is valid for classes too). Look
for getter/setter methods and internally declare
an artifical property based on them if found. */
x = maybe_make_artificial_property_decl (NULL_TREE,
NULL_TREE,
rprotos,
property_ident,
IS_CLASS (rtype));
}
}
}
else if (objc_method_context)
{
/* Else, if we are inside a method it could be the case of
'super' or 'self'. */
tree interface_type = NULL_TREE;
tree t = object;
while (TREE_CODE (t) == COMPOUND_EXPR
|| TREE_CODE (t) == MODIFY_EXPR
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == COMPONENT_REF)
t = TREE_OPERAND (t, 0);
if (t == UOBJC_SUPER_decl)
interface_type = lookup_interface (CLASS_SUPER_NAME (implementation_template));
else if (t == self_decl)
interface_type = lookup_interface (CLASS_NAME (implementation_template));
/* TODO: Protocols. */
if (interface_type)
{
if (TREE_CODE (objc_method_context) != CLASS_METHOD_DECL)
{
x = lookup_property (interface_type, property_ident);
/* TODO: Protocols. */
}
if (x == NULL_TREE)
{
/* Try the dot-syntax without a declared property.
If this is an access to 'self', it is possible
that they may refer to a setter/getter that is
not declared in the interface, but exists locally
in the implementation. In that case, get the
implementation context and use it. */
tree implementation = NULL_TREE;
if (t == self_decl)
implementation = objc_implementation_context;
/* TODO: Protocols. */
x = maybe_make_artificial_property_decl
(interface_type, implementation, NULL_TREE,
property_ident,
(TREE_CODE (objc_method_context) == CLASS_METHOD_DECL));
}
}
}
}
else
{
/* This is the case where we have more information on 'rtype'. */
tree basetype = TYPE_MAIN_VARIANT (rtype);
/* Skip the pointer - if none, it's not an Objective-C object or
class. */
if (basetype != NULL_TREE && TREE_CODE (basetype) == POINTER_TYPE)
basetype = TREE_TYPE (basetype);
else
return NULL_TREE;
/* Traverse typedefs. */
while (basetype != NULL_TREE
&& TREE_CODE (basetype) == RECORD_TYPE
&& OBJC_TYPE_NAME (basetype)
@ -1243,58 +1356,91 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
{
tree interface_type = TYPE_OBJC_INTERFACE (basetype);
tree protocol_list = TYPE_OBJC_PROTOCOL_LIST (basetype);
x = lookup_property (interface_type, property_ident);
if (x == NULL_TREE)
x = lookup_property_in_protocol_list (protocol_list, property_ident);
if (x == NULL_TREE)
if (interface_type
&& (TREE_CODE (interface_type) == CLASS_INTERFACE_TYPE
|| TREE_CODE (interface_type) == CATEGORY_INTERFACE_TYPE
|| TREE_CODE (interface_type) == PROTOCOL_INTERFACE_TYPE))
{
/* Ok, no property. Try the dot-syntax without a
declared property. */
x = maybe_make_artificial_property_decl (interface_type, protocol_list,
property_ident, false);
/* Not sure 'rtype' could ever be a class here! Just
for safety we keep the checks. */
if (!IS_CLASS (rtype))
{
x = lookup_property (interface_type, property_ident);
if (x == NULL_TREE)
x = lookup_property_in_protocol_list (protocol_list,
property_ident);
}
if (x == NULL_TREE)
{
/* Try the dot-syntax without a declared property.
If we are inside a method implementation, it is
possible that they may refer to a setter/getter
that is not declared in the interface, but exists
locally in the implementation. In that case, get
the implementation context and use it. */
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,
IS_CLASS (rtype));
}
}
}
}
/* TODO: Fix compiling super.accessor. */
if (x)
{
tree expression;
if (TREE_DEPRECATED (x))
warn_deprecated_use (x, NULL_TREE);
expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
SET_EXPR_LOCATION (expression, input_location);
TREE_SIDE_EFFECTS (expression) = 1;
tree getter_call;
/* We have an additional nasty problem here; if this
PROPERTY_REF needs to become a 'getter', then the conversion
from PROPERTY_REF into a getter call happens in gimplify,
after the selector table has already been generated and it is
too late to add another selector to it. To work around the
problem, we always put the selector in the table at this
stage, as if we were building the method call here. And the
easiest way to do this is precisely to build the method call,
then discard it. Note that if the PROPERTY_REF becomes a
'setter' instead of a 'getter', then we have added a selector
too many to the selector table. This is a little
inefficient.
after the selector table has already been generated and when
it is too late to add another selector to it. To work around
the problem, we always create the getter call at this stage,
which puts the selector in the table. Note that if the
PROPERTY_REF becomes a 'setter' instead of a 'getter', then
we have added a selector too many to the selector table.
This is a little inefficient.
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.
Also note that method calls to 'self' and 'super' require the
context (self_decl, UOBJS_SUPER_decl,
objc_implementation_context etc) to be built correctly; this
is yet another reason why building the call at the gimplify
stage (when this context has been lost) is not very
practical. If we build it at this stage, we know it will
always be built correctly.
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);
if (PROPERTY_HAS_NO_GETTER (x))
getter_call = NULL_TREE;
else
getter_call = objc_finish_message_expr (object,
PROPERTY_GETTER_NAME (x),
NULL_TREE);
if (TREE_DEPRECATED (x))
warn_deprecated_use (x, NULL_TREE);
expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call);
SET_EXPR_LOCATION (expression, input_location);
TREE_SIDE_EFFECTS (expression) = 1;
return expression;
}
@ -1341,26 +1487,28 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
return error_mark_node;
}
x = maybe_make_artificial_property_decl (rtype, NULL_TREE,
x = maybe_make_artificial_property_decl (rtype, NULL_TREE, NULL_TREE,
property_ident,
true);
if (x)
{
tree expression;
tree getter_call;
if (PROPERTY_HAS_NO_GETTER (x))
getter_call = NULL_TREE;
else
getter_call = objc_finish_message_expr (object,
PROPERTY_GETTER_NAME (x),
NULL_TREE);
if (TREE_DEPRECATED (x))
warn_deprecated_use (x, NULL_TREE);
expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call);
SET_EXPR_LOCATION (expression, input_location);
TREE_SIDE_EFFECTS (expression) = 1;
/* See above for why we do this. */
if (!PROPERTY_HAS_NO_GETTER (x))
objc_finish_message_expr (object,
PROPERTY_GETTER_NAME (x),
NULL_TREE);
return expression;
}
else
@ -7957,13 +8105,16 @@ lookup_method (tree mchain, tree method)
return NULL_TREE;
}
/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
in INTERFACE, along with any categories and protocols attached thereto.
If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
recursively examine the INTERFACE's superclass. If OBJC_LOOKUP_CLASS is
set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
be found in INTERFACE or any of its superclasses, look for an _instance_
method of the same name in the root class as a last resort.
/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance
method in INTERFACE, along with any categories and protocols
attached thereto. If method is not found, and the
OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS, recursively examine the
INTERFACE's superclass. If OBJC_LOOKUP_CLASS is set,
OBJC_LOOKUP_NO_SUPER is clear, and no suitable class method could
be found in INTERFACE or any of its superclasses, look for an
_instance_ method of the same name in the root class as a last
resort. This behaviour can be turned off by using
OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS.
If a suitable method cannot be found, return NULL_TREE. */
@ -7974,6 +8125,7 @@ lookup_method_static (tree interface, tree ident, int flags)
tree inter = interface;
int is_class = (flags & OBJC_LOOKUP_CLASS);
int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
int no_instance_methods_of_root_class = (flags & OBJC_LOOKUP_NO_INSTANCE_METHODS_OF_ROOT_CLASS);
while (inter)
{
@ -8020,11 +8172,18 @@ lookup_method_static (tree interface, tree ident, int flags)
}
while (inter);
/* If no class (factory) method was found, check if an _instance_
method of the same name exists in the root class. This is what
the Objective-C runtime will do. If an instance method was not
found, return 0. */
return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
if (is_class && !no_instance_methods_of_root_class)
{
/* If no class (factory) method was found, check if an _instance_
method of the same name exists in the root class. This is what
the Objective-C runtime will do. */
return lookup_method_static (root_inter, ident, 0);
}
else
{
/* If an instance method was not found, return 0. */
return NULL_TREE;
}
}
/* Add the method to the hash list if it doesn't contain an identical
@ -12038,15 +12197,24 @@ objc_rewrite_function_call (tree function, tree first_param)
static void
objc_gimplify_property_ref (tree *expr_p)
{
tree object_expression = PROPERTY_REF_OBJECT (*expr_p);
tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
tree call_exp, getter;
tree getter = PROPERTY_REF_GETTER_CALL (*expr_p);
tree call_exp;
/* TODO: Implement super.property. */
if (getter == NULL_TREE)
{
tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
/* This can happen if DECL_ARTIFICIAL (*expr_p), but
should be impossible for real properties, which always
have a getter. */
error_at (EXPR_LOCATION (*expr_p), "no %qs getter found",
IDENTIFIER_POINTER (PROPERTY_NAME (property_decl)));
/* Try to recover from the error to prevent an ICE. We take
zero and cast it to the type of the property. */
*expr_p = convert (TREE_TYPE (property_decl),
integer_zero_node);
return;
}
getter = objc_finish_message_expr (object_expression,
PROPERTY_GETTER_NAME (property_decl),
NULL_TREE);
call_exp = getter;
#ifdef OBJCPLUS
/* In C++, a getter which returns an aggregate value results in a

View File

@ -131,6 +131,15 @@ typedef enum objc_property_assign_semantics {
declared property. */
#define PROPERTY_REF_PROPERTY_DECL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 1)
/* PROPERTY_REF_GETTER_CALL is the getter call expression, ready to
use at gimplify time if needed. Generating the getter call
requires modifying the selector table, and, in the case of
self/super, requires the context to be generated correctly. The
gimplify stage is too late to do these things, so we generate the
getter call earlier instead, and keep it here in case we need to
use it. */
#define PROPERTY_REF_GETTER_CALL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 2)
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,

View File

@ -44,9 +44,11 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
where 'object' is an Objective-C object and 'property' is an
Objective-C property. Operand 0 is the object (the tree
representing the expression), and Operand 1 is the property (the
PROPERTY_DECL). A PROPERTY_REF tree needs to be transformed into
'setter' and 'getter' calls at some point; at the moment this
happens in two places:
PROPERTY_DECL). Operand 2 is the 'getter' call, ready to be used;
we pregenerate it because it is hard to generate it properly later
on. A PROPERTY_REF tree needs to be transformed into 'setter' and
'getter' calls at some point; at the moment this happens in two
places:
* if we detect that a modify expression is being applied to a
PROPERTY_REF, then we transform that into a 'getter' call (this
@ -54,13 +56,15 @@ 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.
a 'getter' call during ObjC/ObjC++ gimplify. At that point, it
is quite hard to build a 'getter' call, but we have already built
it and we just need to swap Operand 2 in.
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)
DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 3)
/*
Local variables:

View File

@ -1,3 +1,21 @@
2010-11-06 Nicola Pero <nicola.pero@meta-innovation.com>
Fixed using the Objective-C 2.0 dot-syntax with self and super.
* objc.dg/property/dotsyntax-5.m: New.
* objc.dg/property/dotsyntax-6.m: New.
* objc.dg/property/dotsyntax-7.m: New.
* objc.dg/property/dotsyntax-8.m: New.
* objc.dg/property/dotsyntax-9.m: New.
* objc.dg/property/dotsyntax-10.m: New.
* objc.dg/property/dotsyntax-11.m: New.
* obj-c++.dg/property/dotsyntax-5.mm: New.
* obj-c++.dg/property/dotsyntax-6.mm: New.
* obj-c++.dg/property/dotsyntax-7.mm: New.
* obj-c++.dg/property/dotsyntax-8.mm: New.
* obj-c++.dg/property/dotsyntax-9.mm: New.
* obj-c++.dg/property/dotsyntax-10.mm: New.
* obj-c++.dg/property/dotsyntax-11.mm: New.
2010-11-06 Iain Sandoe <iains@gcc.gnu.org>
* obj-c++.dg/encode-3.mm: Provide a different string check for the

View File

@ -0,0 +1,86 @@
/* 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 dot-syntax with 'super'. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
@interface MySubClass : MyRootClass
+ (int) testMe;
- (int) testMe;
@end
@implementation MySubClass
- (int) testMe
{
super.count = 400;
if (super.count != 400)
abort ();
return super.count;
}
+ (int) testMe
{
super.classCount = 4000;
if (super.classCount != 4000)
abort ();
return super.classCount;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MySubClass testMe] != 4000)
abort ();
return 0;
}

View File

@ -0,0 +1,61 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test the error reporting for the dot-syntax in the scenario where
we have a setter, but not a getter, yet a getter is requested. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (void) setCount: (int)count;
+ (void) setClassCount: (int)count;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (void) setCount: (int)count
{
a = count;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
@interface MySubClass : MyRootClass
+ (int) testMe;
- (int) testMe;
@end
@implementation MySubClass
- (int) testMe
{
super.count = 400;
if (super.count != 400) /* { dg-error "no .count. getter found" } */
abort ();
return super.count; /* { dg-error "no .count. getter found" } */
}
+ (int) testMe
{
super.classCount = 4000;
if (super.classCount != 4000) /* { dg-error "no .classCount. getter found" } */
abort ();
return super.classCount; /* { dg-error "no .classCount. getter found" } */
}
@end

View File

@ -0,0 +1,78 @@
/* 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 the 'dot syntax' with self, both in instance and class methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
+ (int) testMe
{
self.classCount = 4000;
if (self.classCount != 4000)
abort ();
return self.classCount;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MyRootClass testMe] != 4000)
abort ();
return 0;
}

View File

@ -0,0 +1,107 @@
/* 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 nested 'dot syntax' (xxx.yyy.zzz or [xxx yyy].zzz). */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@class MyRootClass;
static int c;
static MyRootClass *shared_root = nil;
@interface MyRootClass
{
Class isa;
int a;
int b;
MyRootClass *next;
}
@property int b;
@property (assign) MyRootClass *next;
+ (id) initialize;
+ (MyRootClass *)sharedInstance;
+ (id) alloc;
- (id) init;
- (MyRootClass *)same;
- (int) count;
- (void) setCount: (int)count;
@end
@implementation MyRootClass
@synthesize b;
@synthesize next;
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
+ (MyRootClass *)sharedInstance
{
if (!shared_root)
shared_root = [[self alloc] init];
return shared_root;
}
- (MyRootClass *)same
{
return self;
}
- (int) count
{
return a;
}
- (void) setCount: (int)count
{
a = count;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
/* Test ClassName.accessor.accessor. */
MyRootClass.sharedInstance.count = 500;
if (MyRootClass.sharedInstance.count != 500)
abort ();
/* Test object.accessor.accessor. */
object.same.count = 1000;
if (object.same.count != 1000)
abort ();
/* Test object.accessor.property. */
object.same.next = object;
if (object.same.next != object)
abort ();
/* Test lots of nesting. */
if (object.next.next.same.same.next.next.same != object)
abort ();
/* Test more nesting. */
MyRootClass.sharedInstance.next = object;
MyRootClass.sharedInstance.next.next.next.next.next.count = 2000;
if (MyRootClass.sharedInstance.next.next.next.next.next.count != 2000)
abort ();
/* Test more nesting. */
MyRootClass.sharedInstance.same.same.same.same.same.count = 3000;
if (MyRootClass.sharedInstance.same.same.same.same.same.count != 3000)
abort ();
/* Test [object method].property. */
[MyRootClass sharedInstance].count = 5000;
if ([MyRootClass sharedInstance].count != 5000)
abort ();
/* Just a final check. */
if (shared_root.count != 5000)
abort ();
return 0;
}

View File

@ -0,0 +1,48 @@
/* 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 dot syntax of a casted expression. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
@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)count
{
a = count;
}
@end
int main (void)
{
id object = [[MyRootClass alloc] init];
((MyRootClass *)object).count = 200;
if (((MyRootClass *)object).count != 200)
abort ();
return 0;
}

View File

@ -0,0 +1,62 @@
/* 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 the 'dot syntax' with typedefs. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
typedef MyRootClass MyType;
int main (void)
{
MyType *object = [[MyRootClass alloc] init];
object.count = 1974;
if (object.count != 1974)
abort ();
return 0;
}

View File

@ -0,0 +1,77 @@
/* 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 that setter/getters for dot-syntax are properly found even if
not declared in the @interface, but available in the local
@implementation before the current line (ie, [object name] can be
compiled in that case, so object.name should be compiled too). */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
+ (int) testMe
{
self.classCount = 4000;
if (self.classCount != 4000)
abort ();
return self.classCount;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MyRootClass testMe] != 4000)
abort ();
return 0;
}

View File

@ -0,0 +1,86 @@
/* 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 dot-syntax with 'super'. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
@interface MySubClass : MyRootClass
+ (int) testMe;
- (int) testMe;
@end
@implementation MySubClass
- (int) testMe
{
super.count = 400;
if (super.count != 400)
abort ();
return super.count;
}
+ (int) testMe
{
super.classCount = 4000;
if (super.classCount != 4000)
abort ();
return super.classCount;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MySubClass testMe] != 4000)
abort ();
return 0;
}

View File

@ -0,0 +1,61 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test the error reporting for the dot-syntax in the scenario where
we have a setter, but not a getter, yet a getter is requested. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (void) setCount: (int)count;
+ (void) setClassCount: (int)count;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (void) setCount: (int)count
{
a = count;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
@interface MySubClass : MyRootClass
+ (int) testMe;
- (int) testMe;
@end
@implementation MySubClass
- (int) testMe
{
super.count = 400;
if (super.count != 400) /* { dg-error "no .count. getter found" } */
abort ();
return super.count; /* { dg-error "no .count. getter found" } */
}
+ (int) testMe
{
super.classCount = 4000;
if (super.classCount != 4000) /* { dg-error "no .classCount. getter found" } */
abort ();
return super.classCount; /* { dg-error "no .classCount. getter found" } */
}
@end

View File

@ -0,0 +1,78 @@
/* 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 the 'dot syntax' with self, both in instance and class methods. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
+ (int) testMe
{
self.classCount = 4000;
if (self.classCount != 4000)
abort ();
return self.classCount;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MyRootClass testMe] != 4000)
abort ();
return 0;
}

View File

@ -0,0 +1,107 @@
/* 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 nested 'dot syntax' (xxx.yyy.zzz or [xxx yyy].zzz). */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@class MyRootClass;
static int c;
static MyRootClass *shared_root = nil;
@interface MyRootClass
{
Class isa;
int a;
int b;
MyRootClass *next;
}
@property int b;
@property (assign) MyRootClass *next;
+ (id) initialize;
+ (MyRootClass *)sharedInstance;
+ (id) alloc;
- (id) init;
- (MyRootClass *)same;
- (int) count;
- (void) setCount: (int)count;
@end
@implementation MyRootClass
@synthesize b;
@synthesize next;
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
+ (MyRootClass *)sharedInstance
{
if (!shared_root)
shared_root = [[self alloc] init];
return shared_root;
}
- (MyRootClass *)same
{
return self;
}
- (int) count
{
return a;
}
- (void) setCount: (int)count
{
a = count;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
/* Test ClassName.accessor.accessor. */
MyRootClass.sharedInstance.count = 500;
if (MyRootClass.sharedInstance.count != 500)
abort ();
/* Test object.accessor.accessor. */
object.same.count = 1000;
if (object.same.count != 1000)
abort ();
/* Test object.accessor.property. */
object.same.next = object;
if (object.same.next != object)
abort ();
/* Test lots of nesting. */
if (object.next.next.same.same.next.next.same != object)
abort ();
/* Test more nesting. */
MyRootClass.sharedInstance.next = object;
MyRootClass.sharedInstance.next.next.next.next.next.count = 2000;
if (MyRootClass.sharedInstance.next.next.next.next.next.count != 2000)
abort ();
/* Test more nesting. */
MyRootClass.sharedInstance.same.same.same.same.same.count = 3000;
if (MyRootClass.sharedInstance.same.same.same.same.same.count != 3000)
abort ();
/* Test [object method].property. */
[MyRootClass sharedInstance].count = 5000;
if ([MyRootClass sharedInstance].count != 5000)
abort ();
/* Just a final check. */
if (shared_root.count != 5000)
abort ();
return 0;
}

View File

@ -0,0 +1,48 @@
/* 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 dot syntax of a casted expression. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
@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)count
{
a = count;
}
@end
int main (void)
{
id object = [[MyRootClass alloc] init];
((MyRootClass *)object).count = 200;
if (((MyRootClass *)object).count != 200)
abort ();
return 0;
}

View File

@ -0,0 +1,62 @@
/* 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 the 'dot syntax' with typedefs. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
+ (int) classCount;
+ (void) setClassCount: (int)count;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
@end
typedef MyRootClass MyType;
int main (void)
{
MyType *object = [[MyRootClass alloc] init];
object.count = 1974;
if (object.count != 1974)
abort ();
return 0;
}

View File

@ -0,0 +1,77 @@
/* 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 that setter/getters for dot-syntax are properly found even if
not declared in the @interface, but available in the local
@implementation before the current line (ie, [object name] can be
compiled in that case, so object.name should be compiled too). */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
static int c;
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
@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)count
{
a = count;
}
+ (int) classCount
{
return c;
}
+ (void) setClassCount: (int)count
{
c = count;
}
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
+ (int) testMe
{
self.classCount = 4000;
if (self.classCount != 4000)
abort ();
return self.classCount;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
if ([object testMe] != 400)
abort ();
if ([MyRootClass testMe] != 4000)
abort ();
return 0;
}