diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 38aed72d866..1f83435d33e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2004-01-17 Ziemowit Laski + + * objc/objc-act.c (build_objc_method_call): Use target + hooks instead of macros to determine if ..._stret + dispatchers should be used (NeXT runtime only). + 2004-01-17 Roger Sayle * builtins.c (expand_builtin_expect_jump): Fix mistake in my diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index c552bada9de..c1352922c7e 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -5890,21 +5890,18 @@ build_objc_method_call (int super_flag, tree method_prototype, if (flag_next_runtime) { -#ifdef STRUCT_VALUE /* If we are returning a struct in memory, and the address of that memory location is passed as a hidden first argument, then change which messenger entry point this expr will call. NB: Note that sender_cast remains unchanged (it already has a struct return type). */ - if ((TREE_CODE (ret_type) == RECORD_TYPE - || TREE_CODE (ret_type) == UNION_TYPE) -#if defined (DEFAULT_PCC_STRUCT_RETURN) && DEFAULT_PCC_STRUCT_RETURN == 0 - && RETURN_IN_MEMORY (ret_type) -#endif - && STRUCT_VALUE == 0) + if (!targetm.calls.struct_value_rtx (0, 0) + && (TREE_CODE (ret_type) == RECORD_TYPE + || TREE_CODE (ret_type) == UNION_TYPE) + && targetm.calls.return_in_memory (ret_type, 0)) sender = (super_flag ? umsg_super_stret_decl : flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl); -#endif + method_params = tree_cons (NULL_TREE, lookup_object, tree_cons (NULL_TREE, selector, method_params)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ffe63786ce1..1847836d79e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-01-17 Ziemowit Laski + + * objc.dg/stret-1.m: New. + * objc.dg/stret-2.m: New. + 2004-01-17 Andrew Pinski PR c++/11895 diff --git a/gcc/testsuite/objc.dg/stret-1.m b/gcc/testsuite/objc.dg/stret-1.m new file mode 100644 index 00000000000..427b5574d7e --- /dev/null +++ b/gcc/testsuite/objc.dg/stret-1.m @@ -0,0 +1,62 @@ +/* Test for handling of struct-returning methods. */ +/* Contributed by Ziemowit Laski . */ +/* { dg-do run } */ + +#include + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +struct astruct { + float a, b; +} glob = { 1.0, 2.0 }; + +struct bstruct { + float a, b, c, d, e, f; +} globb = { 1, 2, 3, 4, 5, 6 }; + +@interface foo : Object +- (struct astruct) stret; +- (struct bstruct) stretb; +@end + +@implementation foo : Object +- (struct astruct) stret { return glob; } +- (struct bstruct) stretb { return globb; } +@end + +@interface bar: foo +- (struct astruct) stret; +- (struct bstruct) stretb; +@end + +@implementation bar +- (struct astruct) stret { struct astruct a = [super stret]; a.b = 77; return a; } +- (struct bstruct) stretb { struct bstruct b = [super stretb]; b.e = 99; return b; } +@end + +int main(void) +{ + foo *obj = [foo new]; + bar *obj2 = [bar new]; + struct astruct loc, loc2; + struct bstruct locb, locb2; + + loc = [obj stret]; + CHECK_IF(loc.a == 1.0 && loc.b == 2.0); + + locb = [obj stretb]; + CHECK_IF(locb.f == 6 && locb.c == 3); + CHECK_IF(locb.e == 5 && locb.b == 2); + CHECK_IF(locb.d == 4 && locb.a == 1); + + loc2 = [obj2 stret]; + CHECK_IF(loc2.a == 1.0 && loc2.b == 77); + + locb2 = [obj2 stretb]; + CHECK_IF(locb2.f == 6 && locb2.c == 3); + CHECK_IF(locb2.e == 99 && locb2.b == 2); + CHECK_IF(locb2.d == 4 && locb2.a == 1); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/stret-2.m b/gcc/testsuite/objc.dg/stret-2.m new file mode 100644 index 00000000000..dd9a2e8e5b2 --- /dev/null +++ b/gcc/testsuite/objc.dg/stret-2.m @@ -0,0 +1,46 @@ +/* Test for handling of struct-returning methods + for the Mac OS X ("NeXT") runtime (which uses specialized entry + points). */ +/* Contributed by Ziemowit Laski . */ +/* { dg-do compile { target *-*-darwin* } } */ + +#include + +struct astruct { + float a, b; +} glob = { 1.0, 2.0 }; + +struct bstruct { + float a, b, c, d, e, f; +} globb = { 1, 2, 3, 4, 5, 6 }; + +@interface foo : Object +- (struct astruct) stret; +- (struct bstruct) stretb; +@end + +@implementation foo : Object +- (struct astruct) stret { return glob; } +- (struct bstruct) stretb { return globb; } +@end + +@interface bar: foo +- (struct astruct) stret; +- (struct bstruct) stretb; +@end + +@implementation bar +- (struct astruct) stret { return [super stret]; } +- (struct bstruct) stretb { return [super stretb]; } +@end + +struct astruct afunc(foo *foo_obj) { + return [foo_obj stret]; +} + +/* { dg-final { scan-assembler "objc_msgSend_stret" } } */ +/* { dg-final { scan-assembler "objc_msgSendSuper_stret" } } */ + +/* { dg-final { scan-assembler-not "objc_msgSend\[^_S\]" } } */ +/* { dg-final { scan-assembler-not "objc_msgSendSuper\[^_\]" } } */ +