Commit 4ca5d2a7 by Nicola Pero Committed by Nicola Pero

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

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

        * objc-act.c (lookup_property): When checking categories, also
        check the protocols attached to each.
        (objc_add_property_declaration): Determine the
        PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME here.  Tidied up
        error message.  Search for an existing property declaration with
        the same name which would be inherited from the class hiearchy,
        and produce an error if it has incompatible attributes.
        (check_methods): Changed second parameter.  If the method is a
        getter or setter for a property, do not warn if it is inherited as
        opposed to implemented directly in the class.
        (check_protocol): Updated calls to check_methods.
        (finish_class): Do not determine the PROPERTY_SETTER_NAME and
        PROPERTY_GETTER_NAME here; this is now done earlier, in
        objc_add_property_declaration.
        * objc-act.h (CLASS_NAME, CLASS_SUPER_NAME): Added comments.

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

        * objc.dg/property/at-property-5.m: Updated test.       
        * objc.dg/property/at-property-16.m: New.
        * objc.dg/property/at-property-17.m: New.
        * objc.dg/property/at-property-18.m: New.
        * objc.dg/property/at-property-19.m: New.       
        * objc.dg/property/dotsyntax-12.m: New
        * objc.dg/protocol-inheritance-1.m: New.
        * objc.dg/protocol-inheritance-2.m: New.
        * obj-c++.dg/property/at-property-5.mm: Updated test.
        * obj-c++.dg/property/at-property-16.mm: New.
        * obj-c++.dg/property/at-property-17.mm: New.
        * obj-c++.dg/property/at-property-18.mm: New.
        * obj-c++.dg/property/at-property-19.mm: New.   
        * obj-c++.dg/protocol-inheritance-1.mm: New.
        * obj-c++.dg/protocol-inheritance-2.mm: New.
        * obj-c++.dg/property/dotsyntax-12.mm: New.

