summaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-03 12:17:59 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-03 12:17:59 +0000
commit73556f5f6c5d835df3baa9979de74da7bd85cd05 (patch)
treeac76e75c45976914468f05d9d01c6dab44ff831c /gcc/objc
parent009b254c18c50184aadbc41673222104cec47838 (diff)
downloadgcc-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/ChangeLog109
-rw-r--r--gcc/objc/config-lang.in2
-rw-r--r--gcc/objc/objc-act.c428
-rw-r--r--gcc/objc/objc-act.h5
-rw-r--r--gcc/objc/objc-tree.def10
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: