aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-12-30 18:26:56 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-12-30 18:26:56 +0000
commit223706ad626f262e18f9ae7786cbc88509b088a5 (patch)
tree43a6e7abb3563b355e1079efa3f54b7b92198ea8 /gcc/objc
parentae480e548c664521c9c79bfc586b8a2fc135ffde (diff)
downloadgcc-223706ad626f262e18f9ae7786cbc88509b088a5.zip
gcc-223706ad626f262e18f9ae7786cbc88509b088a5.tar.gz
gcc-223706ad626f262e18f9ae7786cbc88509b088a5.tar.bz2
In gcc/objc/: 2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 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. When In gcc/testsuite/: 2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/class-extension-3.m: Updated. * objc.dg/method-1.m: Updated. * objc.dg/method-conflict-1.m: New. * objc.dg/method-conflict-2.m: New. * obj-c++.dg/class-extension-3.mm: Updated. * obj-c++.dg/method-8.mm: Updated. * obj-c++.dg/method-conflict-1.mm: New. * obj-c++.dg/method-conflict-2.mm: New. From-SVN: r168350
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/ChangeLog13
-rw-r--r--gcc/objc/objc-act.c129
2 files changed, 107 insertions, 35 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index b717a94..43ef65d 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,4 +1,15 @@
-2010-12-30 Nicola Pero <nicola@nicola.brainstorm.co.uk>
+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. When
+
+2010-12-30 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (start_class): Warn when a class attribute is
ignored.
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index a0a7a09..ec7fea5 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -8898,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;
- /* @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)
+ /* 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)
{
- 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)))
+ /* @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));
+ }
+ }
+ }
+
+ /* If the method didn't exist already, add it. */
+ if (!existing_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;
}
@@ -8923,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)