From-SVN: r166455
parent 9e115cec
2010-11-08 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (lookup_property): When checking categories, also
check the protocols attached to each.
(objc_add_property_declaration): Determine the
PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME here. Tidied up
error message. Search for an existing property declaration with
the same name which would be inherited from the class hiearchy,
and produce an error if it has incompatible attributes.
(check_methods): Changed second parameter. If the method is a
getter or setter for a property, do not warn if it is inherited as
opposed to implemented directly in the class.
(check_protocol): Updated calls to check_methods.
(finish_class): Do not determine the PROPERTY_SETTER_NAME and
PROPERTY_GETTER_NAME here; this is now done earlier, in
objc_add_property_declaration.
* objc-act.h (CLASS_NAME, CLASS_SUPER_NAME): Added comments.
2010-11-06 Nicola Pero <nicola.pero@meta-innovation.com> 2010-11-06 Nicola Pero <nicola.pero@meta-innovation.com>
Fixed using the Objective-C 2.0 syntax with self and super. Fixed using the Objective-C 2.0 syntax with self and super.
......
...@@ -829,6 +829,78 @@ objc_set_method_opt (bool optional) ...@@ -829,6 +829,78 @@ objc_set_method_opt (bool optional)
} }
} }
/* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or
PROTOCOL. */
static tree
lookup_property_in_list (tree chain, tree property)
{
tree x;
for (x = CLASS_PROPERTY_DECL (chain); x; x = TREE_CHAIN (x))
if (PROPERTY_NAME (x) == property)
return x;
return NULL_TREE;
}
/* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */
static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
{
tree rproto, x;
for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
{
tree p = TREE_VALUE (rproto);
if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
{
if ((x = lookup_property_in_list (p, property)))
return x;
if (PROTOCOL_LIST (p))
return lookup_property_in_protocol_list (PROTOCOL_LIST (p), property);
}
else
{
; /* An identifier...if we could not find a protocol. */
}
}
return NULL_TREE;
}
/* This routine looks up the PROPERTY in current INTERFACE, its categories and up the
chain of interface hierarchy. */
static tree
lookup_property (tree interface_type, tree property)
{
tree inter = interface_type;
while (inter)
{
tree x, category;
if ((x = lookup_property_in_list (inter, property)))
return x;
/* Failing that, look for the property in each category of the class. */
category = inter;
while ((category = CLASS_CATEGORY_LIST (category)))
{
if ((x = lookup_property_in_list (category, property)))
return x;
/* When checking a category, also check the protocols
attached with the category itself. */
if (CLASS_PROTOCOL_LIST (category)
&& (x = lookup_property_in_protocol_list
(CLASS_PROTOCOL_LIST (category), property)))
return x;
}
/* Failing to find in categories, look for property in protocol list. */
if (CLASS_PROTOCOL_LIST (inter)
&& (x = lookup_property_in_protocol_list
(CLASS_PROTOCOL_LIST (inter), property)))
return x;
/* Failing that, climb up the inheritance hierarchy. */
inter = lookup_interface (CLASS_SUPER_NAME (inter));
}
return inter;
}
/* This routine is called by the parser when a /* This routine is called by the parser when a
@property... declaration is found. 'decl' is the declaration of @property... declaration is found. 'decl' is the declaration of
the property (type/identifier), and the other arguments represent the property (type/identifier), and the other arguments represent
...@@ -920,19 +992,6 @@ objc_add_property_declaration (location_t location, tree decl, ...@@ -920,19 +992,6 @@ objc_add_property_declaration (location_t location, tree decl,
/* At this point we know that we are either in an interface, a /* At this point we know that we are either in an interface, a
category, or a protocol. */ category, or a protocol. */
if (parsed_property_setter_ident)
{
/* The setter should be terminated by ':', but the parser only
gives us an identifier without ':'. So, we need to add ':'
at the end. */
const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
size_t length = strlen (parsed_setter);
char *final_setter = (char *)alloca (length + 2);
sprintf (final_setter, "%s:", parsed_setter);
parsed_property_setter_ident = get_identifier (final_setter);
}
/* Check that the property does not have an initial value specified. /* Check that the property does not have an initial value specified.
This should never happen as the parser doesn't allow this, but This should never happen as the parser doesn't allow this, but
it's just in case. */ it's just in case. */
...@@ -984,8 +1043,39 @@ objc_add_property_declaration (location_t location, tree decl, ...@@ -984,8 +1043,39 @@ objc_add_property_declaration (location_t location, tree decl,
&& !objc_type_valid_for_messaging (TREE_TYPE (decl), true)) && !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
error_at (location, "%<copy%> attribute is only valid for Objective-C objects"); error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
/* Now determine the final property getter and setter names. They
will be stored in the PROPERTY_DECL, from which they'll always be
extracted and used. */
/* Adjust, or fill in, setter and getter names. We overwrite the
parsed_property_setter_ident and parsed_property_getter_ident
with the final setter and getter identifiers that will be
used. */
if (parsed_property_setter_ident)
{
/* The setter should be terminated by ':', but the parser only
gives us an identifier without ':'. So, we need to add ':'
at the end. */
const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
size_t length = strlen (parsed_setter);
char *final_setter = (char *)alloca (length + 2);
sprintf (final_setter, "%s:", parsed_setter);
parsed_property_setter_ident = get_identifier (final_setter);
}
else
{
if (!property_readonly)
parsed_property_setter_ident = get_identifier (objc_build_property_setter_name
(DECL_NAME (decl)));
}
if (!parsed_property_getter_ident)
parsed_property_getter_ident = DECL_NAME (decl);
/* Check for duplicate property declarations. We first check the /* Check for duplicate property declarations. We first check the
immediate context for a property with the same name. */ immediate context for a property with the same name. Any such
declarations are an error. */
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x)) for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{ {
if (PROPERTY_NAME (x) == DECL_NAME (decl)) if (PROPERTY_NAME (x) == DECL_NAME (decl))
...@@ -995,14 +1085,126 @@ objc_add_property_declaration (location_t location, tree decl, ...@@ -995,14 +1085,126 @@ objc_add_property_declaration (location_t location, tree decl,
error_at (location, "redeclaration of property %qD", decl); error_at (location, "redeclaration of property %qD", decl);
if (original_location != UNKNOWN_LOCATION) if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally declared here"); inform (original_location, "originally specified here");
return; return;
} }
} }
/* TODO: Shall we check here for other property declaractions (in /* We now need to check for existing property declarations (in the
the superclass, other categories or protocols) with the same name superclass, other categories or protocols) and check that the new
and conflicting types ? */ declaration is not in conflict with existing ones. */
/* Search for a previous, existing declaration of a property with
the same name in superclasses, protocols etc. If one is found,
it will be in the 'x' variable. */
x = NULL_TREE;
/* Note that, for simplicity, the following may search again the
local context. That's Ok as nothing will be found (else we'd
have thrown an error above); it's only a little inefficient, but
the code is simpler. */
switch (TREE_CODE (objc_interface_context))
{
case CLASS_INTERFACE_TYPE:
/* Look up the property in the current @interface (which will
find nothing), then its protocols and categories and
superclasses. */
x = lookup_property (objc_interface_context, DECL_NAME (decl));
break;
case CATEGORY_INTERFACE_TYPE:
/* Look up the property in the main @interface, then protocols
and categories (one of them is ours, and will find nothing)
and superclasses. */
x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)),
DECL_NAME (decl));
break;
case PROTOCOL_INTERFACE_TYPE:
/* Looks up the property in any protocols attached to the
current protocol. */
if (PROTOCOL_LIST (objc_interface_context))
{
x = lookup_property_in_protocol_list (PROTOCOL_LIST (objc_interface_context),
DECL_NAME (decl));
}
break;
default:
gcc_unreachable ();
}
if (x != NULL_TREE)
{
/* An existing property was found; check that it has the same
types, or it is compatible. */
location_t original_location = DECL_SOURCE_LOCATION (x);
if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic)
{
error_at (location, "'nonatomic' attribute of property %qD conflicts with previous declaration", decl);
if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally specified here");
return;
}
if (PROPERTY_GETTER_NAME (x) != parsed_property_getter_ident)
{
error_at (location, "'getter' attribute of property %qD conflicts with previous declaration", decl);
if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally specified here");
return;
}
/* We can only compare the setter names if both the old and new property have a setter. */
if (!property_readonly && !PROPERTY_READONLY(x))
{
if (PROPERTY_SETTER_NAME (x) != parsed_property_setter_ident)
{
error_at (location, "'setter' attribute of property %qD conflicts with previous declaration", decl);
if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally specified here");
return;
}
}
if (PROPERTY_ASSIGN_SEMANTICS (x) != property_assign_semantics)
{
error_at (location, "assign semantics attributes of property %qD conflict with previous declaration", decl);
if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally specified here");
return;
}
/* It's ok to have a readonly property that becomes a readwrite, but not vice versa. */
if (PROPERTY_READONLY (x) == 0 && property_readonly == 1)
{
error_at (location, "'readonly' attribute of property %qD conflicts with previous declaration", decl);
if (original_location != UNKNOWN_LOCATION)
inform (original_location, "originally specified here");
return;
}
if (property_readonly)
{
/* If the property is readonly, it is Ok if the property
type is a specialization of the previously declared one.
Eg, the superclass returns 'NSArray' while the subclass
returns 'NSMutableArray'. */
/* TODO: Check that the types are the same, or more specialized. */
;
}
else
{
/* Else, the types must match exactly. */
/* TODO: Check that property types are identical. */
;
}
}
/* Create a PROPERTY_DECL node. */ /* Create a PROPERTY_DECL node. */
property_decl = make_node (PROPERTY_DECL); property_decl = make_node (PROPERTY_DECL);
...@@ -1022,74 +1224,18 @@ objc_add_property_declaration (location_t location, tree decl, ...@@ -1022,74 +1224,18 @@ objc_add_property_declaration (location_t location, tree decl,
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE; PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
PROPERTY_DYNAMIC (property_decl) = 0; PROPERTY_DYNAMIC (property_decl) = 0;
/* Note that PROPERTY_GETTER_NAME is always set for all
PROPERTY_DECLs, and PROPERTY_SETTER_NAME is always set for all
PROPERTY_DECLs where PROPERTY_READONLY == 0. Any time we deal
with a getter or setter, we should get the PROPERTY_DECL and use
PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME to know the correct
names. */
/* Add the PROPERTY_DECL to the list of properties for the class. */ /* Add the PROPERTY_DECL to the list of properties for the class. */
TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context); TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
CLASS_PROPERTY_DECL (objc_interface_context) = property_decl; CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
} }
/* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or
PROTOCOL. */
static tree
lookup_property_in_list (tree chain, tree property)
{
tree x;
for (x = CLASS_PROPERTY_DECL (chain); x; x = TREE_CHAIN (x))
if (PROPERTY_NAME (x) == property)
return x;
return NULL_TREE;
}
/* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */
static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
{
tree rproto, x;
for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
{
tree p = TREE_VALUE (rproto);
if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
{
if ((x = lookup_property_in_list (p, property)))
return x;
if (PROTOCOL_LIST (p))
return lookup_property_in_protocol_list (PROTOCOL_LIST (p), property);
}
else
{
; /* An identifier...if we could not find a protocol. */
}
}
return NULL_TREE;
}
/* This routine looks up the PROPERTY in current INTERFACE, its categories and up the
chain of interface hierarchy. */
static tree
lookup_property (tree interface_type, tree property)
{
tree inter = interface_type;
while (inter)
{
tree x, category;
if ((x = lookup_property_in_list (inter, property)))
return x;
/* Failing that, look for the property in each category of the class. */
category = inter;
while ((category = CLASS_CATEGORY_LIST (category)))
if ((x = lookup_property_in_list (category, property)))
return x;
/* Failing to find in categories, look for property in protocol list. */
if (CLASS_PROTOCOL_LIST (inter)
&& (x = lookup_property_in_protocol_list (
CLASS_PROTOCOL_LIST (inter), property)))
return x;
/* Failing that, climb up the inheritance hierarchy. */
inter = lookup_interface (CLASS_SUPER_NAME (inter));
}
return inter;
}
/* This is a subroutine of objc_maybe_build_component_ref. Search the /* This is a subroutine of objc_maybe_build_component_ref. Search the
list of methods in the interface (and, failing that, the local list list of methods in the interface (and, failing that, the local list
in the implementation, and failing that, the protocol list) in the implementation, and failing that, the protocol list)
...@@ -1295,7 +1441,10 @@ objc_maybe_build_component_ref (tree object, tree property_ident) ...@@ -1295,7 +1441,10 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
if (t == UOBJC_SUPER_decl) if (t == UOBJC_SUPER_decl)
interface_type = lookup_interface (CLASS_SUPER_NAME (implementation_template)); {
/* TODO: Check if this is correct also for 'super' in categories. */
interface_type = lookup_interface (CLASS_SUPER_NAME (implementation_template));
}
else if (t == self_decl) else if (t == self_decl)
interface_type = lookup_interface (CLASS_NAME (implementation_template)); interface_type = lookup_interface (CLASS_NAME (implementation_template));
...@@ -8564,12 +8713,26 @@ objc_is_public (tree expr, tree identifier) ...@@ -8564,12 +8713,26 @@ objc_is_public (tree expr, tree identifier)
return 1; return 1;
} }
/* Make sure all entries in CHAIN are also in LIST. */ /* Make sure all methods in CHAIN (a list of method declarations from
an @interface or a @protocol) are in IMPLEMENTATION (the
implementation context). This is used to check for example that
all methods declared in an @interface were implemented in an
@implementation.
Some special methods (property setters/getters) are special and if
they are not found in IMPLEMENTATION, we look them up in its
superclasses. */
static int static int
check_methods (tree chain, tree list, int mtype) check_methods (tree chain, tree implementation, int mtype)
{ {
int first = 1; int first = 1;
tree list;
if (mtype == (int)'+')
list = CLASS_CLS_METHODS (implementation);
else
list = CLASS_NST_METHODS (implementation);
while (chain) while (chain)
{ {
...@@ -8577,7 +8740,7 @@ check_methods (tree chain, tree list, int mtype) ...@@ -8577,7 +8740,7 @@ check_methods (tree chain, tree list, int mtype)
is Ok not to have the method implementation, as it will be is Ok not to have the method implementation, as it will be
generated dynamically at runtime. */ generated dynamically at runtime. */
tree property = METHOD_PROPERTY_CONTEXT (chain); tree property = METHOD_PROPERTY_CONTEXT (chain);
if (property != NULL_TREE && PROPERTY_DYNAMIC (property)) if (property != NULL_TREE && PROPERTY_DYNAMIC (property))
{ {
chain = TREE_CHAIN (chain); /* next method... */ chain = TREE_CHAIN (chain); /* next method... */
continue; continue;
...@@ -8585,17 +8748,66 @@ check_methods (tree chain, tree list, int mtype) ...@@ -8585,17 +8748,66 @@ check_methods (tree chain, tree list, int mtype)
if (!lookup_method (list, chain)) if (!lookup_method (list, chain))
{ {
/* If the method is a property setter/getter, we'll still
allow it to be missing if it is implemented by
'interface' or any of its superclasses. */
if (property)
{
/* Note that since this is a property getter/setter, it
is obviously an instance method. */
tree interface = NULL_TREE;
/* For a category, first check the main class
@interface. */
if (TREE_CODE (implementation) == CATEGORY_IMPLEMENTATION_TYPE)
{
interface = lookup_interface (CLASS_NAME (implementation));
/* If the method is found in the main class, it's Ok. */
if (lookup_method (CLASS_NST_METHODS (interface), chain))
{
chain = DECL_CHAIN (chain);
continue;
}
/* Else, get the superclass. */
if (CLASS_SUPER_NAME (interface))
interface = lookup_interface (CLASS_SUPER_NAME (interface));
else
interface = NULL_TREE;
}
/* Get the superclass for classes. */
if (TREE_CODE (implementation) == CLASS_IMPLEMENTATION_TYPE)
{
if (CLASS_SUPER_NAME (implementation))
interface = lookup_interface (CLASS_SUPER_NAME (implementation));
else
interface = NULL_TREE;
}
/* Now, interface is the superclass, if any; go check it. */
if (interface)
{
if (lookup_method_static (interface, chain, 0))
{
chain = DECL_CHAIN (chain);
continue;
}
}
/* Else, fall through - warn. */
}
if (first) if (first)
{ {
switch (TREE_CODE (objc_implementation_context)) switch (TREE_CODE (implementation))
{ {
case CLASS_IMPLEMENTATION_TYPE: case CLASS_IMPLEMENTATION_TYPE:
warning (0, "incomplete implementation of class %qE", warning (0, "incomplete implementation of class %qE",
CLASS_NAME (objc_implementation_context)); CLASS_NAME (implementation));
break; break;
case CATEGORY_IMPLEMENTATION_TYPE: case CATEGORY_IMPLEMENTATION_TYPE:
warning (0, "incomplete implementation of category %qE", warning (0, "incomplete implementation of category %qE",
CLASS_SUPER_NAME (objc_implementation_context)); CLASS_SUPER_NAME (implementation));
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -8733,10 +8945,10 @@ check_protocol (tree p, const char *type, tree name) ...@@ -8733,10 +8945,10 @@ check_protocol (tree p, const char *type, tree name)
if (warn_protocol) if (warn_protocol)
{ {
f1 = check_methods (PROTOCOL_CLS_METHODS (p), f1 = check_methods (PROTOCOL_CLS_METHODS (p),
CLASS_CLS_METHODS (objc_implementation_context), objc_implementation_context,
'+'); '+');
f2 = check_methods (PROTOCOL_NST_METHODS (p), f2 = check_methods (PROTOCOL_NST_METHODS (p),
CLASS_NST_METHODS (objc_implementation_context), objc_implementation_context,
'-'); '-');
} }
else else
...@@ -9829,9 +10041,9 @@ finish_class (tree klass) ...@@ -9829,9 +10041,9 @@ finish_class (tree klass)
{ {
/* Ensure that all method listed in the interface contain bodies. */ /* Ensure that all method listed in the interface contain bodies. */
check_methods (CLASS_CLS_METHODS (implementation_template), check_methods (CLASS_CLS_METHODS (implementation_template),
CLASS_CLS_METHODS (objc_implementation_context), '+'); objc_implementation_context, '+');
check_methods (CLASS_NST_METHODS (implementation_template), check_methods (CLASS_NST_METHODS (implementation_template),
CLASS_NST_METHODS (objc_implementation_context), '-'); objc_implementation_context, '-');
if (CLASS_PROTOCOL_LIST (implementation_template)) if (CLASS_PROTOCOL_LIST (implementation_template))
check_protocols (CLASS_PROTOCOL_LIST (implementation_template), check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
...@@ -9848,12 +10060,12 @@ finish_class (tree klass) ...@@ -9848,12 +10060,12 @@ finish_class (tree klass)
{ {
/* Generate what needed for property; setters, getters, etc. */ /* Generate what needed for property; setters, getters, etc. */
objc_gen_property_data (implementation_template, category); objc_gen_property_data (implementation_template, category);
/* Ensure all method listed in the interface contain bodies. */ /* Ensure all method listed in the interface contain bodies. */
check_methods (CLASS_CLS_METHODS (category), check_methods (CLASS_CLS_METHODS (category),
CLASS_CLS_METHODS (objc_implementation_context), '+'); objc_implementation_context, '+');
check_methods (CLASS_NST_METHODS (category), check_methods (CLASS_NST_METHODS (category),
CLASS_NST_METHODS (objc_implementation_context), '-'); objc_implementation_context, '-');
if (CLASS_PROTOCOL_LIST (category)) if (CLASS_PROTOCOL_LIST (category))
check_protocols (CLASS_PROTOCOL_LIST (category), check_protocols (CLASS_PROTOCOL_LIST (category),
...@@ -9870,104 +10082,69 @@ finish_class (tree klass) ...@@ -9870,104 +10082,69 @@ finish_class (tree klass)
tree x; tree x;
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x)) for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{ {
/* Store the getter name that we used into the property.
It is used to generate the right getter calls;
moreover, when a @synthesize is processed, it copies
everything from the property, including the
PROPERTY_GETTER_NAME. We want to be sure that
@synthesize will get exactly the right
PROPERTY_GETTER_NAME. */
if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
PROPERTY_GETTER_NAME (x) = PROPERTY_NAME (x);
/* Now we check that the appropriate getter is declared, /* Now we check that the appropriate getter is declared,
and if not, we declare one ourselves. */ and if not, we declare one ourselves. */
{ tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
tree getter_decl = lookup_method (CLASS_NST_METHODS (klass), PROPERTY_GETTER_NAME (x));
PROPERTY_GETTER_NAME (x));
if (getter_decl)
if (getter_decl) {
{ /* TODO: Check that the declaration is consistent with the property. */
/* TODO: Check that the declaration is consistent with the property. */ ;
; }
} else
else {
{ /* Generate an instance method declaration for the
/* Generate an instance method declaration for the getter; for example "- (id) name;". In general it
getter; for example "- (id) name;". In general will be of the form
it will be of the form -(type)property_getter_name; */
-(type)property_getter_name; */ tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x)); getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
getter_decl = build_method_decl (INSTANCE_METHOD_DECL, rettype, PROPERTY_GETTER_NAME (x),
rettype, PROPERTY_GETTER_NAME (x), NULL_TREE, false);
NULL_TREE, false); objc_add_method (objc_interface_context, getter_decl, false, false);
objc_add_method (objc_interface_context, getter_decl, false, false); METHOD_PROPERTY_CONTEXT (getter_decl) = x;
METHOD_PROPERTY_CONTEXT (getter_decl) = x; }
}
}
if (PROPERTY_READONLY (x) == 0) if (PROPERTY_READONLY (x) == 0)
{ {
/* Store the setter name that we used into the
property. It is used when generating setter calls;
moreover, when a @synthesize is processed, it
copies everything from the property, including the
PROPERTY_SETTER_NAME. We want to be sure that
@synthesize will get exactly the right
PROPERTY_SETTER_NAME. */
if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
PROPERTY_SETTER_NAME (x) = get_identifier (objc_build_property_setter_name
(PROPERTY_NAME (x)));
/* Now we check that the appropriate setter is declared, /* Now we check that the appropriate setter is declared,
and if not, we declare on ourselves. */ and if not, we declare on ourselves. */
{ tree setter_decl = lookup_method (CLASS_NST_METHODS (klass),
tree setter_decl = lookup_method (CLASS_NST_METHODS (klass), PROPERTY_SETTER_NAME (x));
PROPERTY_SETTER_NAME (x));
if (setter_decl)
if (setter_decl) {
{ /* TODO: Check that the declaration is consistent with the property. */
/* TODO: Check that the declaration is consistent with the property. */ ;
; }
} else
else {
{ /* The setter name is something like 'setName:'.
/* The setter name is something like 'setName:'. We need the substring 'setName' to build the
We need the substring 'setName' to build the method declaration due to how the declaration
method declaration due to how the declaration works. TODO: build_method_decl() will then
works. TODO: build_method_decl() will then generate back 'setName:' from 'setName'; it
generate back 'setName:' from 'setName'; it would be more efficient to hook into there. */
would be more efficient to hook into const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
there. */ size_t length = strlen (full_setter_name);
const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x)); char *setter_name = (char *) alloca (length);
size_t length = strlen (full_setter_name); tree ret_type, selector, arg_type, arg_name;
char *setter_name = (char *) alloca (length);
tree ret_type, selector, arg_type, arg_name; strcpy (setter_name, full_setter_name);
setter_name[length - 1] = '\0';
strcpy (setter_name, full_setter_name); ret_type = build_tree_list (NULL_TREE, void_type_node);
setter_name[length - 1] = '\0'; arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
ret_type = build_tree_list (NULL_TREE, void_type_node); arg_name = get_identifier ("_value");
arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x)); selector = objc_build_keyword_decl (get_identifier (setter_name),
arg_name = get_identifier ("_value"); arg_type, arg_name, NULL);
selector = objc_build_keyword_decl (get_identifier (setter_name), setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
arg_type, arg_name, NULL); ret_type, selector,
setter_decl = build_method_decl (INSTANCE_METHOD_DECL, build_tree_list (NULL_TREE, NULL_TREE),
ret_type, selector, false);
build_tree_list (NULL_TREE, NULL_TREE), objc_add_method (objc_interface_context, setter_decl, false, false);
false); METHOD_PROPERTY_CONTEXT (setter_decl) = x;
objc_add_method (objc_interface_context, setter_decl, false, false); }
METHOD_PROPERTY_CONTEXT (setter_decl) = x;
}
}
/* Note how at this point (once an @interface or @protocol
have been processed), PROPERTY_GETTER_NAME is always
set for all PROPERTY_DECLs, and PROPERTY_SETTER_NAME is
always set for all PROPERTY_DECLs where
PROPERTY_READONLY == 0. Any time we deal with a getter
or setter, we should get the PROPERTY_DECL and use
PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME to know
the correct names. */
} }
} }
break; break;
......
...@@ -144,7 +144,10 @@ typedef enum objc_property_assign_semantics { ...@@ -144,7 +144,10 @@ typedef enum objc_property_assign_semantics {
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
PROTOCOL_INTERFACE_TYPE */ PROTOCOL_INTERFACE_TYPE */
/* CLASS_NAME is the name of the class. */
#define CLASS_NAME(CLASS) ((CLASS)->type.name) #define CLASS_NAME(CLASS) ((CLASS)->type.name)
/* CLASS_SUPER_NAME is the name of the superclass, or, in the case of
categories, it is the name of the category itself. */
#define CLASS_SUPER_NAME(CLASS) (TYPE_CHECK (CLASS)->type.context) #define CLASS_SUPER_NAME(CLASS) (TYPE_CHECK (CLASS)->type.context)
#define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0) #define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
#define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1) #define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1)
......
2010-11-08 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/property/at-property-5.m: Updated test.
* objc.dg/property/at-property-16.m: New.
* objc.dg/property/at-property-17.m: New.
* objc.dg/property/at-property-18.m: New.
* objc.dg/property/at-property-19.m: New.
* objc.dg/property/dotsyntax-12.m: New.
* objc.dg/protocol-inheritance-1.m: New.
* objc.dg/protocol-inheritance-2.m: New.
* obj-c++.dg/property/at-property-5.mm: Updated test.
* obj-c++.dg/property/at-property-16.mm: New.
* obj-c++.dg/property/at-property-17.mm: New.
* obj-c++.dg/property/at-property-18.mm: New.
* obj-c++.dg/property/at-property-19.mm: New.
* obj-c++.dg/protocol-inheritance-1.mm: New.
* obj-c++.dg/protocol-inheritance-2.mm: New.
* obj-c++.dg/property/dotsyntax-12.mm: New.
2010-11-08 Jason Merrill <jason@redhat.com> 2010-11-08 Jason Merrill <jason@redhat.com>
* g++.dg/expr/overflow1.C: New. * g++.dg/expr/overflow1.C: New.
......
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class and a
sub-class, the attributes match. */
@interface MyRootClass
{
Class isa;
}
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@end
@interface MyClass : MyRootClass
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@end
/* FIXME - there is a problem with the testuite in running the following test. The compiler generates the messages, but the testsuite still complains. */
@interface MyClass2 : MyRootClass
/* @property (retain) id a; */ /* dg-error "assign semantics attributes of property .a. conflict with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 13 */
/* @property (assign) id b; */ /* dg-error "assign semantics attributes of property .b. conflict with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 14 */
/* @property (nonatomic) int c; */ /* dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 15 */
/* @property int d; */ /* dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 16 */
/* @property (setter=setX:) int e; */ /* dg-error ".setter. attribute of property .e. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 17 */
/* @property (getter=x) int f; */ /* dg-error ".getter. attribute of property .f. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 18 */
/* @property (readonly) int g; */ /* dg-error ".readonly. attribute of property .g. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 19 */
@property (readwrite) int h; /* Ok */
/* @property (readonly) int i; */ /* dg-error ".getter. attribute of property .i. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 21 */
@end
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class, with
getters/setters in the superclass, there are no warnings. */
@interface MyRootClass
{
Class isa;
int myCount;
int myCount2;
int myCount3;
}
- (int)count;
- (void)setCount: (int)number;
- (int)count2;
- (void)setCount2: (int)number;
- (int)count3;
@end
@implementation MyRootClass
- (int) count
{
return myCount;
}
- (void) setCount: (int)number
{
myCount = number;
}
- (int) count2
{
return myCount2;
}
- (void) setCount2: (int)number
{
myCount2 = number;
}
- (int) count3
{
return myCount3;
}
@end
/* Try with a subclass. */
@interface MyClass : MyRootClass
@property int count;
@end
@implementation MyClass
@end /* No warnings. */
/* Try with a category. */
@interface MyRootClass (count)
@property int count;
@end
@implementation MyRootClass (count)
@end /* No warnings. */
/* Try with a category of a subclass. */
@interface MyClass2 : MyClass
@end
@implementation MyClass2
@end
@interface MyClass2 (count2)
@property int count2;
@end
@implementation MyClass2 (count2)
@end /* No warnings. */
/* Now, try with a category of a subclass, but with a missing setter,
which should generate a warning. */
@interface MyClass3 : MyClass
@end
@implementation MyClass3
@end
@interface MyClass3 (count3)
@property int count3;
@end
@implementation MyClass3 (count3)
@end /* { dg-warning "incomplete implementation" } */
/* { dg-warning "method definition for .-setCount3:. not found" "" { target *-*-* } 97 } */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class and a
category, the attributes match. This is almost the same as
at-property-16.m, but for a category. It is a separate file
because it is difficult to test multiple messages for the same
line. */
@interface MyRootClass
{
Class isa;
}
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@property (nonatomic) float j;
@end
/* FIXME - there is a problem with the testuite in running the following test. The compiler generates the messages, but the testsuite still complains. */
@interface MyRootClass (Category)
/*@property (retain) id a; */ /* dg-error "assign semantics attributes of property .a. conflict with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 16 */
/*@property (assign) id b; */ /* dg-error "assign semantics attributes of property .b. conflict with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 17 */
/*@property (nonatomic) int c; */ /* dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 18 */
/*@property int d; */ /* dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 19 */
/*@property (setter=setX:) int e; */ /* dg-error ".setter. attribute of property .e. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 20 */
/*@property (getter=x) int f; */ /* dg-error ".getter. attribute of property .f. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 21 */
/*@property (readonly) int g; */ /* dg-error ".readonly. attribute of property .g. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 22 */
@property (readwrite) int h; /* Ok */
/*@property (readonly) int i; */ /* dg-error ".getter. attribute of property .i. conflicts with previous declaration" */
/* dg-message "originally specified here" "" { target *-*-* } 24 */
@property (nonatomic) float j; /* Ok */
@end
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* Test looking up a @property in a protocol of a category of a superclass. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@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; }
@end
/* Use a different getter/setter, so that the only way to compile
object.count is to find the actual @property. */
@protocol count
@property (getter=number, setter=setNumber:) int count;
@end
@interface MySubClass : MyRootClass
- (int) testMe;
@end
@interface MySubClass (Category) <count>
@end
@implementation MySubClass (Category)
- (int) number
{
return a;
}
- (void) setNumber: (int)count
{
a = count;
}
@end
@implementation MySubClass
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
object.count = 44;
if (object.count != 44)
abort ();
if ([object testMe] != 400)
abort ();
return 0;
}
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
/* FIXME - there is a problem with the testuite in running the following test. The compiler /* FIXME - there is a problem with the testuite in running the following test. The compiler
generates the messages, but the testsuite still complains. */ generates the messages, but the testsuite still complains. */
/*@property (retain) id property_e;*/ /* dg-error "redeclaration of property .property_e." */ /*@property (retain) id property_e;*/ /* dg-error "redeclaration of property .property_e." */
/* dg-message "originally declared here" "" { target *-*-* } 26 */ /* dg-message "originally specified here" "" { target *-*-* } 26 */
@end @end
@property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */ @property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */
/* 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 looking up a setter or getter which are in a protocol attached
to a category of a superclass. */
#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; }
@end
@protocol count
- (int) count;
- (void) setCount: (int)count;
@end
@protocol classCount
+ (int) classCount;
+ (void) setClassCount: (int)count;
@end
@interface MyRootClass (Category) <count, classCount>
@end
@implementation MyRootClass (Category)
- (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
{
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)
{
MySubClass *object = [[MySubClass alloc] init];
object.count = 44;
if (object.count != 44)
abort ();
MySubClass.classCount = 40;
if (MySubClass.classCount != 40)
abort ();
if ([object testMe] != 400)
abort ();
if ([MySubClass testMe] != 4000)
abort ();
return 0;
}
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* { dg-options "-Wno-protocol" } */
#include <objc/objc.h>
/* Test the -Wno-protocol flag. With this, at a class is accepted
(with no warnings) as conforming to a protocol even if some
protocol methods are implemented in the superclass. */
@protocol MyProtocol
- (int)method;
@end
@protocol MyProtocol2
- (int)method2;
@end
/* The superclass implements the method required by the protocol. */
@interface MyRootClass
{
Class isa;
}
- (int)method;
@end
@implementation MyRootClass
- (int)method
{
return 23;
}
@end
/* The subclass inherits the method (does not implement it directly)
but that still makes it conform to the protocol. No warnings. */
@interface MySubClass : MyRootClass <MyProtocol>
@end
@implementation MySubClass
@end /* No warnings here. */
/* The subclass instead does not inherit the method method2 (and does
not implement it directly) so it does not conform to the
protocol MyProtocol2. */
@interface MySubClass2 : MyRootClass <MyProtocol2>
@end
@implementation MySubClass2
@end /* Warnings here, below. */
/* { dg-warning "incomplete implementation of class .MySubClass2." "" { target *-*-* } 50 } */
/* { dg-warning "method definition for .\\-method2. not found" "" { target *-*-* } 50 } */
/* { dg-warning "class .MySubClass2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test standard warnings when a class conforms to a protocol but some
methods are implemented in the superclass. Use -Wno-protocol to
turn these off. */
@protocol MyProtocol
- (int)method;
@end
@protocol MyProtocol2
- (int)method2;
@end
/* The superclass implements the method required by the protocol. */
@interface MyRootClass
{
Class isa;
}
- (int)method;
@end
@implementation MyRootClass
- (int)method
{
return 23;
}
@end
/* The subclass inherits the method (does not implement it directly)
and unless -Wno-protocol is used, we emit a warning. */
@interface MySubClass : MyRootClass <MyProtocol>
@end
@implementation MySubClass
@end
/* { dg-warning "incomplete implementation of class .MySubClass." "" { target *-*-* } 39 } */
/* { dg-warning "method definition for .\\-method. not found" "" { target *-*-* } 39 } */
/* { dg-warning "class .MySubClass. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 39 } */
/* The subclass instead does not inherit the method method2 (and does
not implement it directly) so it does not conform to the
protocol MyProtocol2. */
@interface MySubClass2 : MyRootClass <MyProtocol2>
@end
@implementation MySubClass2
@end /* Warnings here, below. */
/* { dg-warning "incomplete implementation of class .MySubClass2." "" { target *-*-* } 53 } */
/* { dg-warning "method definition for .\\-method2. not found" "" { target *-*-* } 53 } */
/* { dg-warning "class .MySubClass2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 53 } */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class and a
sub-class, the attributes match. */
@interface MyRootClass
{
Class isa;
}
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@end
@interface MyClass : MyRootClass
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@end
@interface MyClass2 : MyRootClass
@property (retain) id a; /* { dg-error "assign semantics attributes of property .a. conflict with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 13 } */
@property (assign) id b; /* { dg-error "assign semantics attributes of property .b. conflict with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 14 } */
@property (nonatomic) int c; /* { dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 15 } */
@property int d; /* { dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 16 } */
@property (setter=setX:) int e; /* { dg-error ".setter. attribute of property .e. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 17 } */
@property (getter=x) int f; /* { dg-error ".getter. attribute of property .f. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 18 } */
@property (readonly) int g; /* { dg-error ".readonly. attribute of property .g. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 19 } */
@property (readwrite) int h; /* Ok */
@property (readonly) int i; /* { dg-error ".getter. attribute of property .i. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 21 } */
@end
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class, with
getters/setters in the superclass, there are no warnings. */
@interface MyRootClass
{
Class isa;
int myCount;
int myCount2;
int myCount3;
}
- (int)count;
- (void)setCount: (int)number;
- (int)count2;
- (void)setCount2: (int)number;
- (int)count3;
@end
@implementation MyRootClass
- (int) count
{
return myCount;
}
- (void) setCount: (int)number
{
myCount = number;
}
- (int) count2
{
return myCount2;
}
- (void) setCount2: (int)number
{
myCount2 = number;
}
- (int) count3
{
return myCount3;
}
@end
/* Try with a subclass. */
@interface MyClass : MyRootClass
@property int count;
@end
@implementation MyClass
@end /* No warnings. */
/* Try with a category. */
@interface MyRootClass (count)
@property int count;
@end
@implementation MyRootClass (count)
@end /* No warnings. */
/* Try with a category of a subclass. */
@interface MyClass2 : MyClass
@end
@implementation MyClass2
@end
@interface MyClass2 (count2)
@property int count2;
@end
@implementation MyClass2 (count2)
@end /* No warnings. */
/* Now, try with a category of a subclass, but with a missing setter,
which should generate a warning. */
@interface MyClass3 : MyClass
@end
@implementation MyClass3
@end
@interface MyClass3 (count3)
@property int count3;
@end
@implementation MyClass3 (count3)
@end /* { dg-warning "incomplete implementation" } */
/* { dg-warning "method definition for .-setCount3:. not found" "" { target *-*-* } 97 } */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that if you have a property declared in a class and a
category, the attributes match. This is almost the same as
at-property-16.m, but for a category. It is a separate file
because it is difficult to test multiple messages for the same
line. */
@interface MyRootClass
{
Class isa;
}
@property (assign) id a;
@property (retain) id b;
@property int c;
@property (nonatomic) int d;
@property int e;
@property int f;
@property int g;
@property (readonly) int h;
@property (readonly,getter=getMe) int i;
@property (nonatomic) float j;
@end
@interface MyRootClass (Category)
@property (retain) id a; /* { dg-error "assign semantics attributes of property .a. conflict with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 16 } */
@property (assign) id b; /* { dg-error "assign semantics attributes of property .b. conflict with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 17 } */
@property (nonatomic) int c; /* { dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 18 } */
@property int d; /* { dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 19 } */
@property (setter=setX:) int e; /* { dg-error ".setter. attribute of property .e. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 20 } */
@property (getter=x) int f; /* { dg-error ".getter. attribute of property .f. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 21 } */
@property (readonly) int g; /* { dg-error ".readonly. attribute of property .g. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 22 } */
@property (readwrite) int h; /* Ok */
@property (readonly) int i; /* { dg-error ".getter. attribute of property .i. conflicts with previous declaration" } */
/* { dg-message "originally specified here" "" { target *-*-* } 24 } */
@property (nonatomic) float j; /* Ok */
@end
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* Test looking up a @property in a protocol of a category of a superclass. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@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; }
@end
/* Use a different getter/setter, so that the only way to compile
object.count is to find the actual @property. */
@protocol count
@property (getter=number, setter=setNumber:) int count;
@end
@interface MySubClass : MyRootClass
- (int) testMe;
@end
@interface MySubClass (Category) <count>
@end
@implementation MySubClass (Category)
- (int) number
{
return a;
}
- (void) setNumber: (int)count
{
a = count;
}
@end
@implementation MySubClass
- (int) testMe
{
self.count = 400;
if (self.count != 400)
abort ();
return self.count;
}
@end
int main (void)
{
MySubClass *object = [[MySubClass alloc] init];
object.count = 44;
if (object.count != 44)
abort ();
if ([object testMe] != 400)
abort ();
return 0;
}
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
@property (retain) id property_g; @property (retain) id property_g;
@property (retain) id property_h; @property (retain) id property_h;
@property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */ @property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */
/* { dg-message "originally declared here" "" { target *-*-* } 26 } */ /* { dg-message "originally specified here" "" { target *-*-* } 26 } */
@end @end
@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */ @property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */
/* 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 looking up a setter or getter which are in a protocol attached
to a category of a superclass. */
#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; }
@end
@protocol count
- (int) count;
- (void) setCount: (int)count;
@end
@protocol classCount
+ (int) classCount;
+ (void) setClassCount: (int)count;
@end
@interface MyRootClass (Category) <count, classCount>
@end
@implementation MyRootClass (Category)
- (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
{
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)
{
MySubClass *object = [[MySubClass alloc] init];
object.count = 44;
if (object.count != 44)
abort ();
MySubClass.classCount = 40;
if (MySubClass.classCount != 40)
abort ();
if ([object testMe] != 400)
abort ();
if ([MySubClass testMe] != 4000)
abort ();
return 0;
}
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* { dg-options "-Wno-protocol" } */
#include <objc/objc.h>
/* Test the -Wno-protocol flag. With this, at a class is accepted
(with no warnings) as conforming to a protocol even if some
protocol methods are implemented in the superclass. */
@protocol MyProtocol
- (int)method;
@end
@protocol MyProtocol2
- (int)method2;
@end
/* The superclass implements the method required by the protocol. */
@interface MyRootClass
{
Class isa;
}
- (int)method;
@end
@implementation MyRootClass
- (int)method
{
return 23;
}
@end
/* The subclass inherits the method (does not implement it directly)
but that still makes it conform to the protocol. No warnings. */
@interface MySubClass : MyRootClass <MyProtocol>
@end
@implementation MySubClass
@end /* No warnings here. */
/* The subclass instead does not inherit the method method2 (and does
not implement it directly) so it does not conform to the
protocol MyProtocol2. */
@interface MySubClass2 : MyRootClass <MyProtocol2>
@end
@implementation MySubClass2
@end /* Warnings here, below. */
/* { dg-warning "incomplete implementation of class .MySubClass2." "" { target *-*-* } 50 } */
/* { dg-warning "method definition for .\\-method2. not found" "" { target *-*-* } 50 } */
/* { dg-warning "class .MySubClass2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test standard warnings when a class conforms to a protocol but some
methods are implemented in the superclass. Use -Wno-protocol to
turn these off. */
@protocol MyProtocol
- (int)method;
@end
@protocol MyProtocol2
- (int)method2;
@end
/* The superclass implements the method required by the protocol. */
@interface MyRootClass
{
Class isa;
}
- (int)method;
@end
@implementation MyRootClass
- (int)method
{
return 23;
}
@end
/* The subclass inherits the method (does not implement it directly)
and unless -Wno-protocol is used, we emit a warning. */
@interface MySubClass : MyRootClass <MyProtocol>
@end
@implementation MySubClass
@end
/* { dg-warning "incomplete implementation of class .MySubClass." "" { target *-*-* } 39 } */
/* { dg-warning "method definition for .\\-method. not found" "" { target *-*-* } 39 } */
/* { dg-warning "class .MySubClass. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 39 } */
/* The subclass instead does not inherit the method method2 (and does
not implement it directly) so it does not conform to the
protocol MyProtocol2. */
@interface MySubClass2 : MyRootClass <MyProtocol2>
@end
@implementation MySubClass2
@end /* Warnings here, below. */
/* { dg-warning "incomplete implementation of class .MySubClass2." "" { target *-*-* } 53 } */
/* { dg-warning "method definition for .\\-method2. not found" "" { target *-*-* } 53 } */
/* { dg-warning "class .MySubClass2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 53 } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment