diff options
author | zlaski <zlaski@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-25 01:26:01 +0000 |
---|---|---|
committer | zlaski <zlaski@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-25 01:26:01 +0000 |
commit | c17b85eafa482aa4b14b5c81bac7a471e41393c7 (patch) | |
tree | 1052b4d25cc404c17e6402e22b8183026f4d4263 /gcc/testsuite/objc.dg | |
parent | 8024827507976fce5cbedb575703ee4aa1f12809 (diff) | |
download | gcc-c17b85eafa482aa4b14b5c81bac7a471e41393c7.tar.gz |
2003-09-24 Ziemowit Laski <zlaski@apple.com>
MERGE OF objc-improvements-branch into MAINLINE.
See 'gcc/ChangeLog' and 'gcc/testsuite/ChangeLog' for
the gory details.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71748 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/testsuite/objc.dg')
58 files changed, 1792 insertions, 20 deletions
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" } } */ + |