This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[objc-improvements] Message passing breaks when receiver type doesn't match promoted sender type (Was: How is it looking?)
- From: Alexander Malmberg <alexander at malmberg dot org>
- To: Ziemowit Laski <zlaski at apple dot com>
- Cc: discuss-gnustep at gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 Aug 2003 01:15:44 +0200
- Subject: [objc-improvements] Message passing breaks when receiver type doesn't match promoted sender type (Was: How is it looking?)
- References: <EDC639DE-CDC4-11D7-A247-000393673036@apple.com>
Ziemowit Laski wrote:
[snip]
> could any of you brave GNUStep folk take the branch for yet another
> spin, and let me know if there are any remaining problems?
GNUstep core/ built, but there were odd failures in the test suite and
apps. Investigation shows that this change:
"""
2003-08-08 23:27 zlaski
* objc-act.c: Fix build_objc_method_call() so that it does not
produce warnings about mismatched argument types. This was
subtly
broken under both GNU and NeXT regimes. While I was at it, I
refactored some of the commonalities. Remove stray APPLE LOCAL
markers.
"""
breaks message passing in many cases. The relevant part is, quoting the
new comment:
""This is because the sender signature may in fact be incorrect,
especially if the type of the receiver is not known. The same applies to
sender's arguments (other than self and _cmd), so just cast them as
'...'.""
By casting the function to id (*)(id,SEL,...), arguments are always
passed as the promoted type of the argument expression, which might not
match what the method expects.
Eg. given:
-(void) anInt: (int)foo;
and
[receiver anInt: 1.0];
the sender will push a double on the stack, while the method expects an
int. Size mismatches between arguments (as in this case; 4 byte int vs.
8 byte double) also means that subsequent arguments will be messed up.
The problem does not appear to be specific to the GNU runtime.
I've attached a patch that fixes this by reverting to the old behavior
when method_prototype is non-null. This fixes my simple tests for it.
I'm waiting for GNUstep to finish (re)compiling to see if there are any
problems left. When method_prototype is null, it uses the new code since
it seems equivalent to the old code wrt arguments.
I've also attached a simple test for one instance of the problem.
- Alexander Malmberg
Index: objc-act.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.179.2.6
diff -u -r1.179.2.6 objc-act.c
--- objc-act.c 12 Aug 2003 19:02:39 -0000 1.179.2.6
+++ objc-act.c 14 Aug 2003 22:51:33 -0000
@@ -5976,19 +5976,37 @@
tree ret_type = (method_prototype
? groktypename (TREE_TYPE (method_prototype))
: id_type);
- tree sender_cast = build_pointer_type
- (build_function_type
- ((ret_type == void_type_node
- ? id_type
+
+ tree sender_cast;
+
+ if (method_prototype)
+ {
+
+ sender_cast = build_pointer_type
+ (build_function_type
+ ((ret_type == void_type_node
+ ? id_type
+ : ret_type),
+ get_arg_type_list (method_prototype,
+ METHOD_REF,
+ super_flag)));
+ }
+ else
+ {
+ sender_cast = build_pointer_type
+ (build_function_type
+ ((ret_type == void_type_node
+ ? id_type
: ret_type),
tree_cons (NULL_TREE,
(super_flag && flag_next_runtime
? super_type
: id_type),
- tree_cons (NULL_TREE,
+ tree_cons (NULL_TREE,
selector_type,
NULL_TREE))));
-
+ }
+
lookup_object = build_c_cast (rcv_p, lookup_object);
if (flag_next_runtime)
#include <objc/Object.h>
@interface Foo : Object
{
}
-(void) brokenType: (float)x anInt: (int)y;
@end
@implementation Foo
-(void) brokenType: (float)x anInt: (int)y
{
printf("x=%g y=%i\n",x,y);
}
@end
int main(int argc,char **argv)
{
Foo *foo=[Foo new];
[foo brokenType: 5.2 anInt: 1234.0];
return 0;
}