Commit 223706ad by Nicola Pero Committed by Nicola Pero

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
parent ae480e54
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 * objc-act.c (start_class): Warn when a class attribute is
ignored. ignored.
......
...@@ -8898,22 +8898,69 @@ add_method_to_hash_list (hash *hash_list, tree method) ...@@ -8898,22 +8898,69 @@ add_method_to_hash_list (hash *hash_list, tree method)
static tree static tree
objc_add_method (tree klass, tree method, int is_class, bool is_optional) 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 /* The first thing we do is look up the method in the list of
that this disables checking that the methods are implemented by methods already defined in the interface (or implementation). */
classes implementing the protocol, since these checks only use if (is_class)
the CLASS_CLS_METHODS and CLASS_NST_METHODS. */ existing_method = lookup_method (CLASS_CLS_METHODS (klass), method);
if (is_optional) 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); /* @required methods are added to the protocol's normal list.
if (!(mth = lookup_method (is_class @optional methods are added to the protocol's OPTIONAL lists.
? PROTOCOL_OPTIONAL_CLS_METHODS (klass) Note that adding the methods to the optional lists disables
: PROTOCOL_OPTIONAL_NST_METHODS (klass), checking that the methods are implemented by classes
method))) 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) 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); TREE_CHAIN (method) = PROTOCOL_OPTIONAL_CLS_METHODS (klass);
PROTOCOL_OPTIONAL_CLS_METHODS (klass) = method; PROTOCOL_OPTIONAL_CLS_METHODS (klass) = method;
} }
...@@ -8923,12 +8970,8 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional) ...@@ -8923,12 +8970,8 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
PROTOCOL_OPTIONAL_NST_METHODS (klass) = method; PROTOCOL_OPTIONAL_NST_METHODS (klass) = method;
} }
} }
} else
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) if (is_class)
{ {
DECL_CHAIN (method) = CLASS_CLS_METHODS (klass); DECL_CHAIN (method) = CLASS_CLS_METHODS (klass);
...@@ -8940,19 +8983,37 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional) ...@@ -8940,19 +8983,37 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
CLASS_NST_METHODS (klass) = method; CLASS_NST_METHODS (klass) = method;
} }
} }
}
else else
{ {
/* When processing an @interface for a class or category, give hard /* The method was already defined. Check that the types match
errors on methods with identical selectors but differing argument for an @interface for a class or category, or for a
and/or return types. We do not do this for @implementations, because @protocol. Give hard errors on methods with identical
C/C++ will do it for us (i.e., there will be duplicate function selectors but differing argument and/or return types. We do
definition errors). */ 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 if ((TREE_CODE (klass) == CLASS_INTERFACE_TYPE
|| TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE) || TREE_CODE (klass) == CATEGORY_INTERFACE_TYPE
&& !comp_proto_with_proto (method, mth, 1)) /* Starting with GCC 4.6, we emit the same error for
error ("duplicate declaration of method %<%c%E%>", protocols too. The situation is identical to
is_class ? '+' : '-', @interfaces as there is no possible meaningful reason
METHOD_SEL_NAME (mth)); 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) if (is_class)
......
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.
2010-12-30 Joseph Myers <joseph@codesourcery.com> 2010-12-30 Joseph Myers <joseph@codesourcery.com>
PR c/46889 PR c/46889
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
Class isa; Class isa;
int count; int count;
} }
- (int) test; - (int) test; /* { dg-warning "previous declaration" } */
@property int count; /* { dg-warning "originally specified here" } */ @property int count; /* { dg-warning "originally specified here" } */
@end @end
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
/* { dg-do compile } */ /* { dg-do compile } */
@interface class1 @interface class1
- (int) meth1; - (int) meth1; /* { dg-error "previous declaration" } */
- (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */ - (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */
@end @end
@interface class2 @interface class2
+ (void) meth1; + (void) meth1; /* { dg-error "previous declaration" } */
+ (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */ + (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */
@end @end
......
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that you can not declare two methods, in the same protocol,
with the same name but conflicting method signatures. */
@protocol MyProtocol
+ (int) method1: (int)x; /* { dg-error "previous declaration" } */
+ (float) method1: (int)x; /* { dg-error "duplicate declaration of method .\\+method1." } */
- (int) method2: (int)x; /* { dg-error "previous declaration" } */
- (int) method2: (float)x; /* { dg-error "duplicate declaration of method .\\-method2." } */
@optional
+ (int *) method3: (int)x; /* { dg-error "previous declaration" } */
+ (int *) method3: (int **)x; /* { dg-error "duplicate declaration of method .\\+method3." } */
- (id) method4: (id)x; /* { dg-error "previous declaration" } */
- (void) method4: (id)x; /* { dg-error "duplicate declaration of method .\\-method4." } */
@end
/* We don't test conflicting types between @required and @optional
methods, as that is tested in method-conflict-2. */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that you can not declare two methods, in the same protocol,
with the same name and method signature, but one as @required and
once as @optional. */
/* First, @required conflicting with @optional. */
@protocol MyProtocol
@optional
+ (void) method1: (id)x; /* { dg-error "previous declaration" } */
- (id) method2: (long)x; /* { dg-error "previous declaration" } */
@required
+ (void) method1: (id)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
- (id) method2: (long)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
@end
/* Second, @optional conflicting with @required. */
@protocol MyProtocol2
@required
+ (void) method3: (Class)x; /* { dg-error "previous declaration" } */
- (id *) method4: (long)x; /* { dg-error "previous declaration" } */
@optional
+ (void) method3: (Class)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
- (id *) method4: (long)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
@end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
Class isa; Class isa;
int count; int count;
} }
- (int) test; - (int) test; /* { dg-message "previous declaration" } */
@property int count; /* { dg-message "originally specified here" } */ @property int count; /* { dg-message "originally specified here" } */
@end @end
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
/* { dg-do compile } */ /* { dg-do compile } */
@interface class1 @interface class1
- (int) meth1; - (int) meth1; /* { dg-message "previous declaration" } */
- (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */ - (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */
@end @end
@interface class2 @interface class2
+ (void) meth1; + (void) meth1; /* { dg-message "previous declaration" } */
+ (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */ + (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */
@end @end
......
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that you can not declare two methods, in the same protocol,
with the same name but conflicting method signatures. */
@protocol MyProtocol
+ (int) method1: (int)x; /* { dg-message "previous declaration" } */
+ (float) method1: (int)x; /* { dg-error "duplicate declaration of method .\\+method1." } */
- (int) method2: (int)x; /* { dg-message "previous declaration" } */
- (int) method2: (float)x; /* { dg-error "duplicate declaration of method .\\-method2." } */
@optional
+ (int *) method3: (int)x; /* { dg-message "previous declaration" } */
+ (int *) method3: (int **)x; /* { dg-error "duplicate declaration of method .\\+method3." } */
- (id) method4: (id)x; /* { dg-message "previous declaration" } */
- (void) method4: (id)x; /* { dg-error "duplicate declaration of method .\\-method4." } */
@end
/* We don't test conflicting types between @required and @optional
methods, as that is tested in method-conflict-2. */
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */
/* { dg-do compile } */
#include <objc/objc.h>
/* Test that you can not declare two methods, in the same protocol,
with the same name and method signature, but one as @required and
once as @optional. */
/* First, @required conflicting with @optional. */
@protocol MyProtocol
@optional
+ (void) method1: (id)x; /* { dg-message "previous declaration" } */
- (id) method2: (long)x; /* { dg-message "previous declaration" } */
@required
+ (void) method1: (id)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
- (id) method2: (long)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
@end
/* Second, @optional conflicting with @required. */
@protocol MyProtocol2
@required
+ (void) method3: (Class)x; /* { dg-message "previous declaration" } */
- (id *) method4: (long)x; /* { dg-message "previous declaration" } */
@optional
+ (void) method3: (Class)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
- (id *) method4: (long)x; /* { dg-error "declared .@optional. and .@required. at the same time" } */
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment