diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-03 12:17:59 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-03 12:17:59 +0000 |
commit | 73556f5f6c5d835df3baa9979de74da7bd85cd05 (patch) | |
tree | ac76e75c45976914468f05d9d01c6dab44ff831c /gcc/objc | |
parent | 009b254c18c50184aadbc41673222104cec47838 (diff) | |
download | gcc-73556f5f6c5d835df3baa9979de74da7bd85cd05.tar.gz |
2011-01-03 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 168414
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@168419 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/objc')
-rw-r--r-- | gcc/objc/ChangeLog | 109 | ||||
-rw-r--r-- | gcc/objc/config-lang.in | 2 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 428 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 5 | ||||
-rw-r--r-- | gcc/objc/objc-tree.def | 10 |
5 files changed, 440 insertions, 114 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index d519ad77327..6da04931bdf 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,112 @@ +2011-01-02 H.J. Lu <hongjiu.lu@intel.com> + + * objc-act.c (check_that_protocol_is_defined): Fix a typo. + +2011-01-02 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (check_that_protocol_is_defined): New. + (lookup_protocol): Call check_that_protocol_is_defined. + +2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (objc_types_are_equivalent): Fixed comparing protocol + lists. Check them two-ways to fix comparisons when one protocol + implements the other one, or when one list contains duplicated + protocols. + +2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (objc_add_method): When emitting an error because a + method with the same name but conflicting types is found in the + same class or category interface, print a note with the location + of the original method. Also, improved the error message to + clearly state that the conflict is due to conflicting types, and + produce it for protocols as well. Emit an error if two identical + methods are declared in a protocol, but one is @required and the + other one is @optional. + +2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (start_class): Warn when a class attribute is + ignored. + (objc_declare_protocols): Warn when a protocol attribute in a + protocol forward-declaration is ignored. + (start_protocol): Warn when a protocol attribute is ignored. + +2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (objc_set_method_opt): Tidy up error messages. In + particular, explicitly mention whether the error is due to the + @optional or @required keyword instead of mentioning + "@optional/@required". + +2010-12-29 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47118 + * objc-act.c (objc_build_synchronized): Check the argument of + @synchronized and emit an appropriate error if it is not a valid + Objective-C object. Deal gracefully with that case. Updated + comments and variable names. + +2010-12-29 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47075 + * objc-act.h (PROPERTY_REF_DEPRECATED_GETTER): New. + * objc-tree.def (PROPERTY_REF): Increased the number of operands + from 3 to 4. + * objc-act.c (objc_finish_message_expr): Added optional argument + allowing to return the deprecated method prototype for deprecated + methods, instead of immediately emitting the deprecation warning. + (objc_maybe_build_component_ref): Do not warn for a deprecated + property. When building the getter call, get the deprecated + method prototype from objc_finish_message_expr() and put it into + the PROPERTY_REF. + (objc_build_class_component_ref): Same change. + (finish_class): Mark the getter and setter as deprecated if they + are generated from a deprecated property. + (objc_gimplify_property_ref): If the getter is deprecated, emit a + deprecation warning. + (objc_build_setter_call, objc_build_message_expr, + objc_finish_foreach_loop): Updated call to + objc_finish_message_expr. + +2010-12-28 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47076 + * objc-act.c (lookup_protocol): Added 'definition_required' + argument. If 'definition_required', and the protocol is not + defined, emit a warning. + (objc_declare_protocols): Updated call to lookup_protocol. + (start_protocol): Same change. + (check_protocol_recursively): Same change. + (objc_build_protocol_expr): Same change. + (lookup_and_install_protocols): Added definition_required argument. + Pass it to lookup_protocol. + (objc_get_protocol_qualified_type): Updated call to + lookup_and_install_protocols. + (start_class): Updated calls to lookup_and_install_protocols; pass + true to 'definition_required' to get the warnings. + (start_protocol): Updated calls to lookup_and_install_protocols. + +2010-12-28 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (objc_start_category_interface): Produce an error if + a class extension is found after the class @implementation. + +2010-12-28 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/47073 + * objc-act.c (encode_method_prototype): Fixed both location and + format string of error "type %qT does not have a known size". + +2010-12-26 Nicola Pero <nicola.pero@meta-innovation.com> + + * config-lang.in (gtfiles): Added c-family/c-cppbuiltin.c. + +2010-12-22 Nathan Froyd <froydnj@codesourcery.com> + + * objc-act.c (next_sjlj_build_enter_and_setjmp): Use prototype_p. + 2010-12-18 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (objc_init): Call using_eh_for_cleanups. diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in index 3f296faf109..9d935757185 100644 --- a/gcc/objc/config-lang.in +++ b/gcc/objc/config-lang.in @@ -33,4 +33,4 @@ target_libs=target-libobjc # Most of the object files for cc1obj actually come from C. lang_requires="c" -gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/objc/objc-act.c" +gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/objc/objc-act.c" diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 2076111c4d6..605705b04ff 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -232,8 +232,8 @@ static void build_selector_table_decl (void); /* Protocols. */ -static tree lookup_protocol (tree, bool); -static tree lookup_and_install_protocols (tree); +static tree lookup_protocol (tree, bool, bool); +static tree lookup_and_install_protocols (tree, bool); /* Type encoding. */ @@ -763,6 +763,23 @@ objc_start_category_interface (tree klass, tree categ, { if (flag_objc1_only) error_at (input_location, "class extensions are not available in Objective-C 1.0"); + else + { + /* Iterate over all the classes and categories implemented + up to now in this compilation unit. */ + struct imp_entry *t; + + for (t = imp_list; t; t = t->next) + { + /* If we find a class @implementation with the same name + as the one we are extending, produce an error. */ + if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE + && IDENTIFIER_POINTER (CLASS_NAME (t->imp_context)) == IDENTIFIER_POINTER (klass)) + error_at (input_location, + "class extension for class %qE declared after its %<@implementation%>", + klass); + } + } } objc_interface_context = start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos, NULL_TREE); @@ -859,13 +876,21 @@ void objc_set_method_opt (bool optional) { if (flag_objc1_only) - error_at (input_location, "@optional/@required are not available in Objective-C 1.0"); + { + if (optional) + error_at (input_location, "%<@optional%> is not available in Objective-C 1.0"); + else + error_at (input_location, "%<@required%> is not available in Objective-C 1.0"); + } objc_method_optional_flag = optional; if (!objc_interface_context || TREE_CODE (objc_interface_context) != PROTOCOL_INTERFACE_TYPE) { - error ("@optional/@required is allowed in @protocol context only"); + if (optional) + error ("%<@optional%> is allowed in @protocol context only"); + else + error ("%<@required%> is allowed in @protocol context only"); objc_method_optional_flag = false; } } @@ -1451,7 +1476,7 @@ maybe_make_artificial_property_decl (tree interface, tree implementation, DECL_SOURCE_LOCATION (property_decl) = input_location; TREE_DEPRECATED (property_decl) = 0; DECL_ARTIFICIAL (property_decl) = 1; - + /* Add property-specific information. Note that one of PROPERTY_GETTER_NAME or PROPERTY_SETTER_NAME may refer to a non-existing method; this will generate an error when the @@ -1726,6 +1751,7 @@ objc_maybe_build_component_ref (tree object, tree property_ident) { tree expression; tree getter_call; + tree deprecated_method_prototype = NULL_TREE; /* We have an additional nasty problem here; if this PROPERTY_REF needs to become a 'getter', then the conversion @@ -1753,14 +1779,16 @@ objc_maybe_build_component_ref (tree object, tree property_ident) if (PROPERTY_HAS_NO_GETTER (x)) getter_call = NULL_TREE; else - getter_call = objc_finish_message_expr (object, - PROPERTY_GETTER_NAME (x), - NULL_TREE); - - if (TREE_DEPRECATED (x)) - warn_deprecated_use (x, NULL_TREE); - - expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call); + getter_call = objc_finish_message_expr + (object, PROPERTY_GETTER_NAME (x), NULL_TREE, + /* Disable the immediate deprecation warning if the getter + is deprecated, but record the fact that the getter is + deprecated by setting PROPERTY_REF_DEPRECATED_GETTER to + the method prototype. */ + &deprecated_method_prototype); + + expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call, + deprecated_method_prototype); SET_EXPR_LOCATION (expression, input_location); TREE_SIDE_EFFECTS (expression) = 1; @@ -1822,17 +1850,17 @@ objc_build_class_component_ref (tree class_name, tree property_ident) { tree expression; tree getter_call; + tree deprecated_method_prototype = NULL_TREE; if (PROPERTY_HAS_NO_GETTER (x)) getter_call = NULL_TREE; else - getter_call = objc_finish_message_expr (object, - PROPERTY_GETTER_NAME (x), - NULL_TREE); - if (TREE_DEPRECATED (x)) - warn_deprecated_use (x, NULL_TREE); + getter_call = objc_finish_message_expr + (object, PROPERTY_GETTER_NAME (x), NULL_TREE, + &deprecated_method_prototype); - expression = build3 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call); + expression = build4 (PROPERTY_REF, TREE_TYPE(x), object, x, getter_call, + deprecated_method_prototype); SET_EXPR_LOCATION (expression, input_location); TREE_SIDE_EFFECTS (expression) = 1; @@ -1889,7 +1917,7 @@ objc_build_setter_call (tree lhs, tree rhs) /* TODO: Decay arguments in C. */ setter = objc_finish_message_expr (object_expr, PROPERTY_SETTER_NAME (property_decl), - setter_argument); + setter_argument, NULL); return setter; } @@ -2906,7 +2934,8 @@ objc_get_protocol_qualified_type (tree interface, tree protocols) /* Look up protocols and install in lang specific list. */ DUP_TYPE_OBJC_INFO (type, TYPE_MAIN_VARIANT (type)); - TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols (protocols); + TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols + (protocols, /* definition_required */ false); /* For RECORD_TYPEs, point to the @interface; for 'id' and 'Class', return the pointer to the new pointee variant. */ @@ -2934,7 +2963,8 @@ check_protocol_recursively (tree proto, tree list) tree pp = TREE_VALUE (p); if (TREE_CODE (pp) == IDENTIFIER_NODE) - pp = lookup_protocol (pp, /* warn if deprecated */ false); + pp = lookup_protocol (pp, /* warn if deprecated */ false, + /* definition_required */ false); if (pp == proto) fatal_error ("protocol %qE has circular dependency", @@ -2946,10 +2976,13 @@ check_protocol_recursively (tree proto, tree list) /* Look up PROTOCOLS, and return a list of those that are found. If none are found, return NULL. Note that this function will emit a - warning if a protocol is found and is deprecated. */ - + warning if a protocol is found and is deprecated. If + 'definition_required', then warn if the protocol is found but is + not defined (ie, if we only saw a forward-declaration of the + protocol (as in "@protocol NSObject;") not a real definition with + the list of methods). */ static tree -lookup_and_install_protocols (tree protocols) +lookup_and_install_protocols (tree protocols, bool definition_required) { tree proto; tree return_value = NULL_TREE; @@ -2960,7 +2993,8 @@ lookup_and_install_protocols (tree protocols) for (proto = protocols; proto; proto = TREE_CHAIN (proto)) { tree ident = TREE_VALUE (proto); - tree p = lookup_protocol (ident, /* warn_if_deprecated */ true); + tree p = lookup_protocol (ident, /* warn_if_deprecated */ true, + definition_required); if (p) return_value = chainon (return_value, @@ -5126,7 +5160,7 @@ next_sjlj_build_enter_and_setjmp (void) t = build_fold_addr_expr_loc (input_location, t); #ifdef OBJCPLUS /* Convert _setjmp argument to type that is expected. */ - if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))) + if (prototype_p (TREE_TYPE (objc_setjmp_decl))) t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t); else t = convert (ptr_type_node, t); @@ -5604,28 +5638,59 @@ objc_build_throw_stmt (location_t loc, tree throw_expr) } tree -objc_build_synchronized (location_t start_locus, tree mutex, tree body) +objc_build_synchronized (location_t start_locus, tree object_expr, tree body) { - tree args, call; + /* object_expr should never be NULL; but in case it is, convert it to + error_mark_node. */ + if (object_expr == NULL) + object_expr = error_mark_node; - /* First lock the mutex. */ - mutex = save_expr (mutex); - args = tree_cons (NULL, mutex, NULL); - call = build_function_call (input_location, - objc_sync_enter_decl, args); - SET_EXPR_LOCATION (call, start_locus); - add_stmt (call); - - /* Build the mutex unlock. */ - args = tree_cons (NULL, mutex, NULL); - call = build_function_call (input_location, - objc_sync_exit_decl, args); - SET_EXPR_LOCATION (call, input_location); - - /* Put the that and the body in a TRY_FINALLY. */ - objc_begin_try_stmt (start_locus, body); - objc_build_finally_clause (input_location, call); - return objc_finish_try_stmt (); + /* Validate object_expr. If not valid, set it to error_mark_node. */ + if (object_expr != error_mark_node) + { + if (!objc_type_valid_for_messaging (TREE_TYPE (object_expr), true)) + { + error_at (start_locus, "%<@synchronized%> argument is not an object"); + object_expr = error_mark_node; + } + } + + if (object_expr == error_mark_node) + { + /* If we found an error, we simply ignore the '@synchronized'. + Compile the body so we can keep going with minimal + casualties. */ + return add_stmt (body); + } + else + { + tree call; + tree args; + + /* objc_sync_enter (object_expr); */ + object_expr = save_expr (object_expr); + args = tree_cons (NULL, object_expr, NULL); + call = build_function_call (input_location, + objc_sync_enter_decl, args); + SET_EXPR_LOCATION (call, start_locus); + add_stmt (call); + + /* Build "objc_sync_exit (object_expr);" but do not add it yet; + it goes inside the @finalize() clause. */ + args = tree_cons (NULL, object_expr, NULL); + call = build_function_call (input_location, + objc_sync_exit_decl, args); + SET_EXPR_LOCATION (call, input_location); + + /* @try { body; } */ + objc_begin_try_stmt (start_locus, body); + + /* @finally { objc_sync_exit (object_expr); } */ + objc_build_finally_clause (input_location, call); + + /* End of try statement. */ + return objc_finish_try_stmt (); + } } @@ -5965,8 +6030,9 @@ encode_method_prototype (tree method_decl) /* If a type size is not known, bail out. */ if (sz < 0) { - error ("type %q+D does not have a known size", - type); + error_at (DECL_SOURCE_LOCATION (method_decl), + "type %qT does not have a known size", + type); /* Pretend that the encoding succeeded; the compilation will fail nevertheless. */ goto finish_encoding; @@ -8005,7 +8071,7 @@ objc_build_message_expr (tree mess) method_params); #endif - return objc_finish_message_expr (receiver, sel_name, method_params); + return objc_finish_message_expr (receiver, sel_name, method_params, NULL); } /* Look up method SEL_NAME that would be suitable for receiver @@ -8034,10 +8100,20 @@ lookup_method_in_hash_lists (tree sel_name, int is_class) /* The 'objc_finish_message_expr' routine is called from within 'objc_build_message_expr' for non-template functions. In the case of C++ template functions, it is called from 'build_expr_from_tree' - (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */ - + (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. + + If the DEPRECATED_METHOD_PROTOTYPE argument is NULL, then we warn + if the method being used is deprecated. If it is not NULL, instead + of deprecating, we set *DEPRECATED_METHOD_PROTOTYPE to the method + prototype that was used and is deprecated. This is useful for + getter calls that are always generated when compiling dot-syntax + expressions, even if they may not be used. In that case, we don't + want the warning immediately; we produce it (if needed) at gimplify + stage when we are sure that the deprecated getter is being + used. */ tree -objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) +objc_finish_message_expr (tree receiver, tree sel_name, tree method_params, + tree *deprecated_method_prototype) { tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype; tree selector, retval, class_tree; @@ -8254,7 +8330,12 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) is often used precisely to turn off warnings associated with the object being of a particular class. */ if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE) - warn_deprecated_use (method_prototype, NULL_TREE); + { + if (deprecated_method_prototype) + *deprecated_method_prototype = method_prototype; + else + warn_deprecated_use (method_prototype, NULL_TREE); + } } @@ -8399,7 +8480,8 @@ tree objc_build_protocol_expr (tree protoname) { tree expr; - tree p = lookup_protocol (protoname, /* warn if deprecated */ true); + tree p = lookup_protocol (protoname, /* warn if deprecated */ true, + /* definition_required */ false); if (!p) { @@ -8816,22 +8898,69 @@ add_method_to_hash_list (hash *hash_list, tree method) static tree objc_add_method (tree klass, tree method, int is_class, bool is_optional) { - tree mth; + tree existing_method = NULL_TREE; + + /* The first thing we do is look up the method in the list of + methods already defined in the interface (or implementation). */ + if (is_class) + existing_method = lookup_method (CLASS_CLS_METHODS (klass), method); + else + existing_method = lookup_method (CLASS_NST_METHODS (klass), method); + + /* In the case of protocols, we have a second list of methods to + consider, the list of optional ones. */ + if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE) + { + /* @required methods are added to the protocol's normal list. + @optional methods are added to the protocol's OPTIONAL lists. + Note that adding the methods to the optional lists disables + checking that the methods are implemented by classes + implementing the protocol, since these checks only use the + CLASS_CLS_METHODS and CLASS_NST_METHODS. */ + + /* First of all, if the method to add is @optional, and we found + it already existing as @required, emit an error. */ + if (is_optional && existing_method) + { + error ("method %<%c%E%> declared %<@optional%> and %<@required%> at the same time", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + inform (DECL_SOURCE_LOCATION (existing_method), + "previous declaration of %<%c%E%> as %<@required%>", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + } + + /* Now check the list of @optional methods if we didn't find the + method in the @required list. */ + if (!existing_method) + { + if (is_class) + existing_method = lookup_method (PROTOCOL_OPTIONAL_CLS_METHODS (klass), method); + else + existing_method = lookup_method (PROTOCOL_OPTIONAL_NST_METHODS (klass), method); + + if (!is_optional && existing_method) + { + error ("method %<%c%E%> declared %<@optional%> and %<@required%> at the same time", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + inform (DECL_SOURCE_LOCATION (existing_method), + "previous declaration of %<%c%E%> as %<@optional%>", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + } + } + } - /* @optional methods are added to protocol's OPTIONAL list. Note - that this disables checking that the methods are implemented by - classes implementing the protocol, since these checks only use - the CLASS_CLS_METHODS and CLASS_NST_METHODS. */ - if (is_optional) + /* If the method didn't exist already, add it. */ + if (!existing_method) { - gcc_assert (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE); - if (!(mth = lookup_method (is_class - ? PROTOCOL_OPTIONAL_CLS_METHODS (klass) - : PROTOCOL_OPTIONAL_NST_METHODS (klass), - method))) + if (is_optional) { if (is_class) { + /* Put the method on the list in reverse order. */ TREE_CHAIN (method) = PROTOCOL_OPTIONAL_CLS_METHODS (klass); PROTOCOL_OPTIONAL_CLS_METHODS (klass) = method; } @@ -8841,36 +8970,50 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional) PROTOCOL_OPTIONAL_NST_METHODS (klass) = method; } } - } - else if (!(mth = lookup_method (is_class - ? CLASS_CLS_METHODS (klass) - : CLASS_NST_METHODS (klass), method))) - { - /* put method on list in reverse order */ - if (is_class) - { - DECL_CHAIN (method) = CLASS_CLS_METHODS (klass); - CLASS_CLS_METHODS (klass) = method; - } else { - DECL_CHAIN (method) = CLASS_NST_METHODS (klass); - CLASS_NST_METHODS (klass) = method; + if (is_class) + { + DECL_CHAIN (method) = CLASS_CLS_METHODS (klass); + CLASS_CLS_METHODS (klass) = method; + } + else + { + DECL_CHAIN (method) = CLASS_NST_METHODS (klass); + CLASS_NST_METHODS (klass) = method; + } } } else { - /* When processing an @interface for a class or category, give hard - errors on methods with identical selectors but differing argument - and/or return types. We do not do this for @implementations, because - C/C++ will do it for us (i.e., there will be duplicate function - definition errors). */ + /* The method was already defined. Check that the types match + for an @interface for a class or category, or for a + @protocol. Give hard errors on methods with identical + selectors but differing argument and/or return types. We do + not do this for @implementations, because C/C++ will do it + for us (i.e., there will be duplicate function definition + errors). */ if ((TREE_CODE (klass) == CLASS_INTERFACE_TYPE - || TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE) - && !comp_proto_with_proto (method, mth, 1)) - error ("duplicate declaration of method %<%c%E%>", - is_class ? '+' : '-', - METHOD_SEL_NAME (mth)); + || TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE + /* Starting with GCC 4.6, we emit the same error for + protocols too. The situation is identical to + @interfaces as there is no possible meaningful reason + for defining the same method with different signatures + in the very same @protocol. If that was allowed, + whenever the protocol is used (both at compile and run + time) there wouldn't be any meaningful way to decide + which of the two method signatures should be used. */ + || TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE) + && !comp_proto_with_proto (method, existing_method, 1)) + { + error ("duplicate declaration of method %<%c%E%> with conflicting types", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + inform (DECL_SOURCE_LOCATION (existing_method), + "previous declaration of %<%c%E%>", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (existing_method)); + } } if (is_class) @@ -9626,7 +9769,7 @@ start_class (enum tree_code code, tree class_name, tree super_name, if (protocol_list) CLASS_PROTOCOL_LIST (klass) - = lookup_and_install_protocols (protocol_list); + = lookup_and_install_protocols (protocol_list, /* definition_required */ true); /* Determine if 'deprecated', the only attribute we recognize for classes, was used. Ignore all other attributes for now, @@ -9640,6 +9783,8 @@ start_class (enum tree_code code, tree class_name, tree super_name, if (is_attribute_p ("deprecated", name)) TREE_DEPRECATED (klass) = 1; + else + warning (OPT_Wattributes, "%qE attribute directive ignored", name); } TYPE_ATTRIBUTES (klass) = attributes; } @@ -9677,7 +9822,9 @@ start_class (enum tree_code code, tree class_name, tree super_name, list. */ CLASS_PROTOCOL_LIST (klass) = chainon (CLASS_PROTOCOL_LIST (klass), - lookup_and_install_protocols (protocol_list)); + lookup_and_install_protocols + (protocol_list, + /* definition_required */ true)); } } else @@ -9686,7 +9833,8 @@ start_class (enum tree_code code, tree class_name, tree super_name, if (protocol_list) CLASS_PROTOCOL_LIST (klass) - = lookup_and_install_protocols (protocol_list); + = lookup_and_install_protocols + (protocol_list, /* definition_required */ true); } } } @@ -10715,6 +10863,7 @@ finish_class (tree klass) objc_add_method (objc_interface_context, getter_decl, false, true); else objc_add_method (objc_interface_context, getter_decl, false, false); + TREE_DEPRECATED (getter_decl) = TREE_DEPRECATED (x); METHOD_PROPERTY_CONTEXT (getter_decl) = x; } @@ -10758,6 +10907,7 @@ finish_class (tree klass) objc_add_method (objc_interface_context, setter_decl, false, true); else objc_add_method (objc_interface_context, setter_decl, false, false); + TREE_DEPRECATED (setter_decl) = TREE_DEPRECATED (x); METHOD_PROPERTY_CONTEXT (setter_decl) = x; } } @@ -10779,11 +10929,32 @@ add_protocol (tree protocol) return protocol_chain; } -/* Looks up a protocol. If 'warn_if_deprecated' is true, a warning is - emitted if the protocol is deprecated. */ +/* Check that a protocol is defined, and, recursively, that all + protocols that this protocol conforms to are defined too. */ +static void +check_that_protocol_is_defined (tree protocol) +{ + if (!PROTOCOL_DEFINED (protocol)) + warning (0, "definition of protocol %qE not found", + PROTOCOL_NAME (protocol)); + + /* If the protocol itself conforms to other protocols, check them + too, recursively. */ + if (PROTOCOL_LIST (protocol)) + { + tree p; + for (p = PROTOCOL_LIST (protocol); p; p = TREE_CHAIN (p)) + check_that_protocol_is_defined (TREE_VALUE (p)); + } +} + +/* Looks up a protocol. If 'warn_if_deprecated' is true, a warning is + emitted if the protocol is deprecated. If 'definition_required' is + true, a warning is emitted if a full @protocol definition has not + been seen. */ static tree -lookup_protocol (tree ident, bool warn_if_deprecated) +lookup_protocol (tree ident, bool warn_if_deprecated, bool definition_required) { tree chain; @@ -10799,6 +10970,9 @@ lookup_protocol (tree ident, bool warn_if_deprecated) PROTOCOL_NAME (chain)); } + if (definition_required) + check_that_protocol_is_defined (chain); + return chain; } @@ -10831,6 +11005,8 @@ objc_declare_protocols (tree names, tree attributes) if (is_attribute_p ("deprecated", name)) deprecated = true; + else + warning (OPT_Wattributes, "%qE attribute directive ignored", name); } } @@ -10838,7 +11014,8 @@ objc_declare_protocols (tree names, tree attributes) { tree name = TREE_VALUE (list); - if (lookup_protocol (name, /* warn if deprecated */ false) == NULL_TREE) + if (lookup_protocol (name, /* warn if deprecated */ false, + /* definition_required */ false) == NULL_TREE) { tree protocol = make_node (PROTOCOL_INTERFACE_TYPE); @@ -10883,10 +11060,13 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes) if (is_attribute_p ("deprecated", name)) deprecated = true; + else + warning (OPT_Wattributes, "%qE attribute directive ignored", name); } } - protocol = lookup_protocol (name, /* warn_if_deprecated */ false); + protocol = lookup_protocol (name, /* warn_if_deprecated */ false, + /* definition_required */ false); if (!protocol) { @@ -10894,7 +11074,7 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes) TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS); PROTOCOL_NAME (protocol) = name; - PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list); + PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list, /* definition_required */ false); add_protocol (protocol); PROTOCOL_DEFINED (protocol) = 1; PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; @@ -10904,7 +11084,7 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes) else if (! PROTOCOL_DEFINED (protocol)) { PROTOCOL_DEFINED (protocol) = 1; - PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list); + PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list, /* definition_required */ false); check_protocol_recursively (protocol, list); } @@ -11763,9 +11943,8 @@ start_method_def (tree method) really_start_method (objc_method_context, parm_info); } -/* Return 1 if TYPE1 is equivalent to TYPE2 - for purposes of method overloading. */ - +/* Return 1 if TYPE1 is equivalent to TYPE2 for purposes of method + overloading. */ static int objc_types_are_equivalent (tree type1, tree type2) { @@ -11779,6 +11958,7 @@ objc_types_are_equivalent (tree type1, tree type2) if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2)) return 0; + /* Compare the protocol lists. */ type1 = (TYPE_HAS_OBJC_INFO (type1) ? TYPE_OBJC_PROTOCOL_LIST (type1) : NULL_TREE); @@ -11786,14 +11966,34 @@ objc_types_are_equivalent (tree type1, tree type2) ? TYPE_OBJC_PROTOCOL_LIST (type2) : NULL_TREE); - if (list_length (type1) == list_length (type2)) + /* If there are no protocols (most common case), the types are + identical. */ + if (type1 == NULL_TREE && type2 == NULL_TREE) + return 1; + + /* If one has protocols, and the other one hasn't, they are not + identical. */ + if ((type1 == NULL_TREE && type2 != NULL_TREE) + || (type1 != NULL_TREE && type2 == NULL_TREE)) + return 0; + else { - for (; type2; type2 = TREE_CHAIN (type2)) - if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2))) + /* Else, both have protocols, and we need to do the full + comparison. It is possible that either type1 or type2 + contain some duplicate protocols in the list, so we can't + even just compare list_length as a first check. */ + tree t; + + for (t = type2; t; t = TREE_CHAIN (t)) + if (!lookup_protocol_in_reflist (type1, TREE_VALUE (t))) + return 0; + + for (t = type1; t; t = TREE_CHAIN (t)) + if (!lookup_protocol_in_reflist (type2, TREE_VALUE (t))) return 0; + return 1; } - return 0; } /* Return 1 if TYPE1 has the same size and alignment as TYPE2. */ @@ -13082,6 +13282,14 @@ objc_gimplify_property_ref (tree *expr_p) return; } + if (PROPERTY_REF_DEPRECATED_GETTER (*expr_p)) + { + /* PROPERTY_REF_DEPRECATED_GETTER contains the method prototype + that is deprecated. */ + warn_deprecated_use (PROPERTY_REF_DEPRECATED_GETTER (*expr_p), + NULL_TREE); + } + call_exp = getter; #ifdef OBJCPLUS /* In C++, a getter which returns an aggregate value results in a @@ -13475,7 +13683,7 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll tree_cons /* __objc_foreach_items */ (NULL_TREE, objc_foreach_items_decl, tree_cons /* 16 */ - (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE)))); + (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))), NULL); #else /* In C, we need to decay the __objc_foreach_items array that we are passing. */ { @@ -13488,7 +13696,7 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll tree_cons /* __objc_foreach_items */ (NULL_TREE, default_function_array_conversion (location, array).value, tree_cons /* 16 */ - (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE)))); + (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))), NULL); } #endif t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_batchsize_decl, @@ -13649,7 +13857,7 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll tree_cons /* __objc_foreach_items */ (NULL_TREE, objc_foreach_items_decl, tree_cons /* 16 */ - (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE)))); + (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))), NULL); #else /* In C, we need to decay the __objc_foreach_items array that we are passing. */ { @@ -13662,7 +13870,7 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll tree_cons /* __objc_foreach_items */ (NULL_TREE, default_function_array_conversion (location, array).value, tree_cons /* 16 */ - (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE)))); + (NULL_TREE, build_int_cst (NULL_TREE, 16), NULL_TREE))), NULL); } #endif t = build2 (MODIFY_EXPR, void_type_node, objc_foreach_batchsize_decl, diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index 7e8e4184880..4d023e87cd3 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -144,6 +144,11 @@ typedef enum objc_property_assign_semantics { use it. */ #define PROPERTY_REF_GETTER_CALL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 2) +/* PROPERTY_REF_DEPRECATED_GETTER is normally set to NULL_TREE. If + the property getter is deprecated, it is set to the method + prototype for it, which is used to generate the deprecation warning + when the getter is used. */ +#define PROPERTY_REF_DEPRECATED_GETTER(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 3) /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE, diff --git a/gcc/objc/objc-tree.def b/gcc/objc/objc-tree.def index e33fc78db29..f72f2332dea 100644 --- a/gcc/objc/objc-tree.def +++ b/gcc/objc/objc-tree.def @@ -46,7 +46,10 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1) representing the expression), and Operand 1 is the property (the PROPERTY_DECL). Operand 2 is the 'getter' call, ready to be used; we pregenerate it because it is hard to generate it properly later - on. A PROPERTY_REF tree needs to be transformed into 'setter' and + on. Operand 3 records whether using the 'getter' call should + generate a deprecation warning or not. + + A PROPERTY_REF tree needs to be transformed into 'setter' and 'getter' calls at some point; at the moment this happens in two places: @@ -58,13 +61,14 @@ DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1) gimplification; at that point, we convert each PROPERTY_REF into a 'getter' call during ObjC/ObjC++ gimplify. At that point, it is quite hard to build a 'getter' call, but we have already built - it and we just need to swap Operand 2 in. + it and we just need to swap Operand 2 in, and emit the deprecation + warnings from Operand 3 if needed. Please note that when the Objective-C 2.0 "dot-syntax" 'object.component' is encountered, where 'component' is not a property but there are valid setter/getter methods for it, an artificial PROPERTY_DECL is generated and used in the PROPERTY_REF. */ -DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 3) +DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 4) /* Local variables: |