===================================================================
@@ -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
@property... declaration is found. 'decl' is the declaration of
the property (type/identifier), and the other arguments represent
@@ -920,19 +992,6 @@ objc_add_property_declaration (location_t location
/* At this point we know that we are either in an interface, a
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.
This should never happen as the parser doesn't allow this, but
it's just in case. */
@@ -984,8 +1043,39 @@ objc_add_property_declaration (location_t location
&& !objc_type_valid_for_messaging (TREE_TYPE (decl), true))
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
- 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))
{
if (PROPERTY_NAME (x) == DECL_NAME (decl))
@@ -995,15 +1085,127 @@ objc_add_property_declaration (location_t location
error_at (location, "redeclaration of property %qD", decl);
if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally declared here");
+ inform (original_location, "originally specified here");
return;
}
}
- /* TODO: Shall we check here for other property declaractions (in
- the superclass, other categories or protocols) with the same name
- and conflicting types ? */
+ /* We now need to check for existing property declarations (in the
+ superclass, other categories or protocols) and check that the new
+ 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. */
property_decl = make_node (PROPERTY_DECL);
@@ -1022,74 +1224,18 @@ objc_add_property_declaration (location_t location
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
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. */
TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
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
list of methods in the interface (and, failing that, the local list
in the implementation, and failing that, the protocol list)
@@ -1295,7 +1441,10 @@ objc_maybe_build_component_ref (tree object, tree
t = TREE_OPERAND (t, 0);
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)
interface_type = lookup_interface (CLASS_NAME (implementation_template));
@@ -8564,20 +8713,34 @@ objc_is_public (tree expr, tree identifier)
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
-check_methods (tree chain, tree list, int mtype)
+check_methods (tree chain, tree implementation, int mtype)
{
int first = 1;
+ tree list;
+ if (mtype == (int)'+')
+ list = CLASS_CLS_METHODS (implementation);
+ else
+ list = CLASS_NST_METHODS (implementation);
+
while (chain)
{
/* If the method is associated with a dynamic property, then it
is Ok not to have the method implementation, as it will be
generated dynamically at runtime. */
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... */
continue;
@@ -8585,17 +8748,66 @@ static int
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)
{
- switch (TREE_CODE (objc_implementation_context))
+ switch (TREE_CODE (implementation))
{
case CLASS_IMPLEMENTATION_TYPE:
warning (0, "incomplete implementation of class %qE",
- CLASS_NAME (objc_implementation_context));
+ CLASS_NAME (implementation));
break;
case CATEGORY_IMPLEMENTATION_TYPE:
warning (0, "incomplete implementation of category %qE",
- CLASS_SUPER_NAME (objc_implementation_context));
+ CLASS_SUPER_NAME (implementation));
break;
default:
gcc_unreachable ();
@@ -8733,10 +8945,10 @@ check_protocol (tree p, const char *type, tree nam
if (warn_protocol)
{
f1 = check_methods (PROTOCOL_CLS_METHODS (p),
- CLASS_CLS_METHODS (objc_implementation_context),
+ objc_implementation_context,
'+');
f2 = check_methods (PROTOCOL_NST_METHODS (p),
- CLASS_NST_METHODS (objc_implementation_context),
+ objc_implementation_context,
'-');
}
else
@@ -9829,9 +10041,9 @@ finish_class (tree klass)
{
/* Ensure that all method listed in the interface contain bodies. */
check_methods (CLASS_CLS_METHODS (implementation_template),
- CLASS_CLS_METHODS (objc_implementation_context), '+');
+ objc_implementation_context, '+');
check_methods (CLASS_NST_METHODS (implementation_template),
- CLASS_NST_METHODS (objc_implementation_context), '-');
+ objc_implementation_context, '-');
if (CLASS_PROTOCOL_LIST (implementation_template))
check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
@@ -9848,12 +10060,12 @@ finish_class (tree klass)
{
/* Generate what needed for property; setters, getters, etc. */
objc_gen_property_data (implementation_template, category);
-
+
/* Ensure all method listed in the interface contain bodies. */
check_methods (CLASS_CLS_METHODS (category),
- CLASS_CLS_METHODS (objc_implementation_context), '+');
+ objc_implementation_context, '+');
check_methods (CLASS_NST_METHODS (category),
- CLASS_NST_METHODS (objc_implementation_context), '-');
+ objc_implementation_context, '-');
if (CLASS_PROTOCOL_LIST (category))
check_protocols (CLASS_PROTOCOL_LIST (category),
@@ -9870,104 +10082,69 @@ finish_class (tree klass)
tree 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,
and if not, we declare one ourselves. */
- {
- tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
- PROPERTY_GETTER_NAME (x));
-
- if (getter_decl)
- {
- /* TODO: Check that the declaration is consistent with the property. */
- ;
- }
- else
- {
- /* Generate an instance method declaration for the
- getter; for example "- (id) name;". In general
- it will be of the form
- -(type)property_getter_name; */
- tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
- getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- rettype, PROPERTY_GETTER_NAME (x),
- NULL_TREE, false);
- objc_add_method (objc_interface_context, getter_decl, false, false);
- METHOD_PROPERTY_CONTEXT (getter_decl) = x;
- }
- }
+ tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
+ PROPERTY_GETTER_NAME (x));
+
+ if (getter_decl)
+ {
+ /* TODO: Check that the declaration is consistent with the property. */
+ ;
+ }
+ else
+ {
+ /* Generate an instance method declaration for the
+ getter; for example "- (id) name;". In general it
+ will be of the form
+ -(type)property_getter_name; */
+ tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
+ getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
+ rettype, PROPERTY_GETTER_NAME (x),
+ NULL_TREE, false);
+ objc_add_method (objc_interface_context, getter_decl, false, false);
+ METHOD_PROPERTY_CONTEXT (getter_decl) = x;
+ }
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,
and if not, we declare on ourselves. */
- {
- tree setter_decl = lookup_method (CLASS_NST_METHODS (klass),
- PROPERTY_SETTER_NAME (x));
-
- if (setter_decl)
- {
- /* TODO: Check that the declaration is consistent with the property. */
- ;
- }
- else
- {
- /* The setter name is something like 'setName:'.
- We need the substring 'setName' to build the
- method declaration due to how the declaration
- works. TODO: build_method_decl() will then
- generate back 'setName:' from 'setName'; it
- would be more efficient to hook into
- there. */
- const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
- size_t length = strlen (full_setter_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';
- ret_type = build_tree_list (NULL_TREE, void_type_node);
- arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
- arg_name = get_identifier ("_value");
- selector = objc_build_keyword_decl (get_identifier (setter_name),
- arg_type, arg_name, NULL);
- setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- ret_type, selector,
- build_tree_list (NULL_TREE, NULL_TREE),
- false);
- 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. */
+ tree setter_decl = lookup_method (CLASS_NST_METHODS (klass),
+ PROPERTY_SETTER_NAME (x));
+
+ if (setter_decl)
+ {
+ /* TODO: Check that the declaration is consistent with the property. */
+ ;
+ }
+ else
+ {
+ /* The setter name is something like 'setName:'.
+ We need the substring 'setName' to build the
+ method declaration due to how the declaration
+ works. TODO: build_method_decl() will then
+ generate back 'setName:' from 'setName'; it
+ would be more efficient to hook into there. */
+ const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
+ size_t length = strlen (full_setter_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';
+ ret_type = build_tree_list (NULL_TREE, void_type_node);
+ arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
+ arg_name = get_identifier ("_value");
+ selector = objc_build_keyword_decl (get_identifier (setter_name),
+ arg_type, arg_name, NULL);
+ setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
+ ret_type, selector,
+ build_tree_list (NULL_TREE, NULL_TREE),
+ false);
+ objc_add_method (objc_interface_context, setter_decl, false, false);
+ METHOD_PROPERTY_CONTEXT (setter_decl) = x;
+ }
}
}
break;
===================================================================
@@ -1,3 +1,21 @@
+2010-11-07 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>
Fixed using the Objective-C 2.0 syntax with self and super.
===================================================================
@@ -144,7 +144,10 @@ typedef enum objc_property_assign_semantics {
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
PROTOCOL_INTERFACE_TYPE */
+/* CLASS_NAME is the name of the class. */
#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_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)
===================================================================
@@ -1,3 +1,22 @@
+2010-11-07 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-06 Nicola Pero <nicola.pero@meta-innovation.com>
Fixed using the Objective-C 2.0 dot-syntax with self and super.
===================================================================
@@ -0,0 +1,54 @@
+/* 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 } */
===================================================================
@@ -0,0 +1,105 @@
+/* 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;
+}
===================================================================
@@ -28,7 +28,7 @@
@property (retain) id property_g;
@property (retain) id property_h;
@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
@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */
===================================================================
@@ -0,0 +1,55 @@
+/* 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
+
===================================================================
@@ -0,0 +1,98 @@
+/* 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 } */
===================================================================
@@ -0,0 +1,47 @@
+/* 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
===================================================================
@@ -0,0 +1,74 @@
+/* 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;
+}
===================================================================
@@ -0,0 +1,57 @@
+/* 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 } */
===================================================================
@@ -0,0 +1,98 @@
+/* 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 } */
===================================================================
@@ -0,0 +1,74 @@
+/* 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 @@
/* FIXME - there is a problem with the testuite in running the following test. The compiler
generates the messages, but the testsuite still complains. */
/*@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
@property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */
===================================================================
@@ -0,0 +1,54 @@
+/* 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
===================================================================
@@ -0,0 +1,47 @@
+/* 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
===================================================================
@@ -0,0 +1,105 @@
+/* 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;
+}
===================================================================
@@ -0,0 +1,57 @@
+/* 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 } */
===================================================================
@@ -0,0 +1,54 @@
+/* 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 } */