mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-23 01:30:29 +08:00
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:
parent
cd746c2704
commit
a9625a91d2
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
86
gcc/testsuite/obj-c++.dg/property/dotsyntax-10.mm
Normal file
86
gcc/testsuite/obj-c++.dg/property/dotsyntax-10.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
61
gcc/testsuite/obj-c++.dg/property/dotsyntax-11.mm
Normal file
61
gcc/testsuite/obj-c++.dg/property/dotsyntax-11.mm
Normal 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
|
78
gcc/testsuite/obj-c++.dg/property/dotsyntax-5.mm
Normal file
78
gcc/testsuite/obj-c++.dg/property/dotsyntax-5.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
107
gcc/testsuite/obj-c++.dg/property/dotsyntax-6.mm
Normal file
107
gcc/testsuite/obj-c++.dg/property/dotsyntax-6.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
48
gcc/testsuite/obj-c++.dg/property/dotsyntax-7.mm
Normal file
48
gcc/testsuite/obj-c++.dg/property/dotsyntax-7.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
62
gcc/testsuite/obj-c++.dg/property/dotsyntax-8.mm
Normal file
62
gcc/testsuite/obj-c++.dg/property/dotsyntax-8.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
77
gcc/testsuite/obj-c++.dg/property/dotsyntax-9.mm
Normal file
77
gcc/testsuite/obj-c++.dg/property/dotsyntax-9.mm
Normal 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;
|
||||
}
|
||||
|
||||
|
86
gcc/testsuite/objc.dg/property/dotsyntax-10.m
Normal file
86
gcc/testsuite/objc.dg/property/dotsyntax-10.m
Normal 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;
|
||||
}
|
||||
|
||||
|
61
gcc/testsuite/objc.dg/property/dotsyntax-11.m
Normal file
61
gcc/testsuite/objc.dg/property/dotsyntax-11.m
Normal 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
|
78
gcc/testsuite/objc.dg/property/dotsyntax-5.m
Normal file
78
gcc/testsuite/objc.dg/property/dotsyntax-5.m
Normal 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;
|
||||
}
|
||||
|
||||
|
107
gcc/testsuite/objc.dg/property/dotsyntax-6.m
Normal file
107
gcc/testsuite/objc.dg/property/dotsyntax-6.m
Normal 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;
|
||||
}
|
||||
|
||||
|
48
gcc/testsuite/objc.dg/property/dotsyntax-7.m
Normal file
48
gcc/testsuite/objc.dg/property/dotsyntax-7.m
Normal 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;
|
||||
}
|
||||
|
||||
|
62
gcc/testsuite/objc.dg/property/dotsyntax-8.m
Normal file
62
gcc/testsuite/objc.dg/property/dotsyntax-8.m
Normal 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;
|
||||
}
|
||||
|
||||
|
77
gcc/testsuite/objc.dg/property/dotsyntax-9.m
Normal file
77
gcc/testsuite/objc.dg/property/dotsyntax-9.m
Normal 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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user