diff options
Diffstat (limited to 'gcc/testsuite')
98 files changed, 2886 insertions, 26 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c1142f07ee3..dd4c187e043 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,31 @@ +2003-09-24 Ziemowit Laski <zlaski@apple.com> + + MERGE OF objc-improvements-branch into MAINLINE: + * lib/objc.exp (objc_target_compile): Do not point at libobjc headers + if libobjc has not been built. + * objc/execute/IMP.m, objc/execute/_cmd.m, objc/execute/bf-common.h, + objc/execute/bycopy-3.m, objc/execute/class-{1-14}.m, objc/execute/class-self-2.m, + objc/execute/many_args_method.m, objc/execute/nested-3.m, objc/execute/np-2.m, + objc/execute/object_is_class.m, objc/execute/object_is_meta_class.m, + objc/execute/redefining_self.m, objc/execute/root_methods.m, + objc/execute/static-{1-2}.m, objc/execute/string-{1-4}.m, objc/execute/va_method.m, + objc.dg/comp-types-4.m, objc.dg/headers.m, objc.dg/special/unclaimed-category-1.h, + objc.dg/special/unclaimed-category-1.m: Make usable with NeXT as well as GNU runtime. + * execute/next_mapping.h: New header, for GNU->NeXT impedance matching. + * execute/cascading-1.m, execute/function-message-1.m, objc.dg/anon-1.m, + objc.dg/bitfield-{3-4}.m, objc.dg/call-super-{1-3}.m, objc.dg/category-1.m, + objc.dg/const-str-{3-6}.m, objc.dg/encode-{1-4}.m, objc.dg/func-ptr-1.m, + objc.dg/gnu-runtime-1.m, objc.dg/image-info.m, objc.dg/method-{3-12}.m, + objc.dg/missing-proto-{1-3}.m, objc.dg/nested-func-1.m, objc.dg/proto-lossage-2.m, + objc.dg/proto-qual-1.m, objc.dg/sizeof-1.m, objc.dg/static-1.m, objc.dg/symtab-1.m, + objc.dg/try-catch-{1-4}.m, objc.dg/type-size-{1-2}.m, objc.dg/zero-link-{1-2}.m: + New test cases. + * objc.dg/bitfield-2.m: Run only on Darwin. + * objc.dg/class-2.m, objc.dg/comp-types-1.m, objc.dg/desig-init-1.m, + objc.dg/method-{1-2}.m, objc.dg/proto-hier-1.m, objc.dg/proto-lossage-1.m: + Adjust for message wording changes. + * objc.dg/const-str-1.m: Fix constant string layout. + 2003-09-24 Alexandre Oliva <aoliva@redhat.com> * gcc.dg/cpp/Wunknown-pragmas-1.c: New test. diff --git a/gcc/testsuite/lib/objc.exp b/gcc/testsuite/lib/objc.exp index 9e7c445d3ce..1817c7022e8 100644 --- a/gcc/testsuite/lib/objc.exp +++ b/gcc/testsuite/lib/objc.exp @@ -168,13 +168,15 @@ proc objc_target_compile { source dest type options } { set options [concat "additional_flags=$TOOL_OPTIONS" $options]; } - # Point to the ObjC headers in libobjc. - set objc_include_dir "${srcdir}/../../libobjc" - lappend options "additional_flags=-I${objc_include_dir}" + # If we have built libobjc along with the compiler (which usually + # _is not_ the case on Mac OS X systems), point the test harness + # at it (and associated headers). set objcpath "[get_multilibs]" set libobjc_dir [lookfor_file ${objcpath} libobjc/.libs/libobjc.a] if { $libobjc_dir != "" } { + set objc_include_dir "${srcdir}/../../libobjc" + lappend options "additional_flags=-I${objc_include_dir}" set libobjc_dir [file dirname ${libobjc_dir}] set objc_link_flags "-L${libobjc_dir}" lappend options "additional_flags=${objc_link_flags}" diff --git a/gcc/testsuite/objc.dg/anon-1.m b/gcc/testsuite/objc.dg/anon-1.m new file mode 100644 index 00000000000..5f10f7d6026 --- /dev/null +++ b/gcc/testsuite/objc.dg/anon-1.m @@ -0,0 +1,14 @@ +/* Test for graceful handling of anonymous ivars. */ +/* { dg-do compile } */ + +@interface Foo { + unsigned char : 1; + int e: 3; + signed: 2; + float f; +} +@end + +@implementation Foo +@end + diff --git a/gcc/testsuite/objc.dg/bitfield-2.m b/gcc/testsuite/objc.dg/bitfield-2.m index 0a401dd6afa..83b31748371 100644 --- a/gcc/testsuite/objc.dg/bitfield-2.m +++ b/gcc/testsuite/objc.dg/bitfield-2.m @@ -2,7 +2,7 @@ the NeXT runtime is used. */ /* Contributed by Ziemowit Laski <zlaski@apple.com>. */ /* { dg-options "-fnext-runtime -fsigned-char" } */ -/* { dg-do run } */ +/* { dg-do run { target *-*-darwin* } } */ struct objc_object { struct objc_class *class_pointer; } *id; diff --git a/gcc/testsuite/objc.dg/bitfield-3.m b/gcc/testsuite/objc.dg/bitfield-3.m new file mode 100644 index 00000000000..f427a3018ad --- /dev/null +++ b/gcc/testsuite/objc.dg/bitfield-3.m @@ -0,0 +1,50 @@ +/* Check if the @defs() construct preserves the correct + layout of bitfields. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc -Wpadded" } */ +/* { dg-do run } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); +extern int strcmp(const char *str1, const char *str2); +#define CHECK_IF(expr) if(!(expr)) abort() + +enum Enum { one, two, three, four }; + +@interface Base: Object { + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +@interface Derived: Base { + signed e: 5; + int f: 4; + enum Enum g: 3; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +/* Note that the semicolon after @defs(...) is optional. */ + +typedef struct { @defs(Base) } Base_t; /* { dg-warning "padding struct size to alignment boundary" } */ +typedef struct { @defs(Derived); } Derived_t; /* { dg-warning "padding struct size to alignment boundary" } */ + +int main(void) +{ + CHECK_IF(sizeof(Base_t) == sizeof(Base)); + CHECK_IF(sizeof(Derived_t) == sizeof(Derived)); + +#ifdef __NEXT_RUNTIME__ + CHECK_IF(!strcmp(@encode(Base), "{Base=#b2b3b4b5}")); + CHECK_IF(!strcmp(@encode(Derived), "{Derived=#b2b3b4b5b5b4b3}")); + + CHECK_IF(!strcmp(@encode(Base_t), "{?=#b2b3b4b5}")); + CHECK_IF(!strcmp(@encode(Derived_t), "{?=#b2b3b4b5b5b4b3}")); +#endif /* __NEXT_RUNTIME__ */ + + return 0; +} diff --git a/gcc/testsuite/objc.dg/bitfield-4.m b/gcc/testsuite/objc.dg/bitfield-4.m new file mode 100644 index 00000000000..858bac2b003 --- /dev/null +++ b/gcc/testsuite/objc.dg/bitfield-4.m @@ -0,0 +1,29 @@ +/* Make sure that bitfield types are printed correctly, and that ivar redeclaration + (@interface vs. @implementation) checks take the bitfield width into account. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +@interface Base { + int i; +} +@end + +@interface WithBitfields: Base { + void *isa; + unsigned a: 3; + signed b: 4; + int c: 5; +} +@end + +@implementation WithBitfields { + char *isa; /* { dg-error "conflicting instance variable type .char \\*isa." } */ + /* { dg-error "previous declaration of .void \\*isa." "" { target *-*-* } 12 } */ + unsigned a: 5; /* { dg-error "conflicting instance variable type .unsigned a: 5." } */ + /* { dg-error "previous declaration of .unsigned a: 3." "" { target *-*-* } 13 } */ + signed b: 4; /* This one is fine. */ + int c: 3; /* { dg-error "conflicting instance variable type .int c: 3." } */ + /* { dg-error "previous declaration of .int c: 5." "" { target *-*-* } 15 } */ +} +@end + diff --git a/gcc/testsuite/objc.dg/call-super-1.m b/gcc/testsuite/objc.dg/call-super-1.m new file mode 100644 index 00000000000..19e0d4900dd --- /dev/null +++ b/gcc/testsuite/objc.dg/call-super-1.m @@ -0,0 +1,76 @@ +/* Check if objc_super stack variables are created correctly (and + not clobbered by other values). */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-std=c99 -lobjc" } */ +/* { dg-do run } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); + +#define CHECK_IF(expr) if(!(expr)) abort(); + +typedef struct _Point { + float x; + float y; +} Point; + +Point MakePoint ( float x , float y ) { + Point p; + p.x = x; + p.y = y; + return p; +} + +@interface Base: Object +- ( void ) translateOriginToPoint : ( Point ) translation ; +@end + +@interface Derived : Base +- ( void ) scrollToPoint : ( Point ) newOrigin ; +- ( void ) translateOriginToPoint : ( Point ) translation ; +@end + +int blort; +float result; + +@implementation Base +- ( void ) translateOriginToPoint : ( Point ) translation { + result = translation.x + translation.y; +} +@end + +@implementation Derived +- ( void ) scrollToPoint : ( Point ) newOrigin { + float transDeltaX =newOrigin.x, transDeltaY =newOrigin.y ; + Point w; + if ( ! blort ) { + w.x = transDeltaX ; w.y = transDeltaY ; + [ super translateOriginToPoint : w ] ; + return; + } + [ super translateOriginToPoint : MakePoint ( transDeltaX , transDeltaY ) ] ; + return; +} +- (void) translateOriginToPoint : ( Point ) translation { + /* This should never be called. */ + CHECK_IF(0); +} +@end + +int main(void) { + Derived *v = [Derived new]; + float r0 = 1.5 + 1.5; + blort = 1; + [v scrollToPoint: MakePoint(1.5, 1.5)]; + CHECK_IF(result == r0); + blort = 0; + [v scrollToPoint: MakePoint(1.5, 1.5)]; + CHECK_IF(result == r0); + blort = 1; + [v scrollToPoint: MakePoint(1.5, 1.5)]; + CHECK_IF(result == r0); + [v free]; + return 0; +} diff --git a/gcc/testsuite/objc.dg/call-super-2.m b/gcc/testsuite/objc.dg/call-super-2.m new file mode 100644 index 00000000000..cd7db41bffe --- /dev/null +++ b/gcc/testsuite/objc.dg/call-super-2.m @@ -0,0 +1,139 @@ +/* Check if casting 'self' or 'super' affects message lookup in the + correct way. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +#ifdef __NEXT_RUNTIME__ +#define OBJC_GETCLASS objc_getClass +#else +#define OBJC_GETCLASS objc_get_class +#endif + +@protocol Func ++ (int) class_func0; +- (int) instance_func0; +@end + +@interface Derived: Object ++ (int) class_func1; ++ (int) class_func2; ++ (int) class_func3; ++ (int) class_func4; ++ (int) class_func5; ++ (int) class_func6; ++ (int) class_func7; +- (int) instance_func1; +- (int) instance_func2; +- (int) instance_func3; +- (int) instance_func4; +- (int) instance_func5; +- (int) instance_func6; +- (int) instance_func7; +@end + +@interface Derived (Categ) ++ (int) categ_class_func1; ++ (int) categ_class_func2; +- (int) categ_instance_func1; +- (int) categ_instance_func2; +@end + +@implementation Derived ++ (int) class_func1 +{ + int i = (int)[self class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 47 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 47 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 47 } */ + return i + (int)[super class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */ +} ++ (int) class_func2 +{ + int i = [(id <Func>)self class_func0]; + return i + [(id <Func>)super class_func0]; +} ++ (int) class_func3 +{ + return [(Object <Func> *)super class_func0]; +} ++ (int) class_func4 +{ + return [(Derived <Func> *)super class_func0]; +} ++ (int) class_func5 +{ + int i = (int)[Derived class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */ + return i + (int)[Object class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */ +} ++ (int) class_func6 +{ + return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning ".Object. may not respond to .\\+class_func1." } */ +} ++ (int) class_func7 +{ + return [OBJC_GETCLASS("Derived") class_func1]; +} +- (int) instance_func1 +{ + int i = (int)[self instance_func0]; /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */ + return i + (int)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */ +} +- (int) instance_func2 +{ + return [(id <Func>)super instance_func0]; +} +- (int) instance_func3 +{ + return [(Object <Func> *)super instance_func0]; +} +- (int) instance_func4 +{ + return [(Derived <Func> *)super instance_func0]; +} +- (int) instance_func5 +{ + int i = (int)[Derived instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+instance_func1." } */ + return i + (int)[Object instance_func1]; /* { dg-warning ".Object. may not respond to .\\+instance_func1." } */ +} +- (int) instance_func6 +{ + return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning ".Object. may not respond to .\\+class_func1." } */ +} +- (int) instance_func7 +{ + return [OBJC_GETCLASS("Derived") class_func1]; +} +@end + +@implementation Derived (Categ) ++ (int) categ_class_func1 +{ + int i = (int)[self class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */ + i += [self class_func1]; + i += [self categ_class_func2]; + i += (int)[self categ_instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+categ_instance_func1." } */ + return i + (int)[super class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */ +} ++ (int) categ_class_func2 +{ + int i = [(id <Func>)self class_func0]; + return i + [(id <Func>)super class_func0]; +} +- (int) categ_instance_func1 +{ + int i = (int)[self instance_func0]; /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */ + i += [(Derived <Func> *)self categ_instance_func2]; + i += (int)[(Object <Func> *)self categ_instance_func2]; /* { dg-warning ".Object. may not respond to .\\-categ_instance_func2." } */ + /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" "" { target *-*-* } 129 } */ + i += (int)[(id <Func>)self categ_instance_func2]; /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" } */ + i += [(id)self categ_instance_func2]; + return i + (int)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */ +} +- (int) categ_instance_func2 +{ + return [(id <Func>)super instance_func0]; +} +@end diff --git a/gcc/testsuite/objc.dg/call-super-3.m b/gcc/testsuite/objc.dg/call-super-3.m new file mode 100644 index 00000000000..05b6233ff5f --- /dev/null +++ b/gcc/testsuite/objc.dg/call-super-3.m @@ -0,0 +1,54 @@ +/* Check if sending messages to super does not interfere with sending messages + to classes. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do run } */ +/* { dg-options "-lobjc" } */ + +#include <objc/Object.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface Base: Object ++ (int) class_func1; +- (int) instance_func1; +@end + +@interface Derived: Base ++ (int) class_func1; +@end + +@interface Derived (Categ) +- (int) instance_func1; +@end + +@implementation Base ++ (int) class_func1 { return 234; } +- (int) instance_func1 { return 345; } +@end + +@implementation Derived ++ (int) class_func1 { + int i = [super class_func1]; + i += [Base class_func1]; + return i; +} +@end + +@implementation Derived (Categ) +- (int) instance_func1 { + int i = [super instance_func1]; + i += [Base class_func1]; /* { dg-bogus "invalid receiver type" } */ + return i; +} +@end + +int main(void) { + Base *base = [[Base alloc] init]; /* { dg-bogus "invalid receiver type" } */ + Derived *derived = [[Derived alloc] init]; + CHECK_IF([Base class_func1] == 234); /* { dg-bogus "invalid receiver type" } */ + CHECK_IF([Derived class_func1] == 234 + 234); + CHECK_IF([base instance_func1] == 345); + CHECK_IF([derived instance_func1] == 234 + 345); + return 0; +} diff --git a/gcc/testsuite/objc.dg/category-1.m b/gcc/testsuite/objc.dg/category-1.m new file mode 100644 index 00000000000..1d29e374aea --- /dev/null +++ b/gcc/testsuite/objc.dg/category-1.m @@ -0,0 +1,43 @@ +/* Test class methods inside categories. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <objc/Object.h> + +#ifdef __NEXT_RUNTIME__ +#define SUPERCLASS superclass +#else +#define SUPERCLASS superClass +#endif + +extern int strcmp(const char *s1, const char *s2); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface MyObject: Object ++ (Class)whatever1; +@end + +@implementation MyObject ++ (Class)whatever1 { return [super SUPERCLASS]; } +@end + +@interface MyObject (ThisWontCompile) ++(Class)whatever2; +@end + +@implementation MyObject (ThisWontCompile) ++(Class)whatever2 { return [super SUPERCLASS]; } +@end + +int main (int argc, const char * argv[]) +{ + Class w1 = [MyObject whatever1]; + Class w2 = [MyObject whatever2]; + + CHECK_IF(!strcmp(w1->name, "Object")); + CHECK_IF(!strcmp(w2->name, "Object")); + return 0; +} + diff --git a/gcc/testsuite/objc.dg/class-2.m b/gcc/testsuite/objc.dg/class-2.m index a4514f9290a..b98d117f54c 100644 --- a/gcc/testsuite/objc.dg/class-2.m +++ b/gcc/testsuite/objc.dg/class-2.m @@ -10,6 +10,5 @@ @interface class1 : supclass1 @end -@implementation class1 : supclass2 -@end /* { dg-error "conflicting super class name" } */ -/* { dg-error "previous declaration" "" { target *-*-* } 14 } */ +@implementation class1 : supclass2 /* { dg-error "conflicting super class name" } */ +@end /* { dg-error "previous declaration" "" { target *-*-* } 13 } */ diff --git a/gcc/testsuite/objc.dg/comp-types-1.m b/gcc/testsuite/objc.dg/comp-types-1.m index 74943860b2d..310b22634c0 100644 --- a/gcc/testsuite/objc.dg/comp-types-1.m +++ b/gcc/testsuite/objc.dg/comp-types-1.m @@ -41,7 +41,7 @@ int main() MyProtocol), but not from an 'id' or from a 'MyOtherClass *' (which implements MyProtocol). */ obj_p = obj; /* Ok */ - obj_p = obj_c; /* { dg-warning "does not implement" } */ /*FIXME: Duplicated*/ + obj_p = obj_c; /* { dg-warning "does not implement" } */ obj_p = obj_cp; /* Ok */ obj_p = obj_C; /* { dg-warning "incompatible pointer type" } */ diff --git a/gcc/testsuite/objc.dg/comp-types-4.m b/gcc/testsuite/objc.dg/comp-types-4.m index e07780485ee..f15390a38d3 100644 --- a/gcc/testsuite/objc.dg/comp-types-4.m +++ b/gcc/testsuite/objc.dg/comp-types-4.m @@ -3,6 +3,11 @@ /* { dg-do compile } */ #include <objc/objc.h> +/* The NeXT runtime headers do not define NULL. */ +#ifndef NULL +#define NULL ((void *)0) +#endif + @protocol MyProtocol - (void) method; @end diff --git a/gcc/testsuite/objc.dg/const-str-1.m b/gcc/testsuite/objc.dg/const-str-1.m index 145c1b31e84..e4cac2e57ec 100644 --- a/gcc/testsuite/objc.dg/const-str-1.m +++ b/gcc/testsuite/objc.dg/const-str-1.m @@ -2,12 +2,21 @@ /* { dg-do compile } */ /* { dg-options "-fgnu-runtime" } */ +#ifdef __cplusplus +extern void baz(...); +#endif + void foo() { baz(@"hiya"); /* { dg-error "annot find interface declaration" } */ } @interface NXConstantString +{ + void *isa; + char *str; + int len; +} @end void bar() diff --git a/gcc/testsuite/objc.dg/const-str-3.m b/gcc/testsuite/objc.dg/const-str-3.m new file mode 100644 index 00000000000..edc03ff62c7 --- /dev/null +++ b/gcc/testsuite/objc.dg/const-str-3.m @@ -0,0 +1,46 @@ +/* Test the -fconstant-string-class=Foo option under the NeXT + runtime. */ +/* Developed by Markus Hitter <mah@jump-ing.de>. */ + +/* { dg-options "-fnext-runtime -fconstant-string-class=Foo -lobjc" } */ +/* { dg-do run { target *-*-darwin* } } */ + +#include <stdio.h> +#include <objc/objc.h> +#include <objc/Object.h> + +@interface Foo: Object { + char *cString; + unsigned int len; +} +- (char *)customString; +@end + +struct objc_class _FooClassReference; + +@implementation Foo : Object +- (char *)customString { + return cString; +} +@end + +int main () { + Foo *string = @"bla"; + Foo *string2 = @"bla"; + + if(string != string2) + abort(); + printf("Strings are being uniqued properly\n"); + + /* This memcpy has to be done before the first message is sent to a + constant string object. Can't be moved to +initialize since _that_ + is already a message. */ + + memcpy(&_FooClassReference, objc_getClass("Foo"), sizeof(_FooClassReference)); + if (strcmp ([string customString], "bla")) { + abort (); + } + + printf([@"This is a working constant string object\n" customString]); + return 0; +} diff --git a/gcc/testsuite/objc.dg/const-str-4.m b/gcc/testsuite/objc.dg/const-str-4.m new file mode 100644 index 00000000000..c178bfc4a0c --- /dev/null +++ b/gcc/testsuite/objc.dg/const-str-4.m @@ -0,0 +1,31 @@ +/* Ensure that the preprocessor handles ObjC string constants gracefully. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-options "-fnext-runtime -fconstant-string-class=MyString -lobjc" } */ +/* { dg-do run { target *-*-darwin* } } */ + +extern void abort(void); + +@interface MyString +{ + void *isa; + char *str; + int len; +} +@end + +#define kMyStringMacro1 "My String" +#define kMyStringMacro2 @"My String" + +void *_MyStringClassReference; + +@implementation MyString +@end + +int main(void) { + MyString* aString1 = @kMyStringMacro1; + MyString* aString2 = kMyStringMacro2; + if(aString1 != aString2) { + abort(); + } + return 0; +} diff --git a/gcc/testsuite/objc.dg/const-str-5.m b/gcc/testsuite/objc.dg/const-str-5.m new file mode 100644 index 00000000000..186edcfceb2 --- /dev/null +++ b/gcc/testsuite/objc.dg/const-str-5.m @@ -0,0 +1,27 @@ +/* Positive test case for constant string layout. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fconstant-string-class=MyConstantString" } */ +/* { dg-do compile } */ + +@interface MyBase { + const char *p; +} +@end + +@interface MyConstantString: MyBase { + union { + void *u; + unsigned char *c; + } _contents; + unsigned int _count; +} +@end + +/* The NeXT runtime initializes the 'isa' pointer of string constants at + compile time. */ +#ifdef __NEXT_RUNTIME__ +extern void *_MyConstantStringClassReference; +#endif + +MyConstantString *str = @"Hello"; diff --git a/gcc/testsuite/objc.dg/const-str-6.m b/gcc/testsuite/objc.dg/const-str-6.m new file mode 100644 index 00000000000..a7cbbf7141a --- /dev/null +++ b/gcc/testsuite/objc.dg/const-str-6.m @@ -0,0 +1,27 @@ +/* Negative test case for constant string layout. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fconstant-string-class=MyConstantString" } */ +/* { dg-do compile } */ + +@interface MyBase { + char p; +} +@end + +@interface MyConstantString: MyBase { + union { + void *u; + unsigned char *c; + } _contents; + char _count; +} +@end + +/* The NeXT runtime initializes the 'isa' pointer of string constants at + compile time. */ +#ifdef __NEXT_RUNTIME__ +extern void *_MyConstantStringClassReference; +#endif + +MyConstantString *str = @"Hello"; /* { dg-error "interface .MyConstantString. does not have valid constant string layout" } */ diff --git a/gcc/testsuite/objc.dg/desig-init-1.m b/gcc/testsuite/objc.dg/desig-init-1.m index 72fe8330960..44abe440d7b 100644 --- a/gcc/testsuite/objc.dg/desig-init-1.m +++ b/gcc/testsuite/objc.dg/desig-init-1.m @@ -22,7 +22,10 @@ 0, [Cls meth1], [2 + 1] = 3, - [2 * 2 ... 5] = [0 meth2], /* { dg-warning "invalid receiver type" } */ + [2 * 2 ... 5] = (int)[0 meth2], /* { dg-warning "invalid receiver type" } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */ [2] [Cls meth2] }; diff --git a/gcc/testsuite/objc.dg/encode-1.m b/gcc/testsuite/objc.dg/encode-1.m new file mode 100644 index 00000000000..868c3254753 --- /dev/null +++ b/gcc/testsuite/objc.dg/encode-1.m @@ -0,0 +1,25 @@ +/* Test if the Objective-C @encode machinery distinguishes between + 'BOOL *' (which should be encoded as a pointer to BOOL) and 'char *' (which + should be encoded as '*'). This is somewhat tricky wrt the NeXT runtime, + where we have 'typedef char BOOL'. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fnext-runtime -lobjc" } */ +/* { dg-do run } */ + +#include <string.h> +#include <stdlib.h> +#include <objc/objc.h> + +int main(void) { + const char *BOOL_ptr = @encode(BOOL *); + const char *BOOL_ = @encode(BOOL); + const char *char_ptr = @encode(char *); + + if(*BOOL_ptr != '^' || strcmp(BOOL_ptr + 1, BOOL_)) + abort(); + + if(strcmp(char_ptr, "*")) + abort(); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/encode-2.m b/gcc/testsuite/objc.dg/encode-2.m new file mode 100644 index 00000000000..ebfd8d3fa2d --- /dev/null +++ b/gcc/testsuite/objc.dg/encode-2.m @@ -0,0 +1,97 @@ +/* Test Objective-C method encodings. */ + +/* The _encoded_ parameter offsets for Objective-C methods are + computed inductively as follows: + - The first paramter (self) has offset 0; + - The k-th parameter (k > 1) has offset equal to the + sum of: + - the offset of the k-1-st paramter + - the int-promoted size of the k-1-st parameter. + + Note that the encoded offsets need not correspond + to the actual placement of parameters (relative to 'self') + on the stack! Your target's ABI may have very different + opinions on the matter. */ + +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do run } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +#ifdef __NEXT_RUNTIME__ +#define METHOD Method +#define OBJC_GETCLASS objc_getClass +#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod +#else +#include <objc/objc-api.h> +#define METHOD Method_t +#define OBJC_GETCLASS objc_get_class +#define CLASS_GETINSTANCEMETHOD class_get_instance_method +#endif + +extern int sscanf(const char *str, const char *format, ...); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface Foo: Object +typedef struct { float x, y; } XXPoint; +typedef struct { float width, height; } XXSize; +typedef struct _XXRect { XXPoint origin; XXSize size; } XXRect; +-(id)setRect:(XXRect)r withInt:(int)i; +-(void) char:(char)c float:(float)f double:(double)d long:(long)l; +@end + +XXRect my_rect; +unsigned offs1, offs2, offs3, offs4, offs5, offs6, offs7; + +@implementation Foo +-(id)setRect:(XXRect)r withInt:(int)i { + unsigned offs = sizeof(self); + CHECK_IF(offs == offs3); + offs += sizeof(_cmd); + CHECK_IF(offs == offs4); + offs += sizeof(r); + CHECK_IF(offs == offs5); + offs += sizeof(i); + CHECK_IF(offs == offs1); + return nil; +} +-(void) char:(char)c float:(float)f double:(double)d long:(long)l { + unsigned offs = sizeof(self); + CHECK_IF(offs == offs3); + offs += sizeof(_cmd); + CHECK_IF(offs == offs4); + offs += sizeof((int)c); + CHECK_IF(offs == offs5); + offs += sizeof(f); + CHECK_IF(offs == offs6); + offs += sizeof(d); + CHECK_IF(offs == offs7); + offs += sizeof(l); + CHECK_IF(offs == offs1); +} +@end + + +int main(void) { + Foo *foo = [[Foo alloc] init]; + Class fooClass = OBJC_GETCLASS("Foo"); + METHOD meth; + + meth = CLASS_GETINSTANCEMETHOD(fooClass, @selector(setRect:withInt:)); + offs2 = 9999; + sscanf(meth->method_types, "@%u@%u:%u{_XXRect={?=ff}{?=ff}}%ui%u", &offs1, &offs2, &offs3, + &offs4, &offs5); + CHECK_IF(!offs2); + [foo setRect:my_rect withInt:123]; + + meth = CLASS_GETINSTANCEMETHOD(fooClass, @selector(char:float:double:long:)); + offs2 = 9999; + sscanf(meth->method_types, "v%u@%u:%uc%uf%ud%ul%u", &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6, &offs7); + CHECK_IF(!offs2); + [foo char:'c' float:2.3 double:3.5 long:2345L]; + + return 0; +} diff --git a/gcc/testsuite/objc.dg/encode-3.m b/gcc/testsuite/objc.dg/encode-3.m new file mode 100644 index 00000000000..b30b956b157 --- /dev/null +++ b/gcc/testsuite/objc.dg/encode-3.m @@ -0,0 +1,66 @@ +/* Method encoding tests for stand-alone @protocol declarations. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do run } */ + +#include <objc/Protocol.h> +#ifdef __cplusplus +#define ProtoBool bool +#else +#define ProtoBool _Bool +#endif + +#ifndef __NEXT_RUNTIME__ +#include <objc/objc-api.h> +#endif + +extern int sscanf(const char *str, const char *format, ...); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +enum Enum { + zero, one, two, three +}; +typedef enum Enum Enum; +typedef signed char ObjCBool; /* as used by the NeXT runtime */ + +@protocol Proto +union __XXAngle { unsigned int alpha, beta; }; +typedef struct { float x, y; union __XXAngle a; } XXPoint; +typedef struct { double width, height; } XXSize; +typedef struct _XXRect { XXPoint origin; XXSize size; struct _XXRect *next; } XXRect; +- (void) char:(char)c float:(float)f double:(double)d unsigned:(unsigned)u short:(short)s long:(long)l; +- (void *)setRect:(XXRect)r withBool:(ProtoBool)b withInt:(int)i; ++ (Enum *)getEnum:(XXPoint *)pt enum:(enum Enum)e bool:(ObjCBool)b; ++ (ProtoBool **)getBool:(ObjCBool **)b; +@end + +Protocol *proto = @protocol(Proto); +struct objc_method_description *meth; +unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7; + +static void scan_initial(const char *pattern) { + totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1; + sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6, &offs7); + CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2); +} + +int main(void) { + meth = [proto descriptionForInstanceMethod: @selector(char:float:double:unsigned:short:long:)]; + scan_initial("v%u@%u:%uc%uf%ud%uI%us%ul%u"); + CHECK_IF(offs3 == offs2 + sizeof(int) && offs4 == offs3 + sizeof(float)); + CHECK_IF(offs5 == offs4 + sizeof(double) && offs6 == offs5 + sizeof(unsigned)); + CHECK_IF(offs7 == offs6 + sizeof(int) && totsize == offs7 + sizeof(long)); + meth = [proto descriptionForInstanceMethod: @selector(setRect:withBool:withInt:)]; + scan_initial("^v%u@%u:%u{_XXRect={?=ff(__XXAngle=II)}{?=dd}^{_XXRect}}%uB%ui%u"); + CHECK_IF(offs3 == offs2 + sizeof(XXRect) && offs4 == offs3 + sizeof(int)); + CHECK_IF(totsize == offs4 + sizeof(int)); + meth = [proto descriptionForClassMethod: @selector(getEnum:enum:bool:)]; + scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u"); + CHECK_IF(offs3 == offs2 + sizeof(XXPoint *) && offs4 == offs3 + sizeof(enum Enum)); + CHECK_IF(totsize == offs4 + sizeof(int)); /* 'ObjCBool' is really 'char' */ + meth = [proto descriptionForClassMethod: @selector(getBool:)]; + scan_initial("^^B%u@%u:%u^*%u"); + CHECK_IF(totsize == offs2 + sizeof(ObjCBool **)); + return 0; +} diff --git a/gcc/testsuite/objc.dg/encode-4.m b/gcc/testsuite/objc.dg/encode-4.m new file mode 100644 index 00000000000..1f179e1dad5 --- /dev/null +++ b/gcc/testsuite/objc.dg/encode-4.m @@ -0,0 +1,73 @@ +/* Encoding tests for ObjC class layouts. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <objc/Object.h> +#ifdef __NEXT_RUNTIME__ +#include <objc/objc-class.h> +#define OBJC_GETCLASS objc_getClass +#else +#include <objc/objc-api.h> +#define OBJC_GETCLASS objc_get_class +#endif + +extern void abort(void); +extern int strcmp(const char *s1, const char *s2); +#define CHECK_IF(expr) if(!(expr)) abort() + +@class Int1, Int2; +struct Nested; + +struct Innermost { + unsigned char a, b; + struct Nested *encl; +}; + +struct Nested { + float a, b; + Int1 *next; + struct Innermost innermost; +}; + +@interface Int1: Object { + char a, b; + Int2 *int2; + struct Nested nested; +} +@end + +@interface Int2: Int1 { + struct Innermost *innermost; + Int1 *base; +} +@end + +@implementation Int1 +@end + +@implementation Int2 +@end + +struct objc_ivar *ivar; + +static void check_ivar(const char *name, const char *type) { + CHECK_IF(!strcmp(ivar->ivar_name, name)); + CHECK_IF(!strcmp(ivar->ivar_type, type)); + ivar++; +} + +int main(void) { + ivar = ((Class)OBJC_GETCLASS("Int1"))->ivars->ivar_list; + check_ivar("a", "c"); + check_ivar("b", "c"); + check_ivar("int2", "@\"Int2\""); + check_ivar("nested", + "{Nested=\"a\"f\"b\"f\"next\"@\"Int1\"\"innermost\"{Innermost=\"a\"C\"b\"C\"encl\"^{Nested}}}"); + + ivar = ((Class)OBJC_GETCLASS("Int2"))->ivars->ivar_list; + check_ivar("innermost", "^{Innermost=CC^{Nested}}"); + check_ivar("base", "@\"Int1\""); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/func-ptr-1.m b/gcc/testsuite/objc.dg/func-ptr-1.m new file mode 100644 index 00000000000..015d3ac292d --- /dev/null +++ b/gcc/testsuite/objc.dg/func-ptr-1.m @@ -0,0 +1,48 @@ +/* Test for handling of function pointer ivars */ +/* { dg-do run } */ + +#include <objc/Object.h> + +extern int strcmp(const char *, const char *); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +typedef float (*floatfunc)(float, float); + +@interface MyObject : Object +{ +@public + int (*ivar)(int, int, int); + floatfunc ffunc; +} +- init; +@end + +int foo(int a, int b, int c) { + return a + b + c; +} + +float bar(float a, float b) { + return a * b; +} + +@implementation MyObject +- init { + [super init]; + ivar = foo; + ffunc = bar; + return self; +} +@end + +int main () +{ + MyObject *obj = [[MyObject alloc] init]; + const char *enc = @encode(MyObject); + + CHECK_IF(obj->ivar(4, 5, 6) == 15); + CHECK_IF(obj->ffunc(34.0, 45.0) == 34.0 * 45.0); + CHECK_IF(!strcmp(enc, "{MyObject=#^?^?}")); + return(0); +} + diff --git a/gcc/testsuite/objc.dg/gnu-runtime-1.m b/gcc/testsuite/objc.dg/gnu-runtime-1.m new file mode 100644 index 00000000000..dab921554f1 --- /dev/null +++ b/gcc/testsuite/objc.dg/gnu-runtime-1.m @@ -0,0 +1,19 @@ +/* Test that compiling for the GNU runtime works (regardless of + the system runtime used). */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ +/* { dg-options "-fgnu-runtime" } */ + +#include <objc/Object.h> + +@interface FooBar: Object +- (void)boo; +@end + +int main () +{ + id fooBarInst = [[FooBar alloc] init]; + [fooBarInst boo]; + return 0; +} + diff --git a/gcc/testsuite/objc.dg/headers.m b/gcc/testsuite/objc.dg/headers.m index 5435a75deee..4c61e1e5524 100644 --- a/gcc/testsuite/objc.dg/headers.m +++ b/gcc/testsuite/objc.dg/headers.m @@ -3,14 +3,29 @@ // { dg-options "-Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wshadow" } // { dg-do compile } +#ifdef __NEXT_RUNTIME__ +#include <Foundation/NSString.h> +#else #include <objc/NXConstStr.h> +#endif #include <objc/Object.h> #include <objc/Protocol.h> +#ifdef __NEXT_RUNTIME__ +#include <objc/objc-runtime.h> +#else #include <objc/encoding.h> #include <objc/hash.h> +#endif + #include <objc/objc-api.h> +#ifndef __NEXT_RUNTIME__ #include <objc/objc-list.h> +#endif + #include <objc/objc.h> + +#ifndef __NEXT_RUNTIME__ #include <objc/sarray.h> #include <objc/thr.h> #include <objc/typedstream.h> +#endif diff --git a/gcc/testsuite/objc.dg/image-info.m b/gcc/testsuite/objc.dg/image-info.m new file mode 100644 index 00000000000..84e6ad8d0e2 --- /dev/null +++ b/gcc/testsuite/objc.dg/image-info.m @@ -0,0 +1,38 @@ +/* Check if the '-freplace-objc-classes' option causes the + __OBJC,__image_info section to be emitted. This is only + usable on MacOS X 10.3 and later. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-freplace-objc-classes" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +#ifndef __NEXT_RUNTIME__ +#error Feature not currently supported by the GNU runtime +#endif + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); + +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object { +@public + int a; + float b; + char c; +} +- init; +@end + +@implementation Base +- init { + [super init]; + a = 123; + b = 1.23; + c = 'c'; + return self; +} +@end + +/* { dg-final { scan-assembler "\n.data\n.section __OBJC, __image_info\n\t.align.*\nL_OBJC_IMAGE_INFO:\n\t.long\t0\n\t.long\t1\n.data\n.objc_module_info\n" } } */ diff --git a/gcc/testsuite/objc.dg/method-1.m b/gcc/testsuite/objc.dg/method-1.m index 8b761c65a28..391ee629c70 100644 --- a/gcc/testsuite/objc.dg/method-1.m +++ b/gcc/testsuite/objc.dg/method-1.m @@ -3,12 +3,12 @@ @interface class1 - (int) meth1; -- (void) meth1; /* { dg-error "duplicate declaration of instance method" } */ +- (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */ @end @interface class2 + (void) meth1; -+ (int) meth1; /* { dg-error "duplicate declaration of class method" } */ ++ (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */ @end @interface class3 @@ -17,8 +17,7 @@ @implementation class3 - (int) meth1 { return 0; } -- (int) meth1 { return 0; } /* { dg-error "duplicate definition of instance method" } */ -/* { dg-error "redefinition of" "" { target *-*-* } 20 } */ +- (int) meth1 { return 0; } /* { dg-error "redefinition of" } */ /* { dg-error "previously defined here" "" { target *-*-* } 19 } */ @end @@ -28,7 +27,6 @@ @implementation class4 + (void) meth1 {} -+ (void) meth1 {} /* { dg-error "duplicate definition of class method" } */ -/* { dg-error "redefinition of" "" { target *-*-* } 31 } */ -/* { dg-error "previously defined here" "" { target *-*-* } 30 } */ ++ (void) meth1 {} /* { dg-error "redefinition of" } */ +/* { dg-error "previously defined here" "" { target *-*-* } 29 } */ @end diff --git a/gcc/testsuite/objc.dg/method-10.m b/gcc/testsuite/objc.dg/method-10.m new file mode 100644 index 00000000000..5a2a1db3462 --- /dev/null +++ b/gcc/testsuite/objc.dg/method-10.m @@ -0,0 +1,32 @@ +/* When there is only one candidate method available, make sure the + compiler uses its argument/return types when constructing the + message sends (so that proper C/C++ argument conversions may + take place). */ +/* { dg-do run } */ + +#include <objc/Object.h> +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +static double d = 4.5920234e2; + +@interface Foo : Object +-(void) brokenType: (int)x floatingPoint: (double)y; +@end + + +@implementation Foo +-(void) brokenType: (int)x floatingPoint: (double)y +{ + CHECK_IF(x == 459); + CHECK_IF(y == d); +} +@end + +int main(void) +{ + Foo *foo=[Foo new]; + [foo brokenType: d floatingPoint: d]; + return 0; +} + diff --git a/gcc/testsuite/objc.dg/method-11.m b/gcc/testsuite/objc.dg/method-11.m new file mode 100644 index 00000000000..5921292c1ba --- /dev/null +++ b/gcc/testsuite/objc.dg/method-11.m @@ -0,0 +1,33 @@ +/* Ensure that we indeed cannot obtain the value of a message send + if the chosen method signature returns 'void'. There used to + exist a cheesy hack that allowed it. While at it, check that + the first lexically occurring method signature gets picked + when sending messages to 'id'. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface Object1 +- (void)initWithData:(Object1 *)data; +@end + +@interface Object2 +- (id)initWithData:(Object1 *)data; +@end + +@interface Object3 +- (id)initWithData:(Object2 *)data; +@end + +void foo(void) { + id obj1, obj2 = 0; + obj2 = [obj1 initWithData: obj2]; + /* { dg-warning "multiple methods named .\\-initWithData:. found" "" { target *-*-* } 25 } */ + /* { dg-warning "using .\\-\\(void\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 12 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 16 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object2 \\*\\)data." "" { target *-*-* } 20 } */ + + /* The following error is a consequence of picking the "wrong" method signature. */ + /* { dg-error "void value not ignored as it ought to be" "" { target *-*-* } 25 } */ +} diff --git a/gcc/testsuite/objc.dg/method-12.m b/gcc/testsuite/objc.dg/method-12.m new file mode 100644 index 00000000000..d6e6ce58a4f --- /dev/null +++ b/gcc/testsuite/objc.dg/method-12.m @@ -0,0 +1,25 @@ +/* Contributed by Igor Seleznev <selez@mail.ru>. */ +/* This used to be broken. */ + +#include <objc/objc-api.h> + +@interface A ++ (A *)currentContext; +@end + +@interface B ++ (B *)currentContext; +@end + +int main() +{ + [A currentContext]; /* { dg-bogus "multiple declarations" } */ + return 0; +} + +@implementation A ++ (A *)currentContext { return nil; } +@end +@implementation B ++ (B *)currentContext { return nil; } +@end diff --git a/gcc/testsuite/objc.dg/method-2.m b/gcc/testsuite/objc.dg/method-2.m index b4cd4da6376..8bf211f8700 100644 --- a/gcc/testsuite/objc.dg/method-2.m +++ b/gcc/testsuite/objc.dg/method-2.m @@ -22,10 +22,11 @@ [self rootInstanceMethod]; /* class is searched for an instance method */ [MyIntermediate rootInstanceMethod]; /* with the same name. */ - [self instanceMethod]; /* { dg-warning "cannot find class" } */ - /* { dg-warning "defaults to id" "" { target *-*-* } 25 } */ - [MyDerived instanceMethod]; /* { dg-warning "cannot find class" } */ - /* { dg-warning "defaults to id" "" { target *-*-* } 27 } */ + [self instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */ + [MyDerived instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */ } @end diff --git a/gcc/testsuite/objc.dg/method-3.m b/gcc/testsuite/objc.dg/method-3.m new file mode 100644 index 00000000000..65031b0aa5b --- /dev/null +++ b/gcc/testsuite/objc.dg/method-3.m @@ -0,0 +1,45 @@ +/* Test for sending messages to aliased classes (and instances thereof). */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <objc/Object.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface Int1: Object ++ (int) classMeth; +- (int) instanceMeth; +@end + +@interface Int2: Object ++ (int) classMeth; +- (int) instanceMeth; +@end + +@implementation Int1 ++ (int) classMeth { return 345; } +- (int) instanceMeth { return 697; } +@end + +@implementation Int2 ++ (int) classMeth { return 1345; } +- (int) instanceMeth { return 1697; } +@end + +typedef Int1 Int1Typedef; +@compatibility_alias Int1Alias Int1Typedef; +@compatibility_alias Int2Alias Int2; +typedef Int2Alias Int2Typedef; + +int main(void) { + Int1Alias *int1alias = [[Int1Typedef alloc] init]; + Int2Typedef *int2typedef = [[Int2Alias alloc] init]; + + CHECK_IF([Int1Typedef classMeth] == 345 && [Int2Alias classMeth] == 1345); + CHECK_IF([int1alias instanceMeth] == 697 && [int2typedef instanceMeth] == 1697); + CHECK_IF([(Int2Typedef *)int1alias instanceMeth] == 697); + CHECK_IF([(Int1Alias *)int2typedef instanceMeth] == 1697); + return 0; +} diff --git a/gcc/testsuite/objc.dg/method-4.m b/gcc/testsuite/objc.dg/method-4.m new file mode 100644 index 00000000000..c8d092df74d --- /dev/null +++ b/gcc/testsuite/objc.dg/method-4.m @@ -0,0 +1,25 @@ +/* Check if class references (generated for the NeXT runtime) are appropriately + folded. This test is safe to run on all targets. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fnext-runtime" } */ +/* { dg-do compile } */ + +#include <objc/Object.h> + +typedef Object ObjectTypedef1; +typedef ObjectTypedef1 ObjectTypedef2; +@compatibility_alias ObjectAlias1 ObjectTypedef2; +@compatibility_alias ObjectAlias2 ObjectAlias1; +typedef ObjectAlias2 ObjectTypedef3; + +void foo(void) { + id obj = [Object new]; + obj = [ObjectTypedef1 new]; + obj = [ObjectTypedef2 new]; + obj = [ObjectTypedef3 new]; + obj = [ObjectAlias1 new]; + obj = [ObjectAlias2 new]; +} + +/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */ +/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */ diff --git a/gcc/testsuite/objc.dg/method-5.m b/gcc/testsuite/objc.dg/method-5.m new file mode 100644 index 00000000000..e2332ea8bd7 --- /dev/null +++ b/gcc/testsuite/objc.dg/method-5.m @@ -0,0 +1,18 @@ +/* Check if sending messages to "underspecified" objects is handled gracefully. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +@class UnderSpecified; +typedef struct NotAClass { + int a, b; +} NotAClass; + +void foo(UnderSpecified *u, NotAClass *n) { + [n nonexistent_method]; /* { dg-warning "invalid receiver type" } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 11 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 11 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 11 } */ + [NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */ + [u nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\-nonexistent_method." } */ + [UnderSpecified nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\+nonexistent_method." } */ +} diff --git a/gcc/testsuite/objc.dg/method-6.m b/gcc/testsuite/objc.dg/method-6.m new file mode 100644 index 00000000000..212958b55c7 --- /dev/null +++ b/gcc/testsuite/objc.dg/method-6.m @@ -0,0 +1,26 @@ +/* Check that sending messages to variables of type 'Class' does not involve instance methods. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +#include <objc/Protocol.h> + +@interface Base +- (unsigned)port; +- (id)starboard; +@end + +@interface Derived: Base +- (Object *)port; ++ (Protocol *)port; +@end + +id foo(void) { + Class receiver; + id p = [receiver port]; /* there should be no warnings here! */ + p = [receiver starboard]; /* { dg-warning ".Class. may not respond to .\\+starboard." } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 20 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 20 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 20 } */ + p = [Class port]; /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */ + return p; +} diff --git a/gcc/testsuite/objc.dg/method-7.m b/gcc/testsuite/objc.dg/method-7.m new file mode 100644 index 00000000000..f84759c2169 --- /dev/null +++ b/gcc/testsuite/objc.dg/method-7.m @@ -0,0 +1,27 @@ +/* Check if finding multiple signatures for a method is handled gracefully. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +#include <objc/Object.h> + +@interface Class1 +- (void)setWindow:(Object *)wdw; +@end + +@interface Class2 +- (void)setWindow:(Class1 *)window; +@end + +id foo(void) { + Object *obj = [[Object alloc] init]; + id obj2 = obj; + [obj setWindow:nil]; /* { dg-warning ".Object. may not respond to .\\-setWindow:." } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 18 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 18 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 18 } */ + [obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */ + /* { dg-warning "using .\\-\\(void\\)setWindow:\\(Object \\*\\)wdw." "" { target *-*-* } 8 } */ + /* { dg-warning "also found .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" { target *-*-* } 12 } */ + + return obj; +} diff --git a/gcc/testsuite/objc.dg/method-8.m b/gcc/testsuite/objc.dg/method-8.m new file mode 100644 index 00000000000..4a13b7d6cbb --- /dev/null +++ b/gcc/testsuite/objc.dg/method-8.m @@ -0,0 +1,14 @@ +/* Check if casting the receiver type causes method lookup to succeed. This was broken + in Objective-C++. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +@interface A +@end + +@interface B: A +- (void)f; +@end + +void g(A *p) { [(B *)p f]; } + diff --git a/gcc/testsuite/objc.dg/method-9.m b/gcc/testsuite/objc.dg/method-9.m new file mode 100644 index 00000000000..ba832840062 --- /dev/null +++ b/gcc/testsuite/objc.dg/method-9.m @@ -0,0 +1,43 @@ +/* Check if finding multiple signatures for a method is handled gracefully + when method lookup succeeds (see also method-7.m). */ +/* Contributed by Ziemowit Laski <zlaski@apple.com> */ +/* { dg-do compile } */ + +#include <objc/Object.h> + +@protocol MyObject +- (id)initWithData:(Object *)data; +@end + +@protocol SomeOther +- (id)initWithData:(int)data; +@end + +@protocol MyCoding +- (id)initWithData:(id<MyObject, MyCoding>)data; +@end + +@interface NTGridDataObject: Object <MyCoding> +{ + Object<MyCoding> *_data; +} ++ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data; +@end + +@implementation NTGridDataObject +- (id)initWithData:(id<MyObject, MyCoding>)data { + return data; +} ++ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data +{ + NTGridDataObject *result = [[NTGridDataObject alloc] initWithData:data]; + /* { dg-warning "multiple methods named .\\-initWithData:. found" "" { target *-*-* } 33 } */ + /* { dg-warning "using .\\-\\(id\\)initWithData:\\(Object \\*\\)data." "" { target *-*-* } 9 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(id <MyObject, MyCoding>\\)data." "" { target *-*-* } 17 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(int\\)data." "" { target *-*-* } 13 } */ + + /* The following warning is a consequence of picking the "wrong" method signature. */ + /* { dg-warning "passing arg 1 of .initWithData:. from incompatible pointer type" "" { target *-*-* } 33 } */ + return result; +} +@end diff --git a/gcc/testsuite/objc.dg/missing-proto-1.m b/gcc/testsuite/objc.dg/missing-proto-1.m new file mode 100644 index 00000000000..7132ead4bef --- /dev/null +++ b/gcc/testsuite/objc.dg/missing-proto-1.m @@ -0,0 +1,6 @@ +/* Test for graceful handling of missing protocol declarations. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +@interface Foo <Missing> /* { dg-error "cannot find protocol declaration for .Missing." } */ +@end diff --git a/gcc/testsuite/objc.dg/missing-proto-2.m b/gcc/testsuite/objc.dg/missing-proto-2.m new file mode 100644 index 00000000000..cb121b496e9 --- /dev/null +++ b/gcc/testsuite/objc.dg/missing-proto-2.m @@ -0,0 +1,5 @@ +/* Test for graceful handling of missing protocol declarations. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +void *protRef = @protocol(Missing); /* { dg-error "cannot find protocol declaration for .Missing." } */ diff --git a/gcc/testsuite/objc.dg/missing-proto-3.m b/gcc/testsuite/objc.dg/missing-proto-3.m new file mode 100644 index 00000000000..6c610ce35c9 --- /dev/null +++ b/gcc/testsuite/objc.dg/missing-proto-3.m @@ -0,0 +1,26 @@ +/* Ensure that the compiler gracefully handles missing protocol declarations. + In addition to not crashing :-), the compiler should properly handle + valid protocol references, even when they're mixed with invalid ones. */ +/* { dg-do compile } */ + +#include <objc/objc.h> + +@protocol DefinedProtocol +- (id) missingMethod1; +@end + +@interface MyClass <UndefinedProtocol, DefinedProtocol> +/* { dg-error "cannot find protocol declaration for .UndefinedProtocol." "" { target *-*-* } 12 } */ +@end + +@implementation MyClass ++(Class)class +{ + return self; +} +@end + +/* { dg-warning "incomplete implementation of class .MyClass." "" { target *-*-* } 21 } */ +/* { dg-warning "method definition for .\\-missingMethod1. not found" "" { target *-*-* } 21 } */ +/* { dg-warning "class .MyClass. does not fully implement the .DefinedProtocol. protocol" "" { target *-*-* } 21 } */ + diff --git a/gcc/testsuite/objc.dg/nested-func-1.m b/gcc/testsuite/objc.dg/nested-func-1.m new file mode 100644 index 00000000000..7a182bd938e --- /dev/null +++ b/gcc/testsuite/objc.dg/nested-func-1.m @@ -0,0 +1,37 @@ +/* Test basic nested C function functionality within ObjC + methods. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ +#include <stdio.h> +#include <objc/objc.h> +#include <objc/Object.h> + +int bappy (int (*blargh) (int a, int b, int c)) +{ + return blargh (4, 7, 2) + 3; +} + +@interface Foo: Object ++ (int)foo; +@end + +@implementation Foo ++ (int)foo +{ + int blargh (int a, int b, int c) + { + return a * b + c; + } + return bappy (blargh); +} +@end + +int main () +{ + int f = [Foo foo]; + if (f != 33) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/proto-hier-1.m b/gcc/testsuite/objc.dg/proto-hier-1.m index 17ea72e8db1..154e6b62d73 100644 --- a/gcc/testsuite/objc.dg/proto-hier-1.m +++ b/gcc/testsuite/objc.dg/proto-hier-1.m @@ -48,7 +48,9 @@ int foo(void) { id<Booing, Fooing> stupidVar; [stupidVar boo]; [stupidVar foo]; - [stupidVar anotherMsg]; /* { dg-warning "not implemented by protocol" } */ - /* { dg-warning "return type defaults to id" "" { target *-*-* } 51 } */ + [stupidVar anotherMsg]; /* { dg-warning ".\-anotherMsg. not implemented by protocol" } */ + /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 51 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 51 } */ + /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 51 } */ return 0; } diff --git a/gcc/testsuite/objc.dg/proto-lossage-1.m b/gcc/testsuite/objc.dg/proto-lossage-1.m index d312039262c..1186f8fd9ff 100644 --- a/gcc/testsuite/objc.dg/proto-lossage-1.m +++ b/gcc/testsuite/objc.dg/proto-lossage-1.m @@ -35,7 +35,12 @@ typedef struct objc_object { struct objc_class *class_pointer; } *id; return (id <NSObject>)plate1; /* { dg-bogus "does not conform" } */ } - (int) getValue { - int i = [plate1 someValue]; /* { dg-warning "not implemented by protocol" } */ + int i = [plate1 someValue]; /* { dg-warning ".\\-someValue. not implemented by protocol\\(s\\)" } */ + /* { dg-warning "\\(Messages without a matching method signature" "" { target *-*-* } 38 } */ + /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 38 } */ + /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 38 } */ + /* { dg-warning "initialization makes integer from pointer without a cast" "" { target *-*-* } 38 } */ + int j = [(id <NSObject>)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ int k = [(id)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ return i + j + k; diff --git a/gcc/testsuite/objc.dg/proto-lossage-2.m b/gcc/testsuite/objc.dg/proto-lossage-2.m new file mode 100644 index 00000000000..b3ab9681f62 --- /dev/null +++ b/gcc/testsuite/objc.dg/proto-lossage-2.m @@ -0,0 +1,20 @@ +/* Don't forget to look in protocols if a class (and its superclasses) do not + provide a suitable method. */ +/* { dg-do compile } */ + +#include <objc/Object.h> + +@protocol Zot +-(void) zot; +@end + +@interface Foo : Object <Zot> +@end + +int foo() +{ + Foo *f=nil; + [f zot]; /* There should be no warnings here! */ + return 0; +} + diff --git a/gcc/testsuite/objc.dg/proto-qual-1.m b/gcc/testsuite/objc.dg/proto-qual-1.m new file mode 100644 index 00000000000..6ae12909380 --- /dev/null +++ b/gcc/testsuite/objc.dg/proto-qual-1.m @@ -0,0 +1,48 @@ +/* Check that protocol qualifiers are compiled and encoded properly. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <objc/Protocol.h> +#ifndef __NEXT_RUNTIME__ +#include <objc/objc-api.h> +#endif + +extern int sscanf(const char *str, const char *format, ...); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@protocol Retain ++ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2; +- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2; +@end + +@interface Foo <Retain> ++ (oneway void)retainArgument:(out bycopy id)arg with:(in signed char **)arg2; +@end + +@implementation Foo ++ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2 { } +- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2 { return nil; } +@end + +Protocol *proto = @protocol(Retain); +struct objc_method_description *meth; +unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7; + +static void scan_initial(const char *pattern) { + totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1; + sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6, &offs7); + CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2); +} + +int main(void) { + meth = [proto descriptionForInstanceMethod: @selector(address:with:)]; + scan_initial("O@%u@%u:%uNR@%uo^^S%u"); + CHECK_IF(offs3 == offs2 + sizeof(id) && totsize == offs3 + sizeof(unsigned)); + meth = [proto descriptionForClassMethod: @selector(retainArgument:with:)]; + scan_initial("Vv%u@%u:%uOo@%un^*%u"); + CHECK_IF(offs3 == offs2 + sizeof(id) && totsize == offs3 + sizeof(char **)); + return 0; +} diff --git a/gcc/testsuite/objc.dg/sizeof-1.m b/gcc/testsuite/objc.dg/sizeof-1.m new file mode 100644 index 00000000000..5d8def16afe --- /dev/null +++ b/gcc/testsuite/objc.dg/sizeof-1.m @@ -0,0 +1,33 @@ +/* Check that the sizeof() operator works with ObjC classes and their aliases. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Foo: Object { + int a, b; + float c, d; +} +@end + +@implementation Foo +@end + +typedef Object MyObject; +typedef struct Foo Foo_type; + +@compatibility_alias AliasObject Object; + +int main(void) { + CHECK_IF(sizeof(Foo) > sizeof(Object) && sizeof(Object) > 0); + CHECK_IF(sizeof(Foo) == sizeof(Foo_type)); + CHECK_IF(sizeof(Object) == sizeof(MyObject)); + CHECK_IF(sizeof(Object) == sizeof(AliasObject)); + return 0; +} + diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h index 6c73d28fd17..52586f01521 100644 --- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h +++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h @@ -2,6 +2,11 @@ #include <objc/objc.h> #include <objc/Object.h> +#ifdef __NEXT_RUNTIME__ +#define objc_get_class(C) objc_getClass(C) +#define class_create_instance(C) class_createInstance(C, 0) +#endif + /* Test loading unclaimed categories - categories of a class defined separately from the class itself. */ diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m index 3e521e91248..8b8af5ed307 100644 --- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m +++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m @@ -21,6 +21,9 @@ { return 4; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc.dg/static-1.m b/gcc/testsuite/objc.dg/static-1.m new file mode 100644 index 00000000000..d6201585939 --- /dev/null +++ b/gcc/testsuite/objc.dg/static-1.m @@ -0,0 +1,33 @@ +/* Test out static (non-heap) allocations of ObjC class instances. + These should elicit errors. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +@interface Object { + struct objc_class *isa; +} +@end + +@compatibility_alias MyObject Object; + +@interface Foo: Object { + int a; + Object *b; + Object c; /* { dg-error "statically allocated instance of Objective-C class .Object." } */ +} +@end + +@compatibility_alias MyFoo Foo; + +typedef Foo FooAlias1; +typedef FooAlias1 FooAlias2; +typedef Object ObjectAlias1; +typedef struct Object ObjectAlias2; +Object staticObject1; /* { dg-error "statically allocated instance of Objective-C class .Object." } */ +struct Object staticObject2; /* { dg-error "statically allocated instance of Objective-C class .Object." } */ +static ObjectAlias1 staticObject3; /* { dg-error "statically allocated instance of Objective-C class .Object." } */ +FooAlias1 staticFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */ +extern FooAlias2 externFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */ +static Foo staticFoo2; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */ +MyObject staticMyObject1; /* { dg-error "statically allocated instance of Objective-C class .Object." } */ +MyFoo staticMyFoo1; /* { dg-error "statically allocated instance of Objective-C class .Foo." } */ diff --git a/gcc/testsuite/objc.dg/symtab-1.m b/gcc/testsuite/objc.dg/symtab-1.m new file mode 100644 index 00000000000..44e7b5aab34 --- /dev/null +++ b/gcc/testsuite/objc.dg/symtab-1.m @@ -0,0 +1,24 @@ +/* Check if the objc_symtab descriptor is being laid out correctly. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fnext-runtime" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +#include <objc/Object.h> + +@interface Base: Object +- (void)setValues; +@end + +@interface Derived: Base +- (void)checkValues; +@end + +@implementation Base +-(void)setValues { } +@end + +@implementation Derived +-(void)checkValues { } +@end + +/* { dg-final { scan-assembler "L_OBJC_SYMBOLS:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_CLASS_Derived\n\t.long\tL_OBJC_CLASS_Base\n" } } */ diff --git a/gcc/testsuite/objc.dg/try-catch-1.m b/gcc/testsuite/objc.dg/try-catch-1.m new file mode 100644 index 00000000000..e40fdf85994 --- /dev/null +++ b/gcc/testsuite/objc.dg/try-catch-1.m @@ -0,0 +1,44 @@ +/* Test if the compiler accepts @throw / @try..@catch..@finally + syntax. This will only be usable on MacOS X 10.3 and later. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +#include <objc/objc.h> +#include <objc/objc-runtime.h> +#include <objc/Object.h> +#include <stdio.h> +#include <setjmp.h> + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static int exc_control = 0; + +int proc() { + if(exc_control) { + printf ("Throwing (%d)... ", exc_control); + @throw [Frob new]; + } + return 1; +} + +int foo() +{ + @try { + return proc(); + } + @catch (Frob* ex) { + if(exc_control > 1) { + printf("Rethrowing (%d)... ", exc_control); + @throw; + } + return 0; + } + @finally { + printf("In @finally block (%d)... ", exc_control); + } +} diff --git a/gcc/testsuite/objc.dg/try-catch-2.m b/gcc/testsuite/objc.dg/try-catch-2.m new file mode 100644 index 00000000000..fc314f3f128 --- /dev/null +++ b/gcc/testsuite/objc.dg/try-catch-2.m @@ -0,0 +1,85 @@ +/* Test out '@catch(id foo) {...}', which should catch + all uncaught exceptions. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fobjc-exceptions -lobjc" } */ +/* { dg-do run { target *-*-darwin[789]* } } */ + +#include <objc/objc.h> +#include <objc/objc-runtime.h> +#include <objc/Object.h> +#include <stdio.h> + +/* The following is not required in actual user code; we include it + here to check that the compiler generates an internal definition of + _setjmp that is consistent with what <setjmp.h> provides. */ +#include <setjmp.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static Frob* _connection = nil; + +//-------------------------------------------------------------------- + + +void test (Object* sendPort) +{ + int cleanupPorts = 1; + Frob* receivePort = nil; + + @try { + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + receivePort = (Frob *) -1; + _connection = (Frob *) -1; + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + receivePort = nil; + sendPort = nil; + cleanupPorts = 0; + + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + @throw [Object new]; + } + @catch(Frob *obj) { + printf ("Exception caught by incorrect handler!\n"); + CHECK_IF(0); + } + @catch(id exc) { + printf ("Exception caught by correct handler.\n"); + printf ("receivePort = %p (expected 0x0)\n", receivePort); + printf ("sendPort = %p (expected 0x0)\n", sendPort); + printf ("cleanupPorts = %d (expected 0)\n", cleanupPorts); + printf ("---"); + CHECK_IF(!receivePort); + CHECK_IF(!sendPort); + CHECK_IF(!cleanupPorts); + } + @catch(Object *obj) { /* { dg-warning "Exception already handled by preceding .\\@catch\\(id\\)." } */ + printf ("Exception caught by incorrect handler!\n"); + CHECK_IF(0); + } +} + +int main (void) { + + test((Object *)-1); + return 0; +} diff --git a/gcc/testsuite/objc.dg/try-catch-3.m b/gcc/testsuite/objc.dg/try-catch-3.m new file mode 100644 index 00000000000..f49362fbf31 --- /dev/null +++ b/gcc/testsuite/objc.dg/try-catch-3.m @@ -0,0 +1,19 @@ +/* Test if caught exception objects are accessible inside the + @catch block. (Yes, I managed to break this.) */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-fobjc-exceptions" } */ + +#include <objc/Object.h> + +const char *foo(void) +{ + @try { + return "foo"; + } + @catch (Object* theException) { + return [theException name]; + } +} + diff --git a/gcc/testsuite/objc.dg/try-catch-4.m b/gcc/testsuite/objc.dg/try-catch-4.m new file mode 100644 index 00000000000..54aea233fed --- /dev/null +++ b/gcc/testsuite/objc.dg/try-catch-4.m @@ -0,0 +1,26 @@ +/* Check that the compiler does not incorrectly complain about + exceptions being caught by previous @catch blocks. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-Wall -fobjc-exceptions" } */ + +@interface Exception +@end + +@interface FooException : Exception +@end + +extern void foo(); + +void test() +{ + @try { + foo(); + } + @catch (FooException* fe) { + } + @catch (Exception* e) { + } +} + diff --git a/gcc/testsuite/objc.dg/type-size-1.m b/gcc/testsuite/objc.dg/type-size-1.m new file mode 100644 index 00000000000..f2fdae5c382 --- /dev/null +++ b/gcc/testsuite/objc.dg/type-size-1.m @@ -0,0 +1,17 @@ +/* Reject ivars with an unknown size. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do compile } */ + +struct unknownStruct; + +@interface ArrayTest +{ + short unknownSize[unknownValue]; /* { dg-error ".unknownValue. (undeclared|was not declared)" } */ + /* { dg-error "instance variable .unknownSize. has unknown size" "" { target *-*-* } 9 } */ + struct unknownStruct unknownObj; /* { dg-error "field .unknownObj. has incomplete type" } */ + /* { dg-error "instance variable .unknownObj. has unknown size" "" { target *-*-* } 11 } */ + long knownSize[3]; /* ok */ + char zeroSize[2 - 2]; /* ok (apparently) */ + int missingSize[]; /* { dg-error "instance variable .missingSize. has unknown size" } */ +} +@end diff --git a/gcc/testsuite/objc.dg/type-size-2.m b/gcc/testsuite/objc.dg/type-size-2.m new file mode 100644 index 00000000000..446de48345a --- /dev/null +++ b/gcc/testsuite/objc.dg/type-size-2.m @@ -0,0 +1,58 @@ +/* Make sure that array arguments to methods are given the size of pointers. */ +/* As in the case of ivars, arrays without size (e.g., 'int []') are + encoded as pointers as well. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-do run } */ + +#include <objc/objc.h> +#ifdef __NEXT_RUNTIME__ +#include <objc/objc-runtime.h> +#define OBJC_GETCLASS objc_getClass +#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod +#else +#include <objc/objc-api.h> +#define OBJC_GETCLASS objc_get_class +#define CLASS_GETINSTANCEMETHOD class_get_instance_method +#endif + +extern int sscanf(const char *str, const char *format, ...); +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +enum Enum { one, two, three, four }; + +@interface ArrayTest +- (const char *)str:(signed char [])arg1 with:(unsigned char *)arg2 and:(enum Enum[4])en; +- (int)meth1:(int [])arg1 with:(int [0])arg2 with:(int [2])arg3; +@end + +@implementation ArrayTest +- (int)meth1:(int [])arg1 with:(int [0])arg2 with:(int [2])arg3 { return 0; } +- (const char *)str:(signed char [])arg1 with:(unsigned char *)arg2 and:(enum Enum[4])en { return "str"; } +@end + +Class cls; +struct objc_method *meth; +unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7; + +static void scan_initial(const char *pattern) { + totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1; + sscanf(meth->method_types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6, &offs7); + CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2); +} + +int main(void) { + cls = OBJC_GETCLASS("ArrayTest"); + + meth = CLASS_GETINSTANCEMETHOD(cls, @selector(str:with:and:)); + scan_initial("r*%u@%u:%u*%u*%u[4i]%u"); + CHECK_IF(offs3 == offs2 + sizeof(signed char *) && offs4 == offs3 + sizeof(unsigned char *)); + CHECK_IF(totsize == offs4 + sizeof(enum Enum *)); + meth = CLASS_GETINSTANCEMETHOD(cls, @selector(meth1:with:with:)); + scan_initial("i%u@%u:%u^i%u[0i]%u[2i]%u"); + CHECK_IF(offs3 == offs2 + sizeof(int *) && offs4 == offs3 + sizeof(int *)); + CHECK_IF(totsize == offs4 + sizeof(int *)); + return 0; +} + diff --git a/gcc/testsuite/objc.dg/zero-link-1.m b/gcc/testsuite/objc.dg/zero-link-1.m new file mode 100644 index 00000000000..96fd0c290d3 --- /dev/null +++ b/gcc/testsuite/objc.dg/zero-link-1.m @@ -0,0 +1,28 @@ +/* Check if the '-fzero-link' flag correctly emits an objc_getClass() call. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fnext-runtime -fzero-link" } */ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object ++ (int) getValue; +@end + +@implementation Base ++ (int) getValue { return 1593; } +@end + +int main(void) { + int val = [Base getValue]; + CHECK_IF(val == 1593); + return 0; +} + +/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_0" } } */ +/* { dg-final { scan-assembler "objc_getClass" } } */ + diff --git a/gcc/testsuite/objc.dg/zero-link-2.m b/gcc/testsuite/objc.dg/zero-link-2.m new file mode 100644 index 00000000000..92b4ab11b0c --- /dev/null +++ b/gcc/testsuite/objc.dg/zero-link-2.m @@ -0,0 +1,28 @@ +/* Check if the '-fno-zero-link' flag correctly _omits_ an objc_getClass() call. */ +/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ +/* { dg-options "-fnext-runtime -fno-zero-link" } */ +/* { dg-do compile } */ + +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object ++ (int) getValue; +@end + +@implementation Base ++ (int) getValue { return 1593; } +@end + +int main(void) { + int val = [Base getValue]; + CHECK_IF(val == 1593); + return 0; +} + +/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */ +/* { dg-final { scan-assembler-not "objc_getClass" } } */ + diff --git a/gcc/testsuite/objc/execute/IMP.m b/gcc/testsuite/objc/execute/IMP.m index 979aebb0158..99f61933926 100644 --- a/gcc/testsuite/objc/execute/IMP.m +++ b/gcc/testsuite/objc/execute/IMP.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Test getting and calling the IMP of a method */ @interface TestClass diff --git a/gcc/testsuite/objc/execute/_cmd.m b/gcc/testsuite/objc/execute/_cmd.m index 20203b51711..f2b05b6527b 100644 --- a/gcc/testsuite/objc/execute/_cmd.m +++ b/gcc/testsuite/objc/execute/_cmd.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Test the hidden argument _cmd to method calls */ @interface TestClass @@ -16,6 +18,9 @@ { return sel_get_name (_cmd); } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc/execute/bf-common.h b/gcc/testsuite/objc/execute/bf-common.h index 123a45413d0..6cf7a0696b6 100644 --- a/gcc/testsuite/objc/execute/bf-common.h +++ b/gcc/testsuite/objc/execute/bf-common.h @@ -1,5 +1,7 @@ +#ifndef __NEXT_RUNTIME__ #include <objc/encoding.h> - +#endif +#include "next_mapping.h" void print_ivars (Class class) { @@ -59,7 +61,7 @@ int main () @defs (MyObject); }; int size1, size2; - Class class = [MyObject class]; + Class class = objc_get_class ("MyObject"); printf ("type = %s\n", @encode (struct class_vars)); print_ivars (class); diff --git a/gcc/testsuite/objc/execute/bycopy-3.m b/gcc/testsuite/objc/execute/bycopy-3.m index 9c7c0acbadb..60acde52b59 100644 --- a/gcc/testsuite/objc/execute/bycopy-3.m +++ b/gcc/testsuite/objc/execute/bycopy-3.m @@ -12,7 +12,11 @@ #include <objc/objc.h> #include <objc/Object.h> #include <objc/Protocol.h> + +#ifndef __NEXT_RUNTIME__ #include <objc/encoding.h> +#endif +#include "next_mapping.h" @protocol MyProtocol + (bycopy id<MyProtocol>) bycopyMethod; diff --git a/gcc/testsuite/objc/execute/cascading-1.m b/gcc/testsuite/objc/execute/cascading-1.m new file mode 100644 index 00000000000..67988a5db2a --- /dev/null +++ b/gcc/testsuite/objc/execute/cascading-1.m @@ -0,0 +1,33 @@ +#include <objc/Object.h> + +@interface Foo : Object ++ foo; ++ bar; +@end + +int foocalled = 0; +int barcalled = 0; + + +@implementation Foo ++ foo +{ + if (foocalled) + abort (); + foocalled = 1; + return self; +} ++ bar +{ + if (barcalled) + abort (); + barcalled = 1; + return self; +} +@end + +int main(int argc,char **argv) +{ + [[Foo foo] bar]; + return 0; +} diff --git a/gcc/testsuite/objc/execute/class-1.m b/gcc/testsuite/objc/execute/class-1.m index a28cfc3abb8..5fd9aa8e038 100644 --- a/gcc/testsuite/objc/execute/class-1.m +++ b/gcc/testsuite/objc/execute/class-1.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a RootClass */ @interface RootClass diff --git a/gcc/testsuite/objc/execute/class-10.m b/gcc/testsuite/objc/execute/class-10.m index 3d9697c0d86..d984d62ac99 100644 --- a/gcc/testsuite/objc/execute/class-10.m +++ b/gcc/testsuite/objc/execute/class-10.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation, and using self to call another method of itself */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-11.m b/gcc/testsuite/objc/execute/class-11.m index 902db2b9a33..00c488bd1b9 100644 --- a/gcc/testsuite/objc/execute/class-11.m +++ b/gcc/testsuite/objc/execute/class-11.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation and using self to call another method of itself - in @@ -14,6 +16,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-12.m b/gcc/testsuite/objc/execute/class-12.m index e65611df06b..fcab65b2d36 100644 --- a/gcc/testsuite/objc/execute/class-12.m +++ b/gcc/testsuite/objc/execute/class-12.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with a class methods */ @interface RootClass @@ -11,6 +13,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end static int class_variable = 0; diff --git a/gcc/testsuite/objc/execute/class-13.m b/gcc/testsuite/objc/execute/class-13.m index 0d87afd9508..98cf0ccd729 100644 --- a/gcc/testsuite/objc/execute/class-13.m +++ b/gcc/testsuite/objc/execute/class-13.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with a class accessor methods and a subclass overriding the superclass' implementation but reusing it with super */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end static int class_variable = 0; diff --git a/gcc/testsuite/objc/execute/class-14.m b/gcc/testsuite/objc/execute/class-14.m index 2827031358c..7d02c36df7a 100644 --- a/gcc/testsuite/objc/execute/class-14.m +++ b/gcc/testsuite/objc/execute/class-14.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with a class accessor methods and a subclass overriding the superclass' implementation, and using self to call another method of itself */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end static int class_variable = 0; diff --git a/gcc/testsuite/objc/execute/class-2.m b/gcc/testsuite/objc/execute/class-2.m index cb8b47fa1a3..350a583e9b5 100644 --- a/gcc/testsuite/objc/execute/class-2.m +++ b/gcc/testsuite/objc/execute/class-2.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass */ @interface RootClass diff --git a/gcc/testsuite/objc/execute/class-3.m b/gcc/testsuite/objc/execute/class-3.m index dbe68bf9037..5ce83376c46 100644 --- a/gcc/testsuite/objc/execute/class-3.m +++ b/gcc/testsuite/objc/execute/class-3.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a minimal subclass tree */ @interface RootClass diff --git a/gcc/testsuite/objc/execute/class-4.m b/gcc/testsuite/objc/execute/class-4.m index 0ae723c035b..34d414b1229 100644 --- a/gcc/testsuite/objc/execute/class-4.m +++ b/gcc/testsuite/objc/execute/class-4.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods */ @@ -12,6 +14,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-5.m b/gcc/testsuite/objc/execute/class-5.m index 5d5297f6247..e2b750ac01d 100644 --- a/gcc/testsuite/objc/execute/class-5.m +++ b/gcc/testsuite/objc/execute/class-5.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-6.m b/gcc/testsuite/objc/execute/class-6.m index f60912aa608..fb2d64b4314 100644 --- a/gcc/testsuite/objc/execute/class-6.m +++ b/gcc/testsuite/objc/execute/class-6.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation but reusing it with super */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-7.m b/gcc/testsuite/objc/execute/class-7.m index 9a2fe0cff41..3fddca77065 100644 --- a/gcc/testsuite/objc/execute/class-7.m +++ b/gcc/testsuite/objc/execute/class-7.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods; accessor methods implemented in a separate category */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass @@ -49,6 +54,13 @@ int main (void) SubClass *object; test_class_with_superclass ("SubClass", "RootClass"); + + /* The NeXT runtime's category implementation is lazy: categories are not attached + to classes until the class is initialized (at +initialize time). */ +#ifdef __NEXT_RUNTIME__ + [SubClass initialize]; +#endif + test_that_class_has_instance_method ("SubClass", @selector (setState:)); test_that_class_has_instance_method ("SubClass", @selector (state)); diff --git a/gcc/testsuite/objc/execute/class-8.m b/gcc/testsuite/objc/execute/class-8.m index fa111850213..806db03687c 100644 --- a/gcc/testsuite/objc/execute/class-8.m +++ b/gcc/testsuite/objc/execute/class-8.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation - in a category */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-9.m b/gcc/testsuite/objc/execute/class-9.m index bb405fbc982..d32362bdd57 100644 --- a/gcc/testsuite/objc/execute/class-9.m +++ b/gcc/testsuite/objc/execute/class-9.m @@ -2,6 +2,8 @@ #include <objc/objc.h> #include <objc/objc-api.h> +#include "next_mapping.h" + /* Tests creating a root class and a subclass with an ivar and accessor methods and a subclass overriding the superclass' implementation but reusing it with super - in a category */ @@ -13,6 +15,9 @@ @end @implementation RootClass +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface SubClass : RootClass diff --git a/gcc/testsuite/objc/execute/class-tests-2.h b/gcc/testsuite/objc/execute/class-tests-2.h index 6df91df2b6e..cc14abb4343 100644 --- a/gcc/testsuite/objc/execute/class-tests-2.h +++ b/gcc/testsuite/objc/execute/class-tests-2.h @@ -62,6 +62,6 @@ void test_accessor_method (TYPE_OF_OBJECT_WITH_ACCESSOR_METHOD object, abort (); } } -#endif CLASS_WITH_ACCESSOR_METHOD +#endif /* CLASS_WITH_ACCESSOR_METHOD */ diff --git a/gcc/testsuite/objc/execute/class_self-1.m b/gcc/testsuite/objc/execute/class_self-1.m index 4d4251628ea..1690f8f6bbc 100644 --- a/gcc/testsuite/objc/execute/class_self-1.m +++ b/gcc/testsuite/objc/execute/class_self-1.m @@ -51,6 +51,9 @@ struct d { return 4; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc/execute/class_self-2.m b/gcc/testsuite/objc/execute/class_self-2.m index e64fcf9fff4..7fa54906cce 100644 --- a/gcc/testsuite/objc/execute/class_self-2.m +++ b/gcc/testsuite/objc/execute/class_self-2.m @@ -32,6 +32,9 @@ struct d return u; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end /* The second class */ @@ -54,6 +57,9 @@ struct d } } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc/execute/function-message-1.m b/gcc/testsuite/objc/execute/function-message-1.m new file mode 100644 index 00000000000..2c8c002d9e8 --- /dev/null +++ b/gcc/testsuite/objc/execute/function-message-1.m @@ -0,0 +1,33 @@ +#include <objc/Object.h> + +@interface Foo : Object ++ bar; +@end + +int foocalled = 0; +int barcalled = 0; + + +id foo() +{ + if (foocalled) + abort (); + foocalled = 1; + return [Foo class]; +} + +@implementation Foo ++ bar +{ + if (barcalled) + abort (); + barcalled = 1; + return self; +} +@end + +int main(int argc,char **argv) +{ + [foo() bar]; + return 0; +} diff --git a/gcc/testsuite/objc/execute/many_args_method.m b/gcc/testsuite/objc/execute/many_args_method.m index d811082cb86..6cc2e2535ed 100644 --- a/gcc/testsuite/objc/execute/many_args_method.m +++ b/gcc/testsuite/objc/execute/many_args_method.m @@ -30,6 +30,9 @@ { return [self sumInteger: a withInteger: b withInteger: c]; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc/execute/nested-3.m b/gcc/testsuite/objc/execute/nested-3.m index 94271c4e4c0..5462fd5ef7a 100644 --- a/gcc/testsuite/objc/execute/nested-3.m +++ b/gcc/testsuite/objc/execute/nested-3.m @@ -22,6 +22,9 @@ return test (); } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end int main (void) diff --git a/gcc/testsuite/objc/execute/next_mapping.h b/gcc/testsuite/objc/execute/next_mapping.h new file mode 100644 index 00000000000..67c2ce34257 --- /dev/null +++ b/gcc/testsuite/objc/execute/next_mapping.h @@ -0,0 +1,851 @@ +/* This file "renames" various ObjC GNU runtime entry points + (and fakes the existence of several others) + if the NeXT runtime is being used. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +#ifdef __NEXT_RUNTIME__ +#include <objc/objc-class.h> +#include <ctype.h> + +#define objc_get_class(C) objc_getClass(C) +#define objc_get_meta_class(C) objc_getMetaClass(C) +#define class_get_class_method(C, S) class_getClassMethod(C, S) +#define class_get_instance_method(C, S) class_getInstanceMethod(C, S) +#define method_get_imp(M) (((Method)M)->method_imp) +#define sel_get_name(S) sel_getName(S) +#define class_create_instance(C) class_createInstance(C, 0) +#define class_get_class_name(C) object_getClassName(C) +#define class_get_super_class(C) (((struct objc_class *)C)->super_class) +#define object_get_super_class(O) class_get_super_class(*(struct objc_class **)O) +#define objc_lookup_class(N) objc_lookUpClass(N) +#define object_get_class(O) (*(struct objc_class **)O) +#define class_is_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_CLASS)? YES: NO) +#define class_is_meta_class(C) (CLS_GETINFO((struct objc_class *)C, CLS_META)? YES: NO) +#define object_is_class(O) class_is_meta_class(*(struct objc_class **)O) +#define object_is_meta_class(O) (class_is_meta_class(O) && class_is_meta_class(*(struct objc_class **)O)) + +/* You need either an empty +initialize method or an empty -forward:: method. + The NeXT runtime unconditionally sends +initialize to classes when they are + first used, and unconditionally tries to forward methods that the class + doesn't understand (including +initialize). If you have neither +initialize + nor -forward::, the runtime complains. + + The simplest workaround is to add + + + initialize { return self; } + + to every root class @implementation. */ + +#ifndef NULL +#define NULL 0 +#endif + +/* The following is necessary to "cover" the bf*.m test cases on NeXT. */ + +#undef MAX +#define MAX(X, Y) \ + ({ typeof (X) __x = (X), __y = (Y); \ + (__x > __y ? __x : __y); }) + +#undef MIN +#define MIN(X, Y) \ + ({ typeof (X) __x = (X), __y = (Y); \ + (__x < __y ? __x : __y); }) + +#undef ROUND +#define ROUND(V, A) \ + ({ typeof (V) __v = (V); typeof (A) __a = (A); \ + __a * ((__v+__a - 1)/__a); }) + +#define BITS_PER_UNIT __CHAR_BIT__ +#define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;})) + +/* Not sure why the following are missing from NeXT objc headers... */ + +#ifndef _C_LNG_LNG +#define _C_LNG_LNG 'q' +#endif +#ifndef _C_ULNG_LNG +#define _C_ULNG_LNG 'Q' +#endif +#ifndef _C_ATOM +#define _C_ATOM '%' +#endif +#ifndef _C_BOOL +#define _C_BOOL 'B' +#endif + +#define _C_CONST 'r' +#define _C_IN 'n' +#define _C_INOUT 'N' +#define _C_OUT 'o' +#define _C_BYCOPY 'O' +#define _C_BYREF 'R' +#define _C_ONEWAY 'V' +#define _C_GCINVISIBLE '!' + +#define _F_CONST 0x01 +#define _F_IN 0x01 +#define _F_OUT 0x02 +#define _F_INOUT 0x03 +#define _F_BYCOPY 0x04 +#define _F_BYREF 0x08 +#define _F_ONEWAY 0x10 +#define _F_GCINVISIBLE 0x20 + +struct objc_struct_layout +{ + const char *original_type; + const char *type; + const char *prev_type; + unsigned int record_size; + unsigned int record_align; +}; + +typedef union { + char *arg_ptr; + char arg_regs[sizeof (char*)]; +} *arglist_t; /* argument frame */ + +const char *objc_skip_typespec (const char *type); +void objc_layout_structure_get_info (struct objc_struct_layout *layout, + unsigned int *offset, unsigned int *align, const char **type); +void objc_layout_structure (const char *type, + struct objc_struct_layout *layout); +BOOL objc_layout_structure_next_member (struct objc_struct_layout *layout); +void objc_layout_finish_structure (struct objc_struct_layout *layout, + unsigned int *size, unsigned int *align); + +/* + return the size of an object specified by type +*/ + +int +objc_sizeof_type (const char *type) +{ + /* Skip the variable name if any */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + + switch (*type) { + case _C_ID: + return sizeof (id); + break; + + case _C_CLASS: + return sizeof (Class); + break; + + case _C_SEL: + return sizeof (SEL); + break; + + case _C_CHR: + return sizeof (char); + break; + + case _C_UCHR: + return sizeof (unsigned char); + break; + + case _C_SHT: + return sizeof (short); + break; + + case _C_USHT: + return sizeof (unsigned short); + break; + + case _C_INT: + return sizeof (int); + break; + + case _C_UINT: + return sizeof (unsigned int); + break; + + case _C_LNG: + return sizeof (long); + break; + + case _C_ULNG: + return sizeof (unsigned long); + break; + + case _C_LNG_LNG: + return sizeof (long long); + break; + + case _C_ULNG_LNG: + return sizeof (unsigned long long); + break; + + case _C_FLT: + return sizeof (float); + break; + + case _C_DBL: + return sizeof (double); + break; + + case _C_VOID: + return sizeof (void); + break; + + case _C_PTR: + case _C_ATOM: + case _C_CHARPTR: + return sizeof (char *); + break; + + case _C_ARY_B: + { + int len = atoi (type + 1); + while (isdigit ((unsigned char)*++type)) + ; + return len * objc_aligned_size (type); + } + break; + + case _C_BFLD: + { + /* The NeXT encoding of bitfields is _still_: b 'size' */ + int size = atoi (type + 1); + /* Return an upper bound on byte size */ + return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; + } + + case _C_STRUCT_B: + { + struct objc_struct_layout layout; + unsigned int size; + + objc_layout_structure (type, &layout); + while (objc_layout_structure_next_member (&layout)) + /* do nothing */ ; + objc_layout_finish_structure (&layout, &size, NULL); + + return size; + } + + case _C_UNION_B: + { + int max_size = 0; + while (*type != _C_UNION_E && *type++ != '=') + /* do nothing */; + while (*type != _C_UNION_E) + { + /* Skip the variable name if any */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + max_size = MAX (max_size, objc_sizeof_type (type)); + type = objc_skip_typespec (type); + } + return max_size; + } + } + return 0; /* error */ +} + + +/* + Return the alignment of an object specified by type +*/ + +int +objc_alignof_type (const char *type) +{ + /* Skip the variable name if any */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + switch (*type) { + case _C_ID: + return __alignof__ (id); + break; + + case _C_CLASS: + return __alignof__ (Class); + break; + + case _C_SEL: + return __alignof__ (SEL); + break; + + case _C_CHR: + return __alignof__ (char); + break; + + case _C_UCHR: + return __alignof__ (unsigned char); + break; + + case _C_SHT: + return __alignof__ (short); + break; + + case _C_USHT: + return __alignof__ (unsigned short); + break; + + case _C_INT: + case _C_BFLD: /* This is for the NeXT only */ + return __alignof__ (int); + break; + + case _C_UINT: + return __alignof__ (unsigned int); + break; + + case _C_LNG: + return __alignof__ (long); + break; + + case _C_ULNG: + return __alignof__ (unsigned long); + break; + + case _C_LNG_LNG: + return __alignof__ (long long); + break; + + case _C_ULNG_LNG: + return __alignof__ (unsigned long long); + break; + + case _C_FLT: + return __alignof__ (float); + break; + + case _C_DBL: + return __alignof__ (double); + break; + + case _C_PTR: + case _C_ATOM: + case _C_CHARPTR: + return __alignof__ (char *); + break; + + case _C_ARY_B: + while (isdigit ((unsigned char)*++type)) + /* do nothing */; + return objc_alignof_type (type); + + case _C_STRUCT_B: + { + struct objc_struct_layout layout; + unsigned int align; + + objc_layout_structure (type, &layout); + while (objc_layout_structure_next_member (&layout)) + /* do nothing */; + objc_layout_finish_structure (&layout, NULL, &align); + + return align; + } + + case _C_UNION_B: + { + int maxalign = 0; + while (*type != _C_UNION_E && *type++ != '=') + /* do nothing */; + while (*type != _C_UNION_E) + { + /* Skip the variable name if any */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + maxalign = MAX (maxalign, objc_alignof_type (type)); + type = objc_skip_typespec (type); + } + return maxalign; + } + } + return 0; /* error */ +} + +/* + The aligned size if the size rounded up to the nearest alignment. +*/ + +int +objc_aligned_size (const char *type) +{ + int size, align; + + /* Skip the variable name */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + + size = objc_sizeof_type (type); + align = objc_alignof_type (type); + + return ROUND (size, align); +} + +/* + The size rounded up to the nearest integral of the wordsize, taken + to be the size of a void *. +*/ + +int +objc_promoted_size (const char *type) +{ + int size, wordsize; + + /* Skip the variable name */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + + size = objc_sizeof_type (type); + wordsize = sizeof (void *); + + return ROUND (size, wordsize); +} + +/* + Skip type qualifiers. These may eventually precede typespecs + occurring in method prototype encodings. +*/ + +inline const char * +objc_skip_type_qualifiers (const char *type) +{ + while (*type == _C_CONST + || *type == _C_IN + || *type == _C_INOUT + || *type == _C_OUT + || *type == _C_BYCOPY + || *type == _C_BYREF + || *type == _C_ONEWAY + || *type == _C_GCINVISIBLE) + { + type += 1; + } + return type; +} + + +/* + Skip one typespec element. If the typespec is prepended by type + qualifiers, these are skipped as well. +*/ + +const char * +objc_skip_typespec (const char *type) +{ + /* Skip the variable name if any */ + if (*type == '"') + { + for (type++; *type++ != '"';) + /* do nothing */; + } + + type = objc_skip_type_qualifiers (type); + + switch (*type) { + + case _C_ID: + /* An id may be annotated by the actual type if it is known + with the @"ClassName" syntax */ + + if (*++type != '"') + return type; + else + { + while (*++type != '"') + /* do nothing */; + return type + 1; + } + + /* The following are one character type codes */ + case _C_CLASS: + case _C_SEL: + case _C_CHR: + case _C_UCHR: + case _C_CHARPTR: + case _C_ATOM: + case _C_SHT: + case _C_USHT: + case _C_INT: + case _C_UINT: + case _C_LNG: + case _C_ULNG: + case _C_LNG_LNG: + case _C_ULNG_LNG: + case _C_FLT: + case _C_DBL: + case _C_VOID: + case _C_UNDEF: + return ++type; + break; + + case _C_ARY_B: + /* skip digits, typespec and closing ']' */ + + while (isdigit ((unsigned char)*++type)) + ; + type = objc_skip_typespec (type); + if (*type == _C_ARY_E) + return ++type; + else + break; /* error */ + + case _C_BFLD: + /* The NeXT encoding for bitfields is _still_: b 'size' */ + while (isdigit ((unsigned char)*++type)) + ; /* skip type and size */ + return type; + + case _C_STRUCT_B: + /* skip name, and elements until closing '}' */ + + while (*type != _C_STRUCT_E && *type++ != '=') + ; + while (*type != _C_STRUCT_E) + { + type = objc_skip_typespec (type); + } + return ++type; + + case _C_UNION_B: + /* skip name, and elements until closing ')' */ + + while (*type != _C_UNION_E && *type++ != '=') + ; + while (*type != _C_UNION_E) + { + type = objc_skip_typespec (type); + } + return ++type; + + case _C_PTR: + /* Just skip the following typespec */ + + return objc_skip_typespec (++type); + } + return 0; /* error */ +} + +/* + Skip an offset as part of a method encoding. This is prepended by a + '+' if the argument is passed in registers. +*/ +inline const char * +objc_skip_offset (const char *type) +{ + if (*type == '+') + type++; + while (isdigit ((unsigned char) *++type)) + ; + return type; +} + +/* + Skip an argument specification of a method encoding. +*/ +const char * +objc_skip_argspec (const char *type) +{ + type = objc_skip_typespec (type); + type = objc_skip_offset (type); + return type; +} + +/* + Return the number of arguments that the method MTH expects. + Note that all methods need two implicit arguments `self' and + `_cmd'. +*/ +int +method_get_number_of_arguments (struct objc_method *mth) +{ + int i = 0; + const char *type = mth->method_types; + while (*type) + { + type = objc_skip_argspec (type); + i += 1; + } + return i - 1; +} + +/* + Return the size of the argument block needed on the stack to invoke + the method MTH. This may be zero, if all arguments are passed in + registers. +*/ + +int +method_get_sizeof_arguments (struct objc_method *mth) +{ + const char *type = objc_skip_typespec (mth->method_types); + return atoi (type); +} + +/* + Return a pointer to the next argument of ARGFRAME. type points to + the last argument. Typical use of this look like: + + { + char *datum, *type; + for (datum = method_get_first_argument (method, argframe, &type); + datum; datum = method_get_next_argument (argframe, &type)) + { + unsigned flags = objc_get_type_qualifiers (type); + type = objc_skip_type_qualifiers (type); + if (*type != _C_PTR) + [portal encodeData: datum ofType: type]; + else + { + if ((flags & _F_IN) == _F_IN) + [portal encodeData: *(char **) datum ofType: ++type]; + } + } + } +*/ + +char * +method_get_next_argument (arglist_t argframe, const char **type) +{ + const char *t = objc_skip_argspec (*type); + + if (*t == '\0') + return 0; + + *type = t; + t = objc_skip_typespec (t); + + if (*t == '+') + return argframe->arg_regs + atoi (++t); + else + return argframe->arg_ptr + atoi (t); +} + +/* + Return a pointer to the value of the first argument of the method + described in M with the given argumentframe ARGFRAME. The type + is returned in TYPE. type must be passed to successive calls of + method_get_next_argument. +*/ +char * +method_get_first_argument (struct objc_method *m, + arglist_t argframe, + const char **type) +{ + *type = m->method_types; + return method_get_next_argument (argframe, type); +} + +/* + Return a pointer to the ARGth argument of the method + M from the frame ARGFRAME. The type of the argument + is returned in the value-result argument TYPE +*/ + +char * +method_get_nth_argument (struct objc_method *m, + arglist_t argframe, int arg, + const char **type) +{ + const char *t = objc_skip_argspec (m->method_types); + + if (arg > method_get_number_of_arguments (m)) + return 0; + + while (arg--) + t = objc_skip_argspec (t); + + *type = t; + t = objc_skip_typespec (t); + + if (*t == '+') + return argframe->arg_regs + atoi (++t); + else + return argframe->arg_ptr + atoi (t); +} + +unsigned +objc_get_type_qualifiers (const char *type) +{ + unsigned res = 0; + BOOL flag = YES; + + while (flag) + switch (*type++) + { + case _C_CONST: res |= _F_CONST; break; + case _C_IN: res |= _F_IN; break; + case _C_INOUT: res |= _F_INOUT; break; + case _C_OUT: res |= _F_OUT; break; + case _C_BYCOPY: res |= _F_BYCOPY; break; + case _C_BYREF: res |= _F_BYREF; break; + case _C_ONEWAY: res |= _F_ONEWAY; break; + case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break; + default: flag = NO; + } + + return res; +} + + +/* The following three functions can be used to determine how a + structure is laid out by the compiler. For example: + + struct objc_struct_layout layout; + int i; + + objc_layout_structure (type, &layout); + while (objc_layout_structure_next_member (&layout)) + { + int position, align; + const char *type; + + objc_layout_structure_get_info (&layout, &position, &align, &type); + printf ("element %d has offset %d, alignment %d\n", + i++, position, align); + } + + These functions are used by objc_sizeof_type and objc_alignof_type + functions to compute the size and alignment of structures. The + previous method of computing the size and alignment of a structure + was not working on some architectures, particulary on AIX, and in + the presence of bitfields inside the structure. */ +void +objc_layout_structure (const char *type, + struct objc_struct_layout *layout) +{ + const char *ntype; + + layout->original_type = ++type; + + /* Skip "<name>=" if any. Avoid embedded structures and unions. */ + ntype = type; + while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B + && *ntype++ != '=') + /* do nothing */; + + /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */ + if (*(ntype - 1) == '=') + type = ntype; + + layout->type = type; + layout->prev_type = NULL; + layout->record_size = 0; + layout->record_align = MAX (BITS_PER_UNIT, STRUCTURE_SIZE_BOUNDARY); +} + + +BOOL +objc_layout_structure_next_member (struct objc_struct_layout *layout) +{ + register int desired_align = 0; + + /* The current type without the type qualifiers */ + const char *type; + + /* Add the size of the previous field to the size of the record. */ + if (layout->prev_type) + { + type = objc_skip_type_qualifiers (layout->prev_type); + + if (*type != _C_BFLD) + layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT; + else + layout->record_size += atoi (++type); + } + + if (*layout->type == _C_STRUCT_E) + return NO; + + /* Skip the variable name if any */ + if (*layout->type == '"') + { + for (layout->type++; *layout->type++ != '"';) + /* do nothing */; + } + + type = objc_skip_type_qualifiers (layout->type); + + desired_align = objc_alignof_type (type) * BITS_PER_UNIT; + + /* Record must have at least as much alignment as any field. + Otherwise, the alignment of the field within the record + is meaningless. */ + layout->record_align = MAX (layout->record_align, desired_align); + + if (*type == _C_BFLD) + { + int bfld_size = atoi (++type); + int int_align = __alignof__ (int) * BITS_PER_UNIT; + /* If this bitfield would traverse a word alignment boundary, push it out + to that boundary instead. */ + if (layout->record_size % int_align + && (layout->record_size / int_align + < (layout->record_size + bfld_size - 1) / int_align)) + layout->record_size = ROUND (layout->record_size, int_align); + } + else if (layout->record_size % desired_align != 0) + { + /* We need to skip space before this field. + Bump the cumulative size to multiple of field alignment. */ + layout->record_size = ROUND (layout->record_size, desired_align); + } + + /* Jump to the next field in record. */ + + layout->prev_type = layout->type; + layout->type = objc_skip_typespec (layout->type); /* skip component */ + + return YES; +} + + +void objc_layout_finish_structure (struct objc_struct_layout *layout, + unsigned int *size, + unsigned int *align) +{ + if (layout->type && *layout->type == _C_STRUCT_E) + { + /* Round the size up to be a multiple of the required alignment */ + layout->record_size = ROUND (layout->record_size, layout->record_align); + layout->type = NULL; + } + if (size) + *size = layout->record_size / BITS_PER_UNIT; + if (align) + *align = layout->record_align / BITS_PER_UNIT; +} + + +void objc_layout_structure_get_info (struct objc_struct_layout *layout, + unsigned int *offset, + unsigned int *align, + const char **type) +{ + if (offset) + *offset = layout->record_size / BITS_PER_UNIT; + if (align) + *align = layout->record_align / BITS_PER_UNIT; + if (type) + *type = layout->prev_type; +} + +#endif /* #ifdef __NEXT_RUNTIME__ */ diff --git a/gcc/testsuite/objc/execute/np-2.m b/gcc/testsuite/objc/execute/np-2.m index 37cf6ddd436..85aa203ca5c 100644 --- a/gcc/testsuite/objc/execute/np-2.m +++ b/gcc/testsuite/objc/execute/np-2.m @@ -17,6 +17,9 @@ { printf ("methodA\n"); } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end int main (void) diff --git a/gcc/testsuite/objc/execute/object_is_class.m b/gcc/testsuite/objc/execute/object_is_class.m index a053434fb14..87deb986497 100644 --- a/gcc/testsuite/objc/execute/object_is_class.m +++ b/gcc/testsuite/objc/execute/object_is_class.m @@ -3,6 +3,8 @@ #include <objc/objc-api.h> #include <objc/Object.h> +#include "next_mapping.h" + /* This test demonstrate a failure in object_is_class which was fixed */ /* Create a class whose instance variables mirror the struct used for diff --git a/gcc/testsuite/objc/execute/object_is_meta_class.m b/gcc/testsuite/objc/execute/object_is_meta_class.m index 90cd3a962f0..aeb129ef4e5 100644 --- a/gcc/testsuite/objc/execute/object_is_meta_class.m +++ b/gcc/testsuite/objc/execute/object_is_meta_class.m @@ -3,6 +3,8 @@ #include <objc/objc-api.h> #include <objc/Object.h> +#include "next_mapping.h" + /* This test demonstrate a failure in object_is_meta_class which was fixed */ @interface EvilClass : Object diff --git a/gcc/testsuite/objc/execute/redefining_self.m b/gcc/testsuite/objc/execute/redefining_self.m index 93659dbac8d..ddb2eb2e3d0 100644 --- a/gcc/testsuite/objc/execute/redefining_self.m +++ b/gcc/testsuite/objc/execute/redefining_self.m @@ -17,6 +17,9 @@ return self; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end diff --git a/gcc/testsuite/objc/execute/root_methods.m b/gcc/testsuite/objc/execute/root_methods.m index 4f2c2fa0ee4..c18ceb07284 100644 --- a/gcc/testsuite/objc/execute/root_methods.m +++ b/gcc/testsuite/objc/execute/root_methods.m @@ -1,6 +1,8 @@ /* Contributed by Nicola Pero - Thu Mar 8 16:27:46 CET 2001 */ #include <objc/objc.h> +#include "next_mapping.h" + /* Test that instance methods of root classes are available as class methods to other classes as well */ @@ -16,6 +18,9 @@ { return self; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end @interface NormalClass : RootClass diff --git a/gcc/testsuite/objc/execute/static-1.m b/gcc/testsuite/objc/execute/static-1.m index 761e7070271..a778b722c15 100644 --- a/gcc/testsuite/objc/execute/static-1.m +++ b/gcc/testsuite/objc/execute/static-1.m @@ -19,6 +19,9 @@ static int test = 1; return test; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end int main (void) diff --git a/gcc/testsuite/objc/execute/static-2.m b/gcc/testsuite/objc/execute/static-2.m index 52a03a8fbd4..4d7e7449bff 100644 --- a/gcc/testsuite/objc/execute/static-2.m +++ b/gcc/testsuite/objc/execute/static-2.m @@ -22,6 +22,9 @@ static int test (void) return test (); } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end int main (void) diff --git a/gcc/testsuite/objc/execute/string1.m b/gcc/testsuite/objc/execute/string1.m index fff03c7cfa6..58a603c1f1f 100644 --- a/gcc/testsuite/objc/execute/string1.m +++ b/gcc/testsuite/objc/execute/string1.m @@ -2,7 +2,12 @@ #include <string.h> #include <stdlib.h> + +#ifdef __NEXT_RUNTIME__ +#import <Foundation/NSString.h> +#else #include <objc/NXConstStr.h> +#endif int main(int argc, void **args) { diff --git a/gcc/testsuite/objc/execute/string2.m b/gcc/testsuite/objc/execute/string2.m index 66462b3c96c..01fb85c1189 100644 --- a/gcc/testsuite/objc/execute/string2.m +++ b/gcc/testsuite/objc/execute/string2.m @@ -2,7 +2,12 @@ #include <string.h> #include <stdlib.h> + +#ifdef __NEXT_RUNTIME__ +#import <Foundation/NSString.h> +#else #include <objc/NXConstStr.h> +#endif int main(int argc, void **args) { diff --git a/gcc/testsuite/objc/execute/string3.m b/gcc/testsuite/objc/execute/string3.m index 21527dcbf15..a8d29696899 100644 --- a/gcc/testsuite/objc/execute/string3.m +++ b/gcc/testsuite/objc/execute/string3.m @@ -2,7 +2,12 @@ #include <string.h> #include <stdlib.h> + +#ifdef __NEXT_RUNTIME__ +#import <Foundation/NSString.h> +#else #include <objc/NXConstStr.h> +#endif #define STRING "this is a string" diff --git a/gcc/testsuite/objc/execute/string4.m b/gcc/testsuite/objc/execute/string4.m index 54550d6f5e9..16025cbaed6 100644 --- a/gcc/testsuite/objc/execute/string4.m +++ b/gcc/testsuite/objc/execute/string4.m @@ -2,7 +2,12 @@ #include <string.h> #include <stdlib.h> + +#ifdef __NEXT_RUNTIME__ +#import <Foundation/NSString.h> +#else #include <objc/NXConstStr.h> +#endif int main(int argc, void **args) { diff --git a/gcc/testsuite/objc/execute/va_method.m b/gcc/testsuite/objc/execute/va_method.m index bcf43d272a2..51619b8d313 100644 --- a/gcc/testsuite/objc/execute/va_method.m +++ b/gcc/testsuite/objc/execute/va_method.m @@ -1,6 +1,7 @@ /* Contributed by Nicola Pero - Thu Mar 8 16:27:46 CET 2001 */ #include <objc/objc.h> #include <objc/objc-api.h> +#include <stdarg.h> /* Test method with variable number of arguments */ @@ -31,6 +32,9 @@ return sum; } +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif @end int main (void) |