1/* { dg-do run } */ 2/* See if -forward:: is able to work. */ 3/* { dg-skip-if "Needs OBJC2 Implementation" { *-*-darwin8* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ 4/* { dg-additional-options "-Wl,-framework,Foundation" { target *-*-darwin* } } */ 5#include <stdio.h> 6#include <stdlib.h> 7 8/* Versions of the runtime after 10.13 no longer support the original 9 'forward:' mechanism, so we make a stripped down representation of 10 NSInvocation and need to link with -framework Foundation. */ 11#if __NEXT_RUNTIME__ 12@class NSInvocation, NSMethodSignature; 13# include "../../objc-obj-c++-shared/F-NSObject.h" 14@interface NSInvocation : NSObject 15+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)sig; 16@property SEL selector; 17- (void)invoke; 18- (void)invokeWithTarget:(id)target; 19@end 20# define OBJECT NSObject 21#else 22#include "../../objc-obj-c++-shared/TestsuiteObject.m" 23#define OBJECT TestsuiteObject 24#endif 25 26#define VALUETOUSE 1234567890 27 28id forwarder, receiver; 29 30@interface Forwarder : OBJECT 31{ 32 id receiver; 33} 34 35-initWithReceiver:theReceiver; 36#if __NEXT_RUNTIME__ 37- (void)forwardInvocation:(NSInvocation *)anInvocation; 38- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; 39#endif 40 41@end 42 43@interface Receiver : OBJECT 44{ 45 int foo; 46} 47-display; 48-initWithFoo:(int)theFoo; 49@end 50 51@implementation Receiver 52 53-initWithFoo: (int)theFoo 54{ 55 foo = theFoo; 56 return self; 57} 58 59-display 60{ 61 printf ("Executing display\n"); 62 /* Check to see if we are really the reciever. */ 63 if (self != receiver) 64 abort (); 65 /* And the value of foo is set correctly. */ 66 if (foo != VALUETOUSE) 67 abort (); 68 return self; 69} 70 71@end 72 73@implementation Forwarder 74-initWithReceiver: theReceiver 75{ 76 [super init]; 77 receiver = theReceiver; 78 return self; 79} 80 81#if __NEXT_RUNTIME__ 82- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSel 83{ 84 return [receiver methodSignatureForSelector:aSel]; 85} 86- (void)forwardInvocation:(NSInvocation *)anInvocation 87{ 88 if ([receiver respondsToSelector:[anInvocation selector]]) { 89 [anInvocation invokeWithTarget:receiver]; 90 } 91 else { 92 } 93} 94#else 95-(void *) forward:(SEL)theSel : (void *)theArgFrame 96{ 97 /* If we have a reciever try to perform on that object */ 98 if (receiver) 99 { 100 /* Simple forward that works for methods with no 101 arguments. */ 102 typedef id (*method_with_no_args) (id receiver, SEL _cmd); 103 Method method = class_getInstanceMethod (object_getClass (receiver), 104 theSel); 105 method_with_no_args imp = (method_with_no_args)(method_getImplementation 106 (method)); 107 return (*imp)(receiver, theSel); 108 } 109 110 /* Normally you'd emit an error here. */ 111 printf ("Unrecognized selector\n"); 112 return NULL; 113} 114#endif 115 116@end 117int main() 118{ 119 /* Init the reciever. */ 120 receiver = [[Receiver alloc] initWithFoo: VALUETOUSE]; 121 /* Init the fowarder. */ 122 forwarder = [[Forwarder alloc] initWithReceiver: receiver]; 123 /* Call display on the forwarder which in turns calls display on 124 the reciever. */ 125 [forwarder display]; 126 exit(0); 127} 128