diff options
author | Nicola Pero <nicola.pero@meta-innovation.com> | 2010-11-11 18:58:43 +0000 |
---|---|---|
committer | Nicola Pero <nicola@gcc.gnu.org> | 2010-11-11 18:58:43 +0000 |
commit | 10e34e6eb1c29981b1e633c670de49b8634493ae (patch) | |
tree | 9caffb5656c139686769f77c990dd121c19d4c86 /gcc/objc/objc-act.c | |
parent | a1d8aa4b1fc433931788b63d51e652969509e4cd (diff) | |
download | gcc-10e34e6eb1c29981b1e633c670de49b8634493ae.zip gcc-10e34e6eb1c29981b1e633c670de49b8634493ae.tar.gz gcc-10e34e6eb1c29981b1e633c670de49b8634493ae.tar.bz2 |
In gcc/objc/: 2010-11-11 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/:
2010-11-11 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (objc_add_property_declaration): Check that the type
of a property and of an inherited property match.
(objc_maybe_build_component_ref): Tidied up indentation and
comments.
(objc_common_type): Added new type of check (-5). If an unknown
class is involved in a comparison, try to look up its interface.
(objc_add_synthesize_declaration_for_property): Check that the
property to synthesize and the instance variable to use have the
same type.
In gcc/testsuite/:
2010-11-11 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/property/at-property-20.m: New.
* objc.dg/property/synthesize-8.m: New.
* obj-c++.dg/property/at-property-20.m: New.
* obj-c++.dg/property/synthesize-8.mm: New.
From-SVN: r166612
Diffstat (limited to 'gcc/objc/objc-act.c')
-rw-r--r-- | gcc/objc/objc-act.c | 147 |
1 files changed, 98 insertions, 49 deletions
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 6f499c3..715623f 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -1184,22 +1184,41 @@ objc_add_property_declaration (location_t location, tree decl, 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. */ - ; + /* We now check that the new and old property declarations have + the same types (or compatible one). In the Objective-C + tradition of loose type checking, we do type-checking but + only generate warnings (not errors) if they do not match. + For non-readonly properties, the types must match exactly; + for readonly properties, it is allowed to use a "more + specialized" type in the new property declaration. Eg, the + superclass has a getter returning (NSArray *) and the + subclass a getter returning (NSMutableArray *). The object's + getter returns an (NSMutableArray *); but if you cast the + object to the superclass, which is allowed, you'd still + expect the getter to return an (NSArray *), which works since + an (NSMutableArray *) is an (NSArray *) too. So, the set of + objects belonging to the type of the new @property should be + a subset of the set of objects belonging to the type of the + old @property. This is what "specialization" means. And the + reason it only applies to readonly properties is that for a + readwrite property the setter would have the opposite + requirement - ie that the superclass type is more specialized + then the subclass one; hence the only way to satisfy both + constraints is that the types match. */ + + /* If the types are not the same in the C sense, we warn ... */ + if (!comptypes (TREE_TYPE (x), TREE_TYPE (decl)) + /* ... unless the property is readonly, in which case we + allow a new, more specialized, declaration. */ + && (!property_readonly + || !objc_compare_types (TREE_TYPE (x), + TREE_TYPE (decl), -5, NULL_TREE))) + { + warning_at (location, 0, + "type of property %qD conflicts with previous declaration", decl); + if (original_location != UNKNOWN_LOCATION) + inform (original_location, "originally specified here"); + return; } } @@ -1445,15 +1464,10 @@ objc_maybe_build_component_ref (tree object, tree property_ident) else if (t == self_decl) interface_type = lookup_interface (CLASS_NAME (implementation_template)); - /* TODO: Protocols. */ - if (interface_type) { if (TREE_CODE (objc_method_context) != CLASS_METHOD_DECL) - { - x = lookup_property (interface_type, property_ident); - /* TODO: Protocols. */ - } + x = lookup_property (interface_type, property_ident); if (x == NULL_TREE) { @@ -1468,8 +1482,6 @@ objc_maybe_build_component_ref (tree object, tree property_ident) if (t == self_decl) implementation = objc_implementation_context; - /* TODO: Protocols. */ - x = maybe_make_artificial_property_decl (interface_type, implementation, NULL_TREE, property_ident, @@ -1544,8 +1556,6 @@ objc_maybe_build_component_ref (tree object, tree property_ident) } } - /* TODO: Fix compiling super.accessor. */ - if (x) { tree expression; @@ -2121,8 +2131,8 @@ objc_common_type (tree type1, tree type2) returning 'true', this routine may issue warnings related to, e.g., protocol conformance. When returning 'false', the routine must produce absolutely no warnings; the C or C++ front-end will do so - instead, if needed. If either LTYP or RTYP is not an Objective-C type, - the routine must return 'false'. + instead, if needed. If either LTYP or RTYP is not an Objective-C + type, the routine must return 'false'. The ARGNO parameter is encoded as follows: >= 1 Parameter number (CALLEE contains function being called); @@ -2130,8 +2140,11 @@ objc_common_type (tree type1, tree type2) -1 Assignment; -2 Initialization; -3 Comparison (LTYP and RTYP may match in either direction); - -4 Silent comparison (for C++ overload resolution). - */ + -4 Silent comparison (for C++ overload resolution); + -5 Silent "specialization" comparison for RTYP to be a "specialization" + of LTYP (a specialization means that RTYP is LTYP plus some constraints, + so that each object of type RTYP is also of type LTYP). This is used + when comparing property types. */ bool objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee) @@ -2216,11 +2229,24 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee) if (rcls && TREE_CODE (rcls) == IDENTIFIER_NODE) rcls = NULL_TREE; - /* If either type is an unqualified 'id', we're done. */ - if ((!lproto && objc_is_object_id (ltyp)) - || (!rproto && objc_is_object_id (rtyp))) - return true; - + /* If either type is an unqualified 'id', we're done. This is because + an 'id' can be assigned to or from any type with no warnings. */ + if (argno != -5) + { + if ((!lproto && objc_is_object_id (ltyp)) + || (!rproto && objc_is_object_id (rtyp))) + return true; + } + else + { + /* For property checks, though, an 'id' is considered the most + general type of object, hence if you try to specialize an + 'NSArray *' (ltyp) property with an 'id' (rtyp) one, we need + to warn. */ + if (!lproto && objc_is_object_id (ltyp)) + return true; + } + pointers_compatible = (TYPE_MAIN_VARIANT (ltyp) == TYPE_MAIN_VARIANT (rtyp)); /* If the underlying types are the same, and at most one of them has @@ -2236,13 +2262,22 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee) else { if (!pointers_compatible) - pointers_compatible - = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp)); + { + /* Again, if any of the two is an 'id', we're satisfied, + unless we're comparing properties, in which case only an + 'id' on the left-hand side (old property) is good + enough. */ + if (argno != -5) + pointers_compatible + = (objc_is_object_id (ltyp) || objc_is_object_id (rtyp)); + else + pointers_compatible = objc_is_object_id (ltyp); + } if (!pointers_compatible) pointers_compatible = DERIVED_FROM_P (ltyp, rtyp); - if (!pointers_compatible && argno <= -3) + if (!pointers_compatible && (argno == -3 || argno == -4)) pointers_compatible = DERIVED_FROM_P (rtyp, ltyp); } @@ -2268,6 +2303,7 @@ objc_compare_types (tree ltyp, tree rtyp, int argno, tree callee) ObjC-specific. */ switch (argno) { + case -5: case -4: return false; @@ -9797,19 +9833,32 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac if (ivar_name == NULL_TREE) ivar_name = property_name; - /* Check that the instance variable exists. You can only use a - non-private instance variable from the same class, not one from - the superclass (this makes sense as it allows us to check that an + /* Check that the instance variable exists. You can only use an + instance variable from the same class, not one from the + superclass (this makes sense as it allows us to check that an instance variable is only used in one synthesized property). */ - if (!is_ivar (CLASS_IVARS (interface), ivar_name)) - { - error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", - IDENTIFIER_POINTER (property_name)); - return; - } + { + tree ivar = is_ivar (CLASS_IVARS (interface), ivar_name); + if (!ivar) + { + error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", + IDENTIFIER_POINTER (property_name)); + return; + } - /* TODO: Check that the types of the instance variable and of the - property match. */ + /* If the instance variable has a different C type, we warn. */ + if (!comptypes (TREE_TYPE (property), TREE_TYPE (ivar))) + { + location_t original_location = DECL_SOURCE_LOCATION (ivar); + + error_at (location, "property %qs is using instance variable %qs of incompatible type", + IDENTIFIER_POINTER (property_name), + IDENTIFIER_POINTER (ivar_name)); + + if (original_location != UNKNOWN_LOCATION) + inform (original_location, "originally specified here"); + } + } /* Check that no other property is using the same instance variable. */ |