diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c3d153f6cb9..e46a7710262 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,27 @@ +2005-05-24 Ziemowit Laski + + * obj-c++.dg/bitfield-[1-5].mm: New. + * obj-c++.dg/class-protocol-1.mm: New. + * obj-c++.dg/comp-types-1[0-1].mm: New. + * obj-c++.dg/comp-types-[2-9].mm: New. + * obj-c++.dg/encode-[4-8].mm: New. + * obj-c++.dg/layout-1.mm: New. + * obj-c++.dg/method-1[0-9].mm: New. + * obj-c++.dg/method-2[0-1].mm: New. + * obj-c++.dg/method-[8-9].mm: New. + * obj-c++.dg/objc-gc-3.mm: New. + * obj-c++.dg/try-catch-10.mm: New. + * objc.dg/bitfield-5.m: New. + * objc.dg/comp-types-10.m: New. + * objc.dg/comp-types-9.m: New. + * objc.dg/layout-1.m: New. + * objc.dg/objc-gc-4.m: New. + * objc.dg/try-catch-9.m: New. + * objc.dg/class-protocol-1.m: Tweak diagnostics. + * objc.dg/comp-types-1.m: Likewise. + * objc.dg/comp-types-[5-6].m: Likewise. + * objc.dg/method-9.m: Likewise. + 2005-05-24 Janis Johnson * gcc.dg/altivec-vec-merge.c: Make test usable on GNU/Linux targets diff --git a/gcc/testsuite/obj-c++.dg/bitfield-1.mm b/gcc/testsuite/obj-c++.dg/bitfield-1.mm new file mode 100644 index 00000000000..c7920251d06 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/bitfield-1.mm @@ -0,0 +1,113 @@ +/* Check if ObjC class layout follows the ABI (informally) + set in the past. ObjC structs must be laid out as if + all ivars, including those inherited from superclasses, + were defined at once (i.e., any padding introduced for + superclasses should be removed). */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-Wpadded -Wabi" } */ +/* { dg-do run } */ + +#include +#include +#include + +#define CHECK_IF(expr) if(!(expr)) abort() + +enum Enum { zero, one, two, three, four }; + +@interface Base: Object { +@public + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +struct Base_0 { /* { dg-warning "padding struct size to alignment boundary" } */ + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +}; + +@interface Derived: Base { +@public + signed e: 5; + unsigned f: 4; + enum Enum g: 3; +} +@end + +struct Derived_0 { + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; + signed e: 5; + int f: 4; + enum Enum g: 3; +}; + +@interface Leaf: Derived { +@public + signed h: 2; +} +@end + +struct Leaf_0 { + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; + signed e: 5; + unsigned f: 4; + enum Enum g: 3; + signed h: 2; +}; + +/* 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; +typedef struct { @defs(Leaf); } Leaf_t; + +int main(void) +{ + struct Leaf_0 l_0; + Leaf *l = (Leaf *)&l_0; + Leaf_t *l_t = (Leaf_t *)&l_0; + + CHECK_IF(sizeof(Base_t) == sizeof(Base)); + CHECK_IF(sizeof(Derived_t) == sizeof(Derived)); + CHECK_IF(sizeof(Leaf_t) == sizeof(Leaf)); + + CHECK_IF(sizeof(struct Base_0) == sizeof(Base)); + CHECK_IF(sizeof(struct Derived_0) == sizeof(Derived)); + CHECK_IF(sizeof(struct Leaf_0) == sizeof(Leaf)); + + l_0.isa = (Class)0; + l_0.a = 3; + l_0.b = 0; + l_0.c = three; + l_0.d = 31; + l_0.e = 0; + l_0.f = 15; + l_0.g = zero; + l_0.h = -2; + + CHECK_IF(!l_t->isa); + CHECK_IF(l->a == 3 && l_t->a == 3); + CHECK_IF(!l->b && !l_t->b); + CHECK_IF(l->c == three && l_t->c == three); + CHECK_IF(l->d == 31 && l_t->d == 31); + CHECK_IF(!l->e && !l_t->e); + CHECK_IF(l->f == 15 && l_t->f == 15); + CHECK_IF(l->g == zero && l_t->g == zero); + CHECK_IF(l->h == -2 && l_t->h == -2); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/bitfield-2.mm b/gcc/testsuite/obj-c++.dg/bitfield-2.mm new file mode 100644 index 00000000000..7f778b5a4d9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/bitfield-2.mm @@ -0,0 +1,78 @@ +/* Check if bitfield ivars are inherited correctly (i.e., without + being "promoted" to ints). */ +/* Contributed by Ziemowit Laski . */ +/* { dg-do run } */ + +#include +#include + +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object +{ + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +- (void)setValues; +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +- (void)checkValues; +@end + +@implementation Base +-(void)setValues { + full = 1; + full2 = 2; + _refs = 3; + field2 = 1; + f3 = 6; + cc = 7; + g = 8; + r2 = 9; + r3 = 10; + r4 = 1; + r5 = 12; + c = 13; +} +@end + +@implementation Derived +-(void)checkValues { + CHECK_IF(full == 1); + CHECK_IF(full2 == 2); + CHECK_IF(_refs == 3); + CHECK_IF(field2 == 1); + CHECK_IF(f3 == 6); + CHECK_IF(cc == 7); + CHECK_IF(g == 8); + CHECK_IF(r2 == 9); + CHECK_IF(r3 == 10); + CHECK_IF(r4 == 1); + CHECK_IF(r5 == 12); + CHECK_IF(c == 13); +} +@end + +int main(void) { + Derived *obj = [[Derived alloc] init]; + + [obj setValues]; + [obj checkValues]; + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/bitfield-3.mm b/gcc/testsuite/obj-c++.dg/bitfield-3.mm new file mode 100644 index 00000000000..d607a3efc9d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/bitfield-3.mm @@ -0,0 +1,57 @@ +/* Check if bitfield ivars are correctly @encode'd when + the NeXT runtime is used. */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-fnext-runtime -fsigned-char" } */ +/* { dg-do run { target *-*-darwin* } } */ + +typedef struct objc_object { struct objc_class *class_pointer; } *id; + +extern "C" { + extern void abort(void); + extern int strcmp(const char *, const char *); +} + +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base +{ + struct objc_class *isa; + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +@end + +@implementation Base +@end + +@implementation Derived +@end + +int main(void) { + const char *s1r = "{Base=#ib32b8b3b8sb16b8b8b2b8c}"; + const char *s1 = @encode(Base); + const char *s2r = "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}"; + const char *s2 = @encode(Derived); + + CHECK_IF(!strcmp(s1r, s1)); + CHECK_IF(!strcmp(s2r, s2)); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/bitfield-4.mm b/gcc/testsuite/obj-c++.dg/bitfield-4.mm new file mode 100644 index 00000000000..4aa2a8b39df --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/bitfield-4.mm @@ -0,0 +1,51 @@ +/* Check if the @defs() construct preserves the correct + layout of bitfields. */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-lobjc -Wpadded" } */ +/* { dg-do run } */ + +#include + +extern "C" { + 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; +} +@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; + +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/obj-c++.dg/bitfield-5.mm b/gcc/testsuite/obj-c++.dg/bitfield-5.mm new file mode 100644 index 00000000000..b6716df8d97 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/bitfield-5.mm @@ -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 */ +/* { 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 *-*-* } 13 } */ + unsigned a: 5; /* { dg-error "conflicting instance variable type .unsigned( int)? a: 5." } */ + /* { dg-error "previous declaration of .unsigned( int)? a: 3." "" { target *-*-* } 14 } */ + 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 *-*-* } 16 } */ +} +@end diff --git a/gcc/testsuite/obj-c++.dg/class-protocol-1.mm b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm new file mode 100644 index 00000000000..b8200d0c0b3 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm @@ -0,0 +1,442 @@ + +/* Check Class types */ +/* Author: David Ayers */ +/* { dg-do compile } */ + +#include +#include + +@protocol MyProto1 ++(void)doItClass1; +-(void)doItInstance1; +@end + +@protocol MyProto2 ++(void)doItClass2; +-(void)doItInstance2; +@end + +@interface MyClass1 +{ + Class isa; +} +@end +@implementation MyClass1 ++(void)doItClass1{} +-(void)doItInstance1{} +@end + +@interface MyClass2 : MyClass1 +@end +@implementation MyClass2 ++(void)doItClass2{} +-(void)doItInstance2{} +@end + +@interface MyClass3 +{ + Class isa; +} +@end +@interface MyClass4 : MyClass3 +@end + +/*----------------------------------------*/ + +Class cls = 0; +Class clsP1 = 0; +Class clsP2 = 0; + +void +testSimple(void) +{ + [cls doItClass1]; + [cls doItInstance1]; + [cls doItClass2]; + [cls doItInstance2]; + + [clsP1 doItClass1]; + [clsP1 doItInstance1]; /* { dg-warning "instead of" } */ + [clsP1 doItClass2]; /* { dg-warning "not found in protocol" } */ + [clsP1 doItInstance2]; /* { dg-warning "not found in protocol" } */ + + [clsP2 doItClass1]; /* { dg-warning "not found in protocol" } */ + [clsP2 doItInstance1]; /* { dg-warning "not found in protocol" } */ + [clsP2 doItClass2]; + [clsP2 doItInstance2]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass1]; + [MyClass1 doItInstance1]; + [MyClass1 doItClass2]; /* { dg-warning "may not respond to" } */ + [MyClass1 doItInstance2]; /* { dg-warning "may not respond to" } */ + + [MyClass2 doItClass1]; + [MyClass2 doItInstance1]; + [MyClass2 doItClass2]; + [MyClass2 doItInstance2]; /* { dg-warning "may not respond to" } */ + + [MyClass3 doItClass1]; /* { dg-warning "may not respond to" } */ + [MyClass3 doItInstance1]; /* { dg-warning "may not respond to" } */ + + [MyClass4 doItClass1]; + [MyClass4 doItInstance1]; /* { dg-warning "may not respond to" } */ +} + +/*----------------------------------------*/ +/* Protocols declared by categories */ + +@protocol MyProto3 ++(void)doItClass3; +-(void)doItInstance3; +@end +@protocol MyProto4 ++(void)doItClass4; +-(void)doItInstance4; +@end + +@interface MyClass1 (Category1) +@end +@interface MyClass2 (Category2) +@end + +void +testCategory(void) +{ + [cls doItClass3]; + [cls doItInstance3]; + [cls doItClass4]; + [cls doItInstance4]; + + [MyClass1 doItClass3]; + [MyClass1 doItInstance3]; + [MyClass1 doItClass4]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance4]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass3]; + [MyClass2 doItInstance3]; + [MyClass2 doItClass4]; + [MyClass2 doItInstance4]; /* { dg-warning "may not respond" } */ + +} + +/*----------------------------------------*/ +/* Inherited protocols declared by categories */ + +@protocol MyProto5 ++(void)doItClass5; +-(void)doItInstance5; +@end + +@protocol MyProto6 ++(void)doItClass6; +-(void)doItInstance6; +@end + +@interface MyClass1 (Category3) +@end +@interface MyClass2 (Category4) +@end + +Class clsP5 = 0; +Class clsP6 = 0; + +void +testCategoryInherited(void) +{ + [cls doItClass5]; + [cls doItInstance5]; + [cls doItClass6]; + [cls doItInstance6]; + + [clsP5 doItClass1]; + [clsP5 doItInstance1]; /* { dg-warning "instead of" } */ + [clsP5 doItClass2]; /* { dg-warning "not found in protocol" } */ + [clsP5 doItInstance2]; /* { dg-warning "not found in protocol" } */ + + [clsP6 doItClass1]; /* { dg-warning "not found in protocol" } */ + [clsP6 doItInstance1]; /* { dg-warning "not found in protocol" } */ + [clsP6 doItClass2]; + [clsP6 doItInstance2]; /* { dg-warning "instead of" } */ + + + [MyClass1 doItClass5]; + [MyClass1 doItInstance5]; + [MyClass1 doItClass6]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance6]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass5]; + [MyClass2 doItInstance5]; + [MyClass2 doItClass6]; + [MyClass2 doItInstance6]; /* { dg-warning "may not respond" } */ + +} + +/*----------------------------------------*/ +/* Forward declared root protocols */ + +@protocol FwProto; + +@interface MyClass1 (Forward) +@end + +Class clsP7 = 0; + +void +testForwardeDeclared1(void) +{ + [cls doItClass7]; /* { dg-warning "no .\\+doItClass7. method found" } */ + [cls doItInstance7]; /* { dg-warning "no .\\+doItInstance7. method found" } */ + + [clsP7 doItClass7]; /* { dg-warning "not found in protocol" } */ + /* { dg-warning "no .\\+doItClass7. method found" "" { target *-*-* } 190 } */ + [clsP7 doItInstance7]; /* { dg-warning "not found in protocol" } */ + /* { dg-warning "no .\\+doItInstance7. method found" "" { target *-*-* } 192 } */ + + [MyClass1 doItClass7]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance7]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass7]; /* { dg-warning "may not respond" } */ + [MyClass2 doItInstance7]; /* { dg-warning "may not respond" } */ + +} + +@protocol FwProto ++(void)doItClass7; +-(void)doItInstance7; +@end + +void +testForwardeDeclared2(void) +{ + [cls doItClass7]; + [cls doItInstance7]; + + [clsP7 doItClass7]; + [clsP7 doItInstance7]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass7]; + [MyClass1 doItInstance7]; + + [MyClass2 doItClass7]; + [MyClass2 doItInstance7]; +} + +/*----------------------------------------*/ +/* Inherited non root protocols */ + +@protocol MyProto8 ++(void)doItClass8; +-(void)doItInstance8; +@end + +@protocol MyProto9 ++(void)doItClass9; +-(void)doItInstance9; +@end + +@interface MyClass1 (InheritedNonRoot) +@end + +Class clsP8 = 0; +Class clsP9 = 0; + +void +testInheritedNonRoot(void) +{ + [cls doItClass8]; + [cls doItInstance8]; + [cls doItClass9]; + [cls doItInstance9]; + + [clsP8 doItClass8]; + [clsP8 doItInstance8]; /* { dg-warning "instead of" } */ + [clsP8 doItClass9]; /* { dg-warning "not found in protocol" } */ + [clsP8 doItInstance9]; /* { dg-warning "not found in protocol" } */ + + [clsP9 doItClass8]; + [clsP9 doItInstance8]; /* { dg-warning "instead of" } */ + [clsP9 doItClass9]; + [clsP9 doItInstance9]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass8]; + [MyClass1 doItInstance8]; + [MyClass1 doItClass9]; + [MyClass1 doItInstance9]; + + [MyClass2 doItClass8]; + [MyClass2 doItInstance8]; + [MyClass2 doItClass9]; + [MyClass2 doItInstance9]; + +} + +/*----------------------------------------*/ +/* Prototype mismatch */ + +@protocol MyOtherProto1 ++(id)doItClass1; +-(id)doItInstance1; +@end +@interface MyOtherClass1 +@end + +Class oclsP1; + +void +testPrototypeMismatch(void) +{ + id tmp1 = [oclsP1 doItClass1]; + id tmp2 = [oclsP1 doItInstance1]; /* { dg-warning "instead of" } */ + + [clsP1 doItClass1]; + [clsP1 doItInstance1]; /* { dg-warning "instead of" } */ +} + +id obj = nil; +id objP1 = nil; +id objP2 = nil; +id objP5 = nil; +int num = 0; +void *ptr = 0; + +MyClass1 *mc1 = nil; + +void +testComptypes(void) +{ + { /* id , id */ + objP1 == objP2; /* { dg-warning "lacks a cast" } */ + objP2 == objP1; /* { dg-warning "lacks a cast" } */ + + objP1 == objP5; + objP5 == objP1; + } + { /* id , SomeClass * */ + mc1 == objP1; + objP1 == mc1; + + mc1 == objP2; /* { dg-warning "lacks a cast" } */ + objP2 == mc1; /* { dg-warning "lacks a cast" } */ + } + { /* id , id */ + obj == objP1; + objP1 == obj; + } + { /* id , Class */ + cls == objP1; /* { dg-warning "lacks a cast" } */ + objP1 == cls; /* { dg-warning "lacks a cast" } */ + } + { /* id , non-ObjC */ + num == objP1; /* { dg-warning "between pointer" } */ + objP1 == num; /* { dg-warning "between pointer" } */ + + ptr == objP1; + objP1 == ptr; + } + { /* Class , Class */ + clsP1 == clsP2; /* { dg-warning "lacks a cast" } */ + clsP2 == clsP1; /* { dg-warning "lacks a cast" } */ + + clsP1 == clsP5; + clsP5 == clsP1; + } + { /* Class , SomeClass * */ + mc1 == clsP1; /* { dg-warning "lacks a cast" } */ + clsP1 == mc1; /* { dg-warning "lacks a cast" } */ + } + { /* Class , id */ + obj == clsP1; + clsP1 == obj; + } + { /* Class , Class */ + cls == clsP1; + clsP1 == cls; + } + { /* Class , non-ObjC */ + num == clsP1; /* { dg-warning "between pointer" } */ + clsP1 == num; /* { dg-warning "between pointer" } */ + + ptr == clsP1; + clsP1 == ptr; + } + { /* Class , id */ + clsP1 == objP1; /* { dg-warning "lacks a cast" } */ + objP1 == clsP1; /* { dg-warning "lacks a cast" } */ + } + + { /* id , id */ + objP1 = objP2; /* { dg-warning "does not conform" } */ + objP2 = objP1; /* { dg-warning "does not conform" } */ + + objP1 = objP5; + objP5 = objP1; /* { dg-warning "does not conform" } */ + } + { /* id , SomeClass * */ + mc1 = objP1; + objP1 = mc1; + + mc1 = objP2; /* { dg-warning "does not conform" } */ + objP2 = mc1; /* { dg-warning "does not implement" } */ + } + { /* id , id */ + obj = objP1; + objP1 = obj; + } + { /* id , Class */ + cls = objP1; /* { dg-warning "distinct Objective\\-C type" } */ + objP1 = cls; /* { dg-warning "distinct Objective\\-C type" } */ + } + { /* id , non-ObjC */ + num = objP1; /* { dg-error "invalid conversion" } */ + objP1 = num; /* { dg-error "invalid conversion" } */ + + ptr = objP1; + objP1 = ptr; /* { dg-error "invalid conversion" } */ + } + { /* Class , Class */ + clsP1 = clsP2; /* { dg-warning "does not conform" } */ + clsP2 = clsP1; /* { dg-warning "does not conform" } */ + + clsP1 = clsP5; + clsP5 = clsP1; /* { dg-warning "does not conform" } */ + } + { /* Class , SomeClass * */ + /* These combinations should always elicit a warning. */ + mc1 = clsP1; /* { dg-warning "distinct Objective\\-C type" } */ + clsP1 = mc1; /* { dg-warning "distinct Objective\\-C type" } */ + + mc1 = clsP2; /* { dg-warning "distinct Objective\\-C type" } */ + clsP2 = mc1; /* { dg-warning "distinct Objective\\-C type" } */ + } + { /* Class , id */ + obj = clsP1; + clsP1 = obj; + } + { /* Class , Class */ + cls = clsP1; + clsP1 = cls; + } + { /* Class , non-ObjC */ + num = clsP1; /* { dg-error "invalid conversion" } */ + clsP1 = num; /* { dg-error "invalid conversion" } */ + + ptr = clsP1; + clsP1 = ptr; /* { dg-error "invalid conversion" } */ + } + { /* Class , id */ + clsP1 = objP1; /* { dg-warning "distinct Objective\\-C type" } */ + objP1 = clsP1; /* { dg-warning "distinct Objective\\-C type" } */ + } +} + +int main () +{ + testSimple(); + testCategory(); + testCategoryInherited(); + return(0); +} + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/obj-c++.dg/comp-types-10.mm b/gcc/testsuite/obj-c++.dg/comp-types-10.mm new file mode 100644 index 00000000000..3abcde5bec6 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-10.mm @@ -0,0 +1,19 @@ +/* Yet another mysterious gimplifier crasher. */ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +@class NSString; +@protocol NSObject +@end +@interface NSObject { +} +@end +void __setRetained(id *ivar, id value) { + *ivar = value; +} +static NSString *_logProcessPrefix = 0; +@implementation NSObject (ScopeAdditions) ++ (void)setObjectLogProcessPrefix:(NSString *)processPrefix { + __setRetained(&_logProcessPrefix, processPrefix); +} +@end diff --git a/gcc/testsuite/obj-c++.dg/comp-types-11.mm b/gcc/testsuite/obj-c++.dg/comp-types-11.mm new file mode 100644 index 00000000000..8cd53404f52 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-11.mm @@ -0,0 +1,28 @@ +/* { dg-do compile } */ + +#include + +@protocol Foo +- (id)meth1; +- (id)meth2:(int)arg; +@end + +@interface Derived1: Object +@end + +@interface Derived2: Object ++ (Derived1 *)new; +@end + +id func(void) { + Object *o = [Object new]; + return o; /* { dg-warning "class .Object. does not implement the .Foo. protocol" } */ +} + +@implementation Derived2 ++ (Derived1 *)new { + Derived2 *o = [super new]; + return o; /* { dg-warning "distinct Objective\\-C type in return" } */ +} +@end + diff --git a/gcc/testsuite/obj-c++.dg/comp-types-2.mm b/gcc/testsuite/obj-c++.dg/comp-types-2.mm new file mode 100644 index 00000000000..07043785a22 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-2.mm @@ -0,0 +1,88 @@ +/* Test various ObjC types assignments and comparisons. */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) foo; +@end + +@interface MyClass +@end + +@interface MyOtherClass +- (void) foo; +@end + +int main() +{ + id obj = nil; + id obj_p = nil; + MyClass *obj_c = nil; + MyOtherClass *obj_cp = nil; + Class obj_C = Nil; + + /* Assigning to an 'id' variable should never + generate a warning. */ + obj = obj_p; /* Ok */ + obj = obj_c; /* Ok */ + obj = obj_cp; /* Ok */ + obj = obj_C; /* Ok */ + + /* Assigning to a 'MyClass *' variable should always generate a + warning, unless done from an 'id'. */ + obj_c = obj; /* Ok */ + obj_c = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ + obj_c = obj_cp; /* { dg-warning "distinct Objective\\-C type" } */ + obj_c = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ + + /* Assigning to an 'id' variable should generate a + warning if done from a 'MyClass *' (which doesn't implement + 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" } */ + obj_p = obj_cp; /* Ok */ + obj_p = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ + + /* Assigning to a 'MyOtherClass *' variable should always generate + a warning, unless done from an 'id' or an 'id' (since + MyOtherClass implements MyProtocol). */ + obj_cp = obj; /* Ok */ + obj_cp = obj_c; /* { dg-warning "distinct Objective\\-C type" } */ + obj_cp = obj_p; /* Ok */ + obj_cp = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ + + /* Any comparison involving an 'id' must be without warnings. */ + if (obj == obj_p) ; /* Ok */ /*Bogus warning here in 2.95.4*/ + if (obj_p == obj) ; /* Ok */ + if (obj == obj_c) ; /* Ok */ + if (obj_c == obj) ; /* Ok */ + if (obj == obj_cp) ; /* Ok */ + if (obj_cp == obj) ; /* Ok */ + if (obj == obj_C) ; /* Ok */ + if (obj_C == obj) ; /* Ok */ + + /* Any comparison between 'MyClass *' and anything which is not an 'id' + must generate a warning. */ + if (obj_c == obj_p) ; /* { dg-warning "lacks a cast" } */ + if (obj_p == obj_c) ; /* { dg-warning "lacks a cast" } */ + if (obj_c == obj_cp) ; /* { dg-warning "lacks a cast" } */ + if (obj_cp == obj_c) ; /* { dg-warning "lacks a cast" } */ + if (obj_c == obj_C) ; /* { dg-warning "lacks a cast" } */ + if (obj_C == obj_c) ; /* { dg-warning "lacks a cast" } */ + + /* Any comparison between 'MyOtherClass *' (which implements + MyProtocol) and an 'id' implementing MyProtocol are Ok. */ + if (obj_cp == obj_p) ; /* Ok */ + if (obj_p == obj_cp) ; /* Ok */ + + + if (obj_p == obj_C) ; /* { dg-warning "lacks a cast" } */ + if (obj_C == obj_p) ; /* { dg-warning "lacks a cast" } */ + if (obj_cp == obj_C) ; /* { dg-warning "lacks a cast" } */ + if (obj_C == obj_cp) ; /* { dg-warning "lacks a cast" } */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-3.mm b/gcc/testsuite/obj-c++.dg/comp-types-3.mm new file mode 100644 index 00000000000..2bea01534a7 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-3.mm @@ -0,0 +1,38 @@ +/* Test simple ObjC types casts. */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) foo; +@end + +@interface MyClass +@end + +int main() +{ + id obj = nil; + id obj_p = nil; + MyClass *obj_c = nil; + Class obj_C = Nil; + + /* All these casts should generate no warnings. */ + + obj = (id)obj_p; + obj = (id)obj_c; + obj = (id)obj_C; + obj_c = (MyClass *)obj; + obj_c = (MyClass *)obj_p; + obj_c = (MyClass *)obj_C; + obj_p = (id)obj; + obj_p = (id)obj_c; + obj_p = (id)obj_C; + obj_C = (Class)obj; + obj_C = (Class)obj_p; + obj_C = (Class)obj_c; + + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-4.mm b/gcc/testsuite/obj-c++.dg/comp-types-4.mm new file mode 100644 index 00000000000..6867f82785d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-4.mm @@ -0,0 +1,64 @@ +/* Test assignments and comparisons between protocols (obscure case). */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocolA +- (void) methodA; +@end + +@protocol MyProtocolB +- (void) methodB; +@end + +@protocol MyProtocolAB +@end + +@protocol MyProtocolAC +- (void) methodC; +@end + +int main() +{ + id obj_a = nil; + id obj_b = nil; + id obj_ab = nil; + id obj_ac = nil; + + obj_a = obj_b; /* { dg-warning "does not conform" } */ + obj_a = obj_ab; /* Ok */ + obj_a = obj_ac; /* Ok */ + + obj_b = obj_a; /* { dg-warning "does not conform" } */ + obj_b = obj_ab; /* Ok */ + obj_b = obj_ac; /* { dg-warning "does not conform" } */ + + obj_ab = obj_a; /* { dg-warning "does not conform" } */ + obj_ab = obj_b; /* { dg-warning "does not conform" } */ + obj_ab = obj_ac; /* { dg-warning "does not conform" } */ + + obj_ac = obj_a; /* { dg-warning "does not conform" } */ + obj_ac = obj_b; /* { dg-warning "does not conform" } */ + obj_ac = obj_ab; /* { dg-warning "does not conform" } */ + + if (obj_a == obj_b) ; /* { dg-warning "lacks a cast" } */ + if (obj_b == obj_a) ; /* { dg-warning "lacks a cast" } */ + + if (obj_a == obj_ab) ; /* Ok */ + if (obj_ab == obj_a) ; /* Ok */ /* Spurious 2.95.4 warning here */ + + if (obj_a == obj_ac) ; /* Ok */ + if (obj_ac == obj_a) ; /* Ok */ /* Spurious 2.95.4 warning here */ + + if (obj_b == obj_ab) ; /* Ok */ + if (obj_ab == obj_b) ; /* Ok */ /* Spurious 2.95.4 warning here */ + + if (obj_b == obj_ac) ; /* { dg-warning "lacks a cast" } */ + if (obj_ac == obj_b) ; /* { dg-warning "lacks a cast" } */ + + if (obj_ab == obj_ac) ; /* { dg-warning "lacks a cast" } */ + if (obj_ac == obj_ab) ; /* { dg-warning "lacks a cast" } */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-5.mm b/gcc/testsuite/obj-c++.dg/comp-types-5.mm new file mode 100644 index 00000000000..99f6772bd42 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-5.mm @@ -0,0 +1,74 @@ +/* Test errors for assignments and comparisons between ObjC and C++ types. */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +/* The NeXT runtime headers do not define NULL. */ +#ifndef NULL +#define NULL ((void *)0) +#endif + +@protocol MyProtocol +- (void) method; +@end + +@interface MyClass +@end + +int main() +{ + id obj = nil; + id obj_p = nil; + MyClass *obj_c = nil; + Class obj_C = Nil; + + int i = 0; + int *j = (int *)NULL; + + /* These should all generate warnings. */ + + obj = i; /* { dg-error "invalid conversion" } */ + obj = j; /* { dg-error "cannot convert" } */ + + obj_p = i; /* { dg-error "invalid conversion" } */ + obj_p = j; /* { dg-error "cannot convert" } */ + + obj_c = i; /* { dg-error "invalid conversion" } */ + obj_c = j; /* { dg-error "cannot convert" } */ + + obj_C = i; /* { dg-error "invalid conversion" } */ + obj_C = j; /* { dg-error "cannot convert" } */ + + i = obj; /* { dg-error "invalid conversion" } */ + i = obj_p; /* { dg-error "invalid conversion" } */ + i = obj_c; /* { dg-error "invalid conversion" } */ + i = obj_C; /* { dg-error "invalid conversion" } */ + + j = obj; /* { dg-error "cannot convert" } */ + j = obj_p; /* { dg-error "cannot convert" } */ + j = obj_c; /* { dg-error "cannot convert" } */ + j = obj_C; /* { dg-error "cannot convert" } */ + + if (obj == i) ; /* { dg-error "comparison between pointer and integer" } */ + if (i == obj) ; /* { dg-error "comparison between pointer and integer" } */ + if (obj == j) ; /* { dg-error "lacks a cast" } */ + if (j == obj) ; /* { dg-error "lacks a cast" } */ + + if (obj_c == i) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (i == obj_c) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (obj_c == j) ; /* { dg-error "lacks a cast" } */ + if (j == obj_c) ; /* { dg-error "lacks a cast" } */ + + if (obj_p == i) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (i == obj_p) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (obj_p == j) ; /* { dg-error "lacks a cast" } */ + if (j == obj_p) ; /* { dg-error "lacks a cast" } */ + + if (obj_C == i) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (i == obj_C) ; /*{ dg-error "comparison between pointer and integer" }*/ + if (obj_C == j) ; /* { dg-error "lacks a cast" } */ + if (j == obj_C) ; /* { dg-error "lacks a cast" } */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-6.mm b/gcc/testsuite/obj-c++.dg/comp-types-6.mm new file mode 100644 index 00000000000..23b84edd374 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-6.mm @@ -0,0 +1,33 @@ +/* Test assignments and comparisons involving `one-off' protocols. */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) method; +@end + +@interface MyClass +@end + +int main() +{ + id obj = nil; + id obj_p = nil; + MyClass *obj_cp = nil; + + obj_cp = obj; /* Ok */ + obj = obj_cp; /* Ok */ + + obj_cp = obj_p; /* Ok */ + obj_p = obj_cp; /* Ok */ + + if (obj_cp == obj) ; /* Ok */ + if (obj == obj_cp) ; /* Ok */ + + if (obj_cp == obj_p) ; /* Ok */ + if (obj_p == obj_cp) ; /* Ok */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-7.mm b/gcc/testsuite/obj-c++.dg/comp-types-7.mm new file mode 100644 index 00000000000..e23558114bc --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-7.mm @@ -0,0 +1,38 @@ +/* Test assignments and comparisons involving category protocols. */ +/* Author: Nicola Pero . */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) method; +@end + +@interface MyClass +@end + +@interface MyClass (Addition) +- (void) method; +@end + +@interface MyOtherClass : MyClass +@end + +int main() +{ + id obj_p = nil; + MyClass *obj_cp = nil; + MyOtherClass *obj_cp2 = nil; + + obj_cp = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ + obj_cp2 = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ + obj_p = obj_cp; /* Ok */ + obj_p = obj_cp2; /* Ok */ + + if (obj_cp == obj_p) ; /* Ok */ + if (obj_cp2 == obj_p) ; /* Ok */ + if (obj_p == obj_cp) ; /* Ok */ + if (obj_p == obj_cp2) ; /* Ok */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/comp-types-8.mm b/gcc/testsuite/obj-c++.dg/comp-types-8.mm new file mode 100644 index 00000000000..490f4ff1938 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-8.mm @@ -0,0 +1,33 @@ +/* { dg-do compile } */ + +/* We used to ICE because we removed the cast to List_linked* + in -[ListIndex_linked next]. */ + +@interface List +{ +@public + int firstLink; +} +@end + +@interface ListIndex_linked +{ +@public + List *collection; + int link; +} +@end + +@interface List_linked: List +@end + +@implementation List +@end + +@implementation ListIndex_linked +- next +{ + link = ((List_linked*)collection)->firstLink; +} +@end + diff --git a/gcc/testsuite/obj-c++.dg/comp-types-9.mm b/gcc/testsuite/obj-c++.dg/comp-types-9.mm new file mode 100644 index 00000000000..f092c9e2796 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-9.mm @@ -0,0 +1,25 @@ +/* { dg-do compile } */ + +/* Another gimplifier ICE... */ + +#include + +@interface MyView: Object { + int _frame; +} +- (void)_finalize; +@end + +@interface MyViewTemplate: MyView { + void *_className; +} +- (id)createRealObject; +@end + +@implementation MyViewTemplate +- (id)createRealObject { + id realObj; + *(MyView *)realObj = *(MyView *)self; + return realObj; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/encode-4.mm b/gcc/testsuite/obj-c++.dg/encode-4.mm new file mode 100644 index 00000000000..25c0b509f8d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-4.mm @@ -0,0 +1,105 @@ +/* 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 (void *)-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 . */ +/* { dg-do run } */ + + +#include +#include + +#ifdef __NEXT_RUNTIME__ +#define METHOD Method +#define OBJC_GETCLASS objc_getClass +#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod +#else +#include +#define METHOD Method_t +#define OBJC_GETCLASS objc_get_class +#define CLASS_GETINSTANCEMETHOD class_get_instance_method +#endif + +extern "C" { + 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:(signed 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:(signed 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; + const char *string; + + 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; + if (sizeof (long) == 8) + string = "v%u@%u:%uc%uf%ud%uq%u"; + else + string = "v%u@%u:%uc%uf%ud%ul%u"; + sscanf(meth->method_types, string, &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/obj-c++.dg/encode-5.mm b/gcc/testsuite/obj-c++.dg/encode-5.mm new file mode 100644 index 00000000000..9a36326a355 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-5.mm @@ -0,0 +1,74 @@ +/* Method encoding tests for stand-alone @protocol declarations. */ +/* Contributed by Ziemowit Laski . */ +/* { dg-do run } */ + +#include +#ifdef __cplusplus +#define ProtoBool bool +#else +#define ProtoBool _Bool +#endif + +#ifndef __NEXT_RUNTIME__ +#include +#endif + +extern "C" { + 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:(signed 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) { + const char *string; + + meth = [proto descriptionForInstanceMethod: @selector(char:float:double:unsigned:short:long:)]; + if (sizeof (long) == 8) + string = "v%u@%u:%uc%uf%ud%uI%us%uq%u"; + else + string = "v%u@%u:%uc%uf%ud%uI%us%ul%u"; + scan_initial(string); + 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/obj-c++.dg/encode-6.mm b/gcc/testsuite/obj-c++.dg/encode-6.mm new file mode 100644 index 00000000000..1ee11714def --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-6.mm @@ -0,0 +1,75 @@ +/* Encoding tests for ObjC class layouts. */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include +#ifdef __NEXT_RUNTIME__ +#include +#define OBJC_GETCLASS objc_getClass +#else +#include +#define OBJC_GETCLASS objc_get_class +#endif + +extern "C" { + 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 { + signed 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/obj-c++.dg/encode-7.mm b/gcc/testsuite/obj-c++.dg/encode-7.mm new file mode 100644 index 00000000000..f2cb693b1b7 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-7.mm @@ -0,0 +1,78 @@ +/* Check if array arguments of ObjC methods are decayed to pointer types + in a proper fashion: + (1) The _encodings_ for the array arguments should remain to be '[4i]' and + such, since this has been the case since at least gcc 3.3. + (2) However, when building the static C functions out of ObjC method signatures, + we need to decay the arrays into pointers (as C does). + (3) If array size is not known (e.g., 'int a[]'), then the type shall be + encoded as a pointer. */ + +/* Contributed by Alexander Malmberg */ + +#include +#include +#include +#define CHECK_IF(expr) if(!(expr)) abort() + +#ifdef __NEXT_RUNTIME__ +#define METHOD Method +#define OBJC_GETCLASS objc_getClass +#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod +#else +#include +#define METHOD Method_t +#define OBJC_GETCLASS objc_get_class +#define CLASS_GETINSTANCEMETHOD class_get_instance_method +#endif + +@interface Test : Object +{ float j; } +-(void) test2: (int [5])a with: (int [])b; +-(id) test3: (Test **)b; /* { dg-warning "previous declaration of .\\-\\(id\\)test3:\\(Test \\*\\*\\)b." } */ +@end + +@implementation Test +-(void) test2: (int [5])a with: (int [])b +{ + a[3] = *b; +} +-(void) test3: (Test [3][4])b { /* { dg-warning "conflicting types for .\\-\\(void\\)test3:\\(Test \\\[3\\\]\\\[4\\\]\\)b." } */ +} +@end + +int bb[6] = { 0, 1, 2, 3, 4, 5 }; +int *b = bb; +Test *cc[4]; +Test **c = cc; + +int offs1, offs2, offs3, offs4, offs5, offs6; + +int main(int argc, char **argv) +{ + Class testClass = OBJC_GETCLASS("Test"); + METHOD meth; + + cc[0] = [Test new]; + CHECK_IF (bb[3] == 3); + [*c test2: b with: bb + 4]; + CHECK_IF (bb[3] == 4); + bb[3] = 0; + [*c test2: bb with: bb + 5]; + CHECK_IF (bb[3] == 5); + + meth = CLASS_GETINSTANCEMETHOD(testClass, @selector(test2:with:)); + offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = -1; + sscanf(meth->method_types, "v%d@%d:%d[%di]%d^i%d", &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6); + CHECK_IF (!offs2 && offs4 == 5 && offs3 > 0); + CHECK_IF (offs5 == 2 * offs3 && offs6 == 3 * offs3 && offs1 == 4 * offs3); + + meth = CLASS_GETINSTANCEMETHOD(testClass, @selector(test3:)); + offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = -1; + sscanf(meth->method_types, "v%d@%d:%d[%d[%d{Test=#f}]]%d", &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6); + CHECK_IF (!offs2 && offs4 == 3 && offs5 == 4 && offs3 > 0); + CHECK_IF (offs6 == 2 * offs3 && offs1 == 3 * offs3); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/encode-8.mm b/gcc/testsuite/obj-c++.dg/encode-8.mm new file mode 100644 index 00000000000..5f61cb87be4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-8.mm @@ -0,0 +1,23 @@ +/* Test if the Objective-C @encode machinery distinguishes between + 'BOOL *' (which should be encoded as '^c') and 'char *' (which + should be encoded as '*'). */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include +#include +#include + +int main(void) { + const char *BOOL_ptr = @encode(BOOL *); + const char *char_ptr = @encode(char *); + + if(strcmp(BOOL_ptr, "^c")) + abort(); + + if(strcmp(char_ptr, "*")) + abort(); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/layout-1.mm b/gcc/testsuite/obj-c++.dg/layout-1.mm new file mode 100644 index 00000000000..fe8ab3d083d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/layout-1.mm @@ -0,0 +1,15 @@ +/* Ensure that we do not get bizarre warnings referring to + __attribute__((packed)) or some such. */ +/* { dg-do compile } */ +/* { dg-options "-Wpadded -Wpacked -Wabi" } */ + +#include + +@interface Derived1: Object +{ } +@end + +@interface Derived2: Object +- (id) foo; +@end + diff --git a/gcc/testsuite/obj-c++.dg/method-10.mm b/gcc/testsuite/obj-c++.dg/method-10.mm new file mode 100644 index 00000000000..4c7ccb8b8a7 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-10.mm @@ -0,0 +1,45 @@ +/* Test for sending messages to aliased classes (and instances thereof). */ +/* Author: Ziemowit Laski . */ +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include + +extern "C" 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/obj-c++.dg/method-11.mm b/gcc/testsuite/obj-c++.dg/method-11.mm new file mode 100644 index 00000000000..c8d092df74d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-11.mm @@ -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 . */ +/* { dg-options "-fnext-runtime" } */ +/* { dg-do compile } */ + +#include + +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/obj-c++.dg/method-12.mm b/gcc/testsuite/obj-c++.dg/method-12.mm new file mode 100644 index 00000000000..21f4bb9f44d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-12.mm @@ -0,0 +1,31 @@ +/* Check that sending messages to variables of type 'Class' does not involve instance methods, unless they reside in root classes. */ +/* Author: Ziemowit Laski */ +/* { dg-options "-Wstrict-selector-match" } */ +/* { dg-do compile } */ + +#include + +@interface Base +- (unsigned)port; +@end + +@interface Derived: Base +- (Object *)port; ++ (Protocol *)port; +- (id)starboard; +@end + +void foo(void) { + Class receiver; + + [receiver port]; /* { dg-warning "multiple methods named .\\+port. found" } */ + /* { dg-warning "using .\\-\\(unsigned( int)?\\)port." "" { target *-*-* } 9 } */ + /* { dg-warning "also found .\\+\\(Protocol \\*\\)port." "" { target *-*-* } 14 } */ + + [receiver starboard]; /* { dg-warning "no .\\+starboard. method found" } */ + /* { 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 } */ + + [Class port]; /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */ +} diff --git a/gcc/testsuite/obj-c++.dg/method-13.mm b/gcc/testsuite/obj-c++.dg/method-13.mm new file mode 100644 index 00000000000..adf6dfe26d8 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-13.mm @@ -0,0 +1,27 @@ +/* Check if finding multiple signatures for a method is handled gracefully. Author: Ziemowit Laski */ +/* { dg-options "-Wstrict-selector-match" } */ +/* { dg-do compile } */ + +#include + +@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/obj-c++.dg/method-14.mm b/gcc/testsuite/obj-c++.dg/method-14.mm new file mode 100644 index 00000000000..4a13b7d6cbb --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-14.mm @@ -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 */ +/* { dg-do compile } */ + +@interface A +@end + +@interface B: A +- (void)f; +@end + +void g(A *p) { [(B *)p f]; } + diff --git a/gcc/testsuite/obj-c++.dg/method-15.mm b/gcc/testsuite/obj-c++.dg/method-15.mm new file mode 100644 index 00000000000..9d9099e9f7e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-15.mm @@ -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 */ +/* { dg-options "-Wstrict-selector-match" } */ +/* { dg-do compile } */ + +#include + +@protocol MyObject +- (id)initWithData:(Object *)data; +@end + +@protocol SomeOther +- (id)initWithData:(int)data; +@end + +@protocol MyCoding +- (id)initWithData:(id)data; +@end + +@interface NTGridDataObject: Object +{ + Object *_data; +} ++ (NTGridDataObject*)dataObject:(id)data; +@end + +@implementation NTGridDataObject +- (id)initWithData:(id)data { + return data; +} ++ (NTGridDataObject*)dataObject:(id)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 \\)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 argument 1 of .initWithData:. from distinct Objective\\-C type" "" { target *-*-* } 33 } */ + return result; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/method-16.mm b/gcc/testsuite/obj-c++.dg/method-16.mm new file mode 100644 index 00000000000..f4a9efcd72c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-16.mm @@ -0,0 +1,34 @@ + +/* 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 */ +/* { dg-do compile } */ + +#include + +@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 *-*-* } 26 } */ + /* { dg-warning "using .\\-\\(void\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 13 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object1 \\*\\)data." "" { target *-*-* } 17 } */ + /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(Object2 \\*\\)data." "" { target *-*-* } 21 } */ + + /* The following error is a consequence of picking the "wrong" method signature. */ + /* { dg-error "void value not ignored as it ought to be" "" { target *-*-* } 26 } */ +} diff --git a/gcc/testsuite/obj-c++.dg/method-17.mm b/gcc/testsuite/obj-c++.dg/method-17.mm new file mode 100644 index 00000000000..556830f3449 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-17.mm @@ -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 +extern "C" 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: (int)d floatingPoint: d]; + return 0; +} + diff --git a/gcc/testsuite/obj-c++.dg/method-18.mm b/gcc/testsuite/obj-c++.dg/method-18.mm new file mode 100644 index 00000000000..411caac111a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-18.mm @@ -0,0 +1,25 @@ +/* Contributed by Igor Seleznev . */ +/* This used to be broken. */ + +#include + +@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/obj-c++.dg/method-19.mm b/gcc/testsuite/obj-c++.dg/method-19.mm new file mode 100644 index 00000000000..55890f5b404 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-19.mm @@ -0,0 +1,81 @@ +/* Test if instance methods of root classes are used as class methods, if no + "real" methods are found. For receivers of type 'id' and 'Class', all + root classes must be considered. */ +/* Author: Ziemowit Laski . */ +/* { dg-do run } */ + +#include + +#ifdef __NEXT_RUNTIME__ +#include +#define OBJC_GETCLASS objc_getClass +#else +#include +#define OBJC_GETCLASS objc_get_class +#endif + +extern "C" { + extern void abort(void); + extern int strcmp(const char *, const char *); +} +#define CHECK_IF(expr) if(!(expr)) abort() + +@protocol Proto +- (const char *) method4; +@end + +@interface Root +{ Class isa; } ++ (const char *) method2; +@end + +@interface Derived: Root +- (const char *) method1; +- (const char *) method2; +- (const char *) method3; +@end + +@interface Root (Categ) +- (const char *) method3; +@end + +@implementation Root (Categ) +- (const char *) method3 { return "Root(Categ)::-method3"; } +- (const char *) method4 { return "Root(Categ)::-method4"; } +@end + +@implementation Derived +- (const char *) method1 { return "Derived::-method1"; } +- (const char *) method2 { return "Derived::-method2"; } +- (const char *) method3 { return "Derived::-method3"; } +@end + +@implementation Root +#ifdef __NEXT_RUNTIME__ ++ initialize { return self; } +#endif +- (const char *) method1 { return "Root::-method1"; } ++ (const char *) method2 { return "Root::+method2"; } +@end + +int main(void) +{ + Class obj = OBJC_GETCLASS("Derived"); + + /* None of the following should elicit compiler-time warnings. */ + + CHECK_IF(!strcmp([Root method1], "Root::-method1")); + CHECK_IF(!strcmp([Root method2], "Root::+method2")); + CHECK_IF(!strcmp([Root method3], "Root(Categ)::-method3")); + CHECK_IF(!strcmp([Root method4], "Root(Categ)::-method4")); + CHECK_IF(!strcmp([Derived method1], "Root::-method1")); + CHECK_IF(!strcmp([Derived method2], "Root::+method2")); + CHECK_IF(!strcmp([Derived method3], "Root(Categ)::-method3")); + CHECK_IF(!strcmp([Derived method4], "Root(Categ)::-method4")); + CHECK_IF(!strcmp([obj method1], "Root::-method1")); + CHECK_IF(!strcmp([obj method2], "Root::+method2")); + CHECK_IF(!strcmp([obj method3], "Root(Categ)::-method3")); + CHECK_IF(!strcmp([obj method4], "Root(Categ)::-method4")); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/method-20.mm b/gcc/testsuite/obj-c++.dg/method-20.mm new file mode 100644 index 00000000000..96982254aa9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-20.mm @@ -0,0 +1,17 @@ +/* Test if context-sensitive "in", "out", "byref", etc., qualifiers can be + used as method selectors. */ +/* Author: Ziemowit Laski . */ +/* { dg-do compile } */ + +@interface Foo +- (void)insertNewButtonImage:(Foo *)newButtonImage in:(Foo *)buttonCell; ++ (oneway void)oneway:(int)i2 byref:(int)i3 out:(float)f4 bycopy:(float)f5; +@end + +@implementation Foo +- (void)insertNewButtonImage:(Foo *)newButtonImage in:(Foo *)buttonCell { } ++ (oneway void)oneway:(int)i2 byref:(int)i3 out:(float)f4 bycopy:(float)f5 { } +@end + +/* { dg-final { scan-assembler "insertNewButtonImage:in:" } } */ +/* { dg-final { scan-assembler "oneway:byref:out:bycopy:" } } */ diff --git a/gcc/testsuite/obj-c++.dg/method-21.mm b/gcc/testsuite/obj-c++.dg/method-21.mm new file mode 100644 index 00000000000..94291a5a106 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-21.mm @@ -0,0 +1,25 @@ +/* Test for spurious "may or may not return a value" warnings. */ +/* { dg-do compile } */ +/* { dg-options "-Wextra" } */ + +#include + +@interface Foo: Object +- (id) meth1; +- (void) meth2; +@end + +extern int bar; + +@implementation Foo +- (id) meth1 { + if (bar) + return [Object new]; + return; /* { dg-error "return.statement with no value" } */ +} +- (void) meth2 { + if (!bar) + return; + bar = 0; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/method-8.mm b/gcc/testsuite/obj-c++.dg/method-8.mm new file mode 100644 index 00000000000..310437a0023 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-8.mm @@ -0,0 +1,30 @@ +/* Tests of duplication. */ +/* { dg-do compile } */ + +@interface class1 +- (int) meth1; +- (void) meth1; /* { dg-error "duplicate declaration of method .\\-meth1." } */ +@end + +@interface class2 ++ (void) meth1; ++ (int) meth1; /* { dg-error "duplicate declaration of method .\\+meth1." } */ +@end + +@interface class3 +- (int) meth1; +@end + +@implementation class3 +- (int) meth1 { return 0; } /* { dg-error "previously defined here" } */ +- (int) meth1 { return 0; } /* { dg-error "redefinition of" } */ +@end + +@interface class4 ++ (void) meth1; +@end + +@implementation class4 ++ (void) meth1 {} /* { dg-error "previously defined here" } */ ++ (void) meth1 {} /* { dg-error "redefinition of" } */ +@end diff --git a/gcc/testsuite/obj-c++.dg/method-9.mm b/gcc/testsuite/obj-c++.dg/method-9.mm new file mode 100644 index 00000000000..4509c4aa477 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-9.mm @@ -0,0 +1,33 @@ +/* Test for lookup of class (factory) methods. */ +/* Author: Ziemowit Laski . */ +/* { dg-do compile } */ + +@interface MyBase +- (void) rootInstanceMethod; +@end + +@interface MyIntermediate: MyBase +@end + +@interface MyDerived: MyIntermediate +- (void) instanceMethod; ++ (void) classMethod; +@end + +@implementation MyDerived +- (void) instanceMethod { +} + ++ (void) classMethod { /* If a class method is not found, the root */ + [self rootInstanceMethod]; /* class is searched for an instance method */ + [MyIntermediate rootInstanceMethod]; /* with the same name. */ + + [self instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */ + [MyDerived instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */ +} +@end + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ + diff --git a/gcc/testsuite/obj-c++.dg/objc-gc-3.mm b/gcc/testsuite/obj-c++.dg/objc-gc-3.mm new file mode 100644 index 00000000000..df0a44cd8dd --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/objc-gc-3.mm @@ -0,0 +1,63 @@ +/* Test looking up fields in superclasses in the context of write-barriers + (where component references get rewritten). */ +/* Contributed by Ziemowit Laski */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-fobjc-gc" } */ + +#include + +@class MyWindow; + +@interface MyDocument : Object { + MyWindow *_window; +} +@end + +@interface MyFileDocument : MyDocument { + struct { + unsigned int autoClose:1; + unsigned int openForUI:1; + unsigned int isClosing:1; + unsigned int needsDiskCheck:1; + unsigned int isWritable:1; + unsigned int representsFileOnDisk:1; + unsigned int RESERVED:26; + } _fdFlags; +} +@end + +@interface MyTextFileDocument : MyFileDocument { + Object *_textStorage; + struct __tfdFlags { + unsigned int immutable:1; + unsigned int lineEnding:2; + unsigned int isClosing:1; + unsigned int settingsAreSet:1; + unsigned int usesTabs:1; + unsigned int isUTF8WithBOM:1; + unsigned int wrapsLines:1; + unsigned int usingDefaultLanguage:1; + unsigned int RESERVED:23; + } _tfdFlags; + int _tabWidth; + int _indentWidth; +} +@end + +@interface MyRTFFileDocument : MyTextFileDocument +- (BOOL)readFromFile:(const char *)fileName ofType:(const char *)type; +@end + +@implementation MyRTFFileDocument +- (BOOL)readFromFile:(const char *)fileName ofType:(const char *)type { + if (_textStorage && fileName) { + [_textStorage free]; + return YES; + } else if (type) { + _textStorage = [MyRTFFileDocument new]; + return NO; + } + return (fileName && type); +} +@end diff --git a/gcc/testsuite/obj-c++.dg/try-catch-10.mm b/gcc/testsuite/obj-c++.dg/try-catch-10.mm new file mode 100644 index 00000000000..5f6daa42bf3 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-10.mm @@ -0,0 +1,25 @@ +/* Check that taking the address of a local variable marked 'volatile' + by the compiler does not generate untoward errors. */ +/* Developed by Ziemowit Laski . */ + +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile } */ + + +void foo (int *arg1, int *arg2) +{ + *arg1 = *arg2; +} + +void bar (int arg) { + int rcvr; + + @try { + rcvr = arg; + } + @finally { + int *rcvr0 = &rcvr; + foo (rcvr0, &arg); + } +} + diff --git a/gcc/testsuite/objc.dg/bitfield-5.m b/gcc/testsuite/objc.dg/bitfield-5.m new file mode 100644 index 00000000000..ddd3b03a309 --- /dev/null +++ b/gcc/testsuite/objc.dg/bitfield-5.m @@ -0,0 +1,113 @@ +/* Check ObjC class layout follows the ABI (informally) + set in the past. ObjC structs must be laid out as if + all ivars, including those inherited from superclasses, + were defined at once (i.e., any padding introduced for + superclasses should be removed). */ +/* Contributed by Ziemowit Laski . */ +/* { dg-options "-Wpadded" } */ +/* { dg-do run } */ + +#include +#include +#include + +#define CHECK_IF(expr) if(!(expr)) abort() + +enum Enum { zero, one, two, three, four }; + +@interface Base: Object { +@public + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +struct Base_0 { + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +}; /* { dg-warning "padding struct size to alignment boundary" } */ + +@interface Derived: Base { +@public + signed e: 5; + unsigned f: 4; + enum Enum g: 3; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +struct Derived_0 { + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; + signed e: 5; + int f: 4; + enum Enum g: 3; +}; /* { dg-warning "padding struct size to alignment boundary" } */ + +@interface Leaf: Derived { +@public + signed h: 2; +} /* { dg-warning "padding struct size to alignment boundary" } */ +@end + +struct Leaf_0 { + Class isa; + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; + signed e: 5; + unsigned f: 4; + enum Enum g: 3; + signed h: 2; +}; /* { dg-warning "padding struct size to alignment boundary" } */ + +/* 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" } */ +typedef struct { @defs(Leaf); } Leaf_t; /* { dg-warning "padding struct size to alignment boundary" } */ + +int main(void) +{ + struct Leaf_0 l_0; + Leaf *l = (Leaf *)&l_0; + Leaf_t *l_t = (Leaf_t *)&l_0; + + CHECK_IF(sizeof(Base_t) == sizeof(Base)); + CHECK_IF(sizeof(Derived_t) == sizeof(Derived)); + CHECK_IF(sizeof(Leaf_t) == sizeof(Leaf)); + + CHECK_IF(sizeof(struct Base_0) == sizeof(Base)); + CHECK_IF(sizeof(struct Derived_0) == sizeof(Derived)); + CHECK_IF(sizeof(struct Leaf_0) == sizeof(Leaf)); + + l_0.isa = (Class)0; + l_0.a = 3; + l_0.b = 0; + l_0.c = three; + l_0.d = 31; + l_0.e = 0; + l_0.f = 15; + l_0.g = zero; + l_0.h = -2; + + CHECK_IF(!l_t->isa); + CHECK_IF(l->a == 3 && l_t->a == 3); + CHECK_IF(!l->b && !l_t->b); + CHECK_IF(l->c == three && l_t->c == three); + CHECK_IF(l->d == 31 && l_t->d == 31); + CHECK_IF(!l->e && !l_t->e); + CHECK_IF(l->f == 15 && l_t->f == 15); + CHECK_IF(l->g == zero && l_t->g == zero); + CHECK_IF(l->h == -2 && l_t->h == -2); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/class-protocol-1.m b/gcc/testsuite/objc.dg/class-protocol-1.m index ffa2435f5c0..f97f2317962 100644 --- a/gcc/testsuite/objc.dg/class-protocol-1.m +++ b/gcc/testsuite/objc.dg/class-protocol-1.m @@ -313,9 +313,9 @@ testComptypes(void) { /* id , SomeClass * */ mc1 == objP1; objP1 == mc1; - - mc1 == objP2; /* { dg-warning "does not implement" } */ - objP2 == mc1; /* { dg-warning "does not implement" } */ + + mc1 == objP2; /* { dg-warning "lacks a cast" } */ + objP2 == mc1; /* { dg-warning "lacks a cast" } */ } { /* id , id */ obj == objP1; @@ -371,10 +371,10 @@ testComptypes(void) objP5 = objP1; /* { dg-warning "does not conform" } */ } { /* id , SomeClass * */ - mc1 = objP1; /* { dg-warning "incompatible" } */ /* FIXME: should be "" */ + mc1 = objP1; objP1 = mc1; - - mc1 = objP2; /* { dg-warning "incompatible" } */ /* FIXME: should be "does not implement" */ + + mc1 = objP2; /* { dg-warning "does not conform" } */ objP2 = mc1; /* { dg-warning "does not implement" } */ } { /* id , id */ @@ -382,8 +382,8 @@ testComptypes(void) objP1 = obj; } { /* id , Class */ - cls = objP1; /* { dg-warning "incompatible" } */ - objP1 = cls; /* { dg-warning "incompatible" } */ + cls = objP1; /* { dg-warning "distinct Objective\\-C type" } */ + objP1 = cls; /* { dg-warning "distinct Objective\\-C type" } */ } { /* id , non-ObjC */ num = objP1; /* { dg-warning "makes integer" } */ @@ -401,11 +401,11 @@ testComptypes(void) } { /* Class , SomeClass * */ /* These combinations should always elicit a warning. */ - mc1 = clsP1; /* { dg-warning "incompatible" } */ - clsP1 = mc1; /* { dg-warning "incompatible" } */ + mc1 = clsP1; /* { dg-warning "distinct Objective\\-C type" } */ + clsP1 = mc1; /* { dg-warning "distinct Objective\\-C type" } */ - mc1 = clsP2; /* { dg-warning "incompatible" } */ - clsP2 = mc1; /* { dg-warning "incompatible" } */ + mc1 = clsP2; /* { dg-warning "distinct Objective\\-C type" } */ + clsP2 = mc1; /* { dg-warning "distinct Objective\\-C type" } */ } { /* Class , id */ obj = clsP1; @@ -423,8 +423,8 @@ testComptypes(void) clsP1 = ptr; } { /* Class , id */ - clsP1 = objP1; /* { dg-warning "incompatible" } */ - objP1 = clsP1; /* { dg-warning "incompatible" } */ + clsP1 = objP1; /* { dg-warning "distinct Objective\\-C type" } */ + objP1 = clsP1; /* { dg-warning "distinct Objective\\-C type" } */ } } diff --git a/gcc/testsuite/objc.dg/comp-types-1.m b/gcc/testsuite/objc.dg/comp-types-1.m index 310b22634c0..5bf59a73cba 100644 --- a/gcc/testsuite/objc.dg/comp-types-1.m +++ b/gcc/testsuite/objc.dg/comp-types-1.m @@ -32,9 +32,9 @@ int main() /* Assigning to a 'MyClass *' variable should always generate a warning, unless done from an 'id'. */ obj_c = obj; /* Ok */ - obj_c = obj_p; /* { dg-warning "incompatible pointer type" } */ - obj_c = obj_cp; /* { dg-warning "incompatible pointer type" } */ - obj_c = obj_C; /* { dg-warning "incompatible pointer type" } */ + obj_c = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ + obj_c = obj_cp; /* { dg-warning "distinct Objective\\-C type" } */ + obj_c = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ /* Assigning to an 'id' variable should generate a warning if done from a 'MyClass *' (which doesn't implement @@ -43,14 +43,15 @@ int main() obj_p = obj; /* Ok */ obj_p = obj_c; /* { dg-warning "does not implement" } */ obj_p = obj_cp; /* Ok */ - obj_p = obj_C; /* { dg-warning "incompatible pointer type" } */ + obj_p = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ /* Assigning to a 'MyOtherClass *' variable should always generate - a warning, unless done from an 'id' */ + a warning, unless done from an 'id' or an 'id' (since + MyOtherClass implements MyProtocol). */ obj_cp = obj; /* Ok */ - obj_cp = obj_c; /* { dg-warning "incompatible pointer type" } */ - obj_cp = obj_p; /* { dg-warning "incompatible pointer type" } */ - obj_cp = obj_C; /* { dg-warning "incompatible pointer type" } */ + obj_cp = obj_c; /* { dg-warning "distinct Objective\\-C type" } */ + obj_cp = obj_p; /* Ok */ + obj_cp = obj_C; /* { dg-warning "distinct Objective\\-C type" } */ /* Any comparison involving an 'id' must be without warnings. */ if (obj == obj_p) ; /* Ok */ /*Bogus warning here in 2.95.4*/ @@ -64,8 +65,8 @@ int main() /* Any comparison between 'MyClass *' and anything which is not an 'id' must generate a warning. */ - if (obj_c == obj_p) ; /* { dg-warning "does not implement" } */ - if (obj_p == obj_c) ; /* { dg-warning "does not implement" } */ + if (obj_c == obj_p) ; /* { dg-warning "lacks a cast" } */ + if (obj_p == obj_c) ; /* { dg-warning "lacks a cast" } */ if (obj_c == obj_cp) ; /* { dg-warning "lacks a cast" } */ if (obj_cp == obj_c) ; /* { dg-warning "lacks a cast" } */ if (obj_c == obj_C) ; /* { dg-warning "lacks a cast" } */ diff --git a/gcc/testsuite/objc.dg/comp-types-10.m b/gcc/testsuite/objc.dg/comp-types-10.m new file mode 100644 index 00000000000..8cd53404f52 --- /dev/null +++ b/gcc/testsuite/objc.dg/comp-types-10.m @@ -0,0 +1,28 @@ +/* { dg-do compile } */ + +#include + +@protocol Foo +- (id)meth1; +- (id)meth2:(int)arg; +@end + +@interface Derived1: Object +@end + +@interface Derived2: Object ++ (Derived1 *)new; +@end + +id func(void) { + Object *o = [Object new]; + return o; /* { dg-warning "class .Object. does not implement the .Foo. protocol" } */ +} + +@implementation Derived2 ++ (Derived1 *)new { + Derived2 *o = [super new]; + return o; /* { dg-warning "distinct Objective\\-C type in return" } */ +} +@end + diff --git a/gcc/testsuite/objc.dg/comp-types-5.m b/gcc/testsuite/objc.dg/comp-types-5.m index f4d3dfc94e9..c112ecbe54d 100644 --- a/gcc/testsuite/objc.dg/comp-types-5.m +++ b/gcc/testsuite/objc.dg/comp-types-5.m @@ -19,8 +19,8 @@ int main() obj_cp = obj; /* Ok */ obj = obj_cp; /* Ok */ - obj_cp = obj_p; /* { dg-warning "incompatible pointer type" } */ - obj_p = obj_cp; /* Ok */ /* Spurious 2.95.4 warning here. */ + obj_cp = obj_p; /* Ok */ + obj_p = obj_cp; /* Ok */ if (obj_cp == obj) ; /* Ok */ if (obj == obj_cp) ; /* Ok */ diff --git a/gcc/testsuite/objc.dg/comp-types-6.m b/gcc/testsuite/objc.dg/comp-types-6.m index 9403b532fd3..e23558114bc 100644 --- a/gcc/testsuite/objc.dg/comp-types-6.m +++ b/gcc/testsuite/objc.dg/comp-types-6.m @@ -1,6 +1,7 @@ /* Test assignments and comparisons involving category protocols. */ /* Author: Nicola Pero . */ /* { dg-do compile } */ + #include @protocol MyProtocol @@ -23,8 +24,8 @@ int main() MyClass *obj_cp = nil; MyOtherClass *obj_cp2 = nil; - obj_cp = obj_p; /* { dg-warning "incompatible pointer type" } */ - obj_cp2 = obj_p; /* { dg-warning "incompatible pointer type" } */ + obj_cp = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ + obj_cp2 = obj_p; /* { dg-warning "distinct Objective\\-C type" } */ obj_p = obj_cp; /* Ok */ obj_p = obj_cp2; /* Ok */ diff --git a/gcc/testsuite/objc.dg/comp-types-9.m b/gcc/testsuite/objc.dg/comp-types-9.m new file mode 100644 index 00000000000..3abcde5bec6 --- /dev/null +++ b/gcc/testsuite/objc.dg/comp-types-9.m @@ -0,0 +1,19 @@ +/* Yet another mysterious gimplifier crasher. */ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +@class NSString; +@protocol NSObject +@end +@interface NSObject { +} +@end +void __setRetained(id *ivar, id value) { + *ivar = value; +} +static NSString *_logProcessPrefix = 0; +@implementation NSObject (ScopeAdditions) ++ (void)setObjectLogProcessPrefix:(NSString *)processPrefix { + __setRetained(&_logProcessPrefix, processPrefix); +} +@end diff --git a/gcc/testsuite/objc.dg/layout-1.m b/gcc/testsuite/objc.dg/layout-1.m new file mode 100644 index 00000000000..6fb114217ab --- /dev/null +++ b/gcc/testsuite/objc.dg/layout-1.m @@ -0,0 +1,15 @@ +/* Ensure that we do not get bizarre warnings referring to + __attribute__((packed)) or some such. */ +/* { dg-do compile } */ +/* { dg-options "-Wpadded -Wpacked" } */ + +#include + +@interface Derived1: Object +{ } +@end + +@interface Derived2: Object +- (id) foo; +@end + diff --git a/gcc/testsuite/objc.dg/method-9.m b/gcc/testsuite/objc.dg/method-9.m index 28f6a1be621..ade5d64e71a 100644 --- a/gcc/testsuite/objc.dg/method-9.m +++ b/gcc/testsuite/objc.dg/method-9.m @@ -39,7 +39,7 @@ /* { dg-warning "also found .\\-\\(id\\)initWithData:\\(int\\)data." "" { target *-*-* } 15 } */ /* The following warning is a consequence of picking the "wrong" method signature. */ - /* { dg-warning "passing argument 1 of .initWithData:. from incompatible pointer type" "" { target *-*-* } 35 } */ + /* { dg-warning "passing argument 1 of .initWithData:. from distinct Objective\\-C type" "" { target *-*-* } 35 } */ return result; } @end diff --git a/gcc/testsuite/objc.dg/objc-gc-4.m b/gcc/testsuite/objc.dg/objc-gc-4.m new file mode 100644 index 00000000000..df0a44cd8dd --- /dev/null +++ b/gcc/testsuite/objc.dg/objc-gc-4.m @@ -0,0 +1,63 @@ +/* Test looking up fields in superclasses in the context of write-barriers + (where component references get rewritten). */ +/* Contributed by Ziemowit Laski */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-fobjc-gc" } */ + +#include + +@class MyWindow; + +@interface MyDocument : Object { + MyWindow *_window; +} +@end + +@interface MyFileDocument : MyDocument { + struct { + unsigned int autoClose:1; + unsigned int openForUI:1; + unsigned int isClosing:1; + unsigned int needsDiskCheck:1; + unsigned int isWritable:1; + unsigned int representsFileOnDisk:1; + unsigned int RESERVED:26; + } _fdFlags; +} +@end + +@interface MyTextFileDocument : MyFileDocument { + Object *_textStorage; + struct __tfdFlags { + unsigned int immutable:1; + unsigned int lineEnding:2; + unsigned int isClosing:1; + unsigned int settingsAreSet:1; + unsigned int usesTabs:1; + unsigned int isUTF8WithBOM:1; + unsigned int wrapsLines:1; + unsigned int usingDefaultLanguage:1; + unsigned int RESERVED:23; + } _tfdFlags; + int _tabWidth; + int _indentWidth; +} +@end + +@interface MyRTFFileDocument : MyTextFileDocument +- (BOOL)readFromFile:(const char *)fileName ofType:(const char *)type; +@end + +@implementation MyRTFFileDocument +- (BOOL)readFromFile:(const char *)fileName ofType:(const char *)type { + if (_textStorage && fileName) { + [_textStorage free]; + return YES; + } else if (type) { + _textStorage = [MyRTFFileDocument new]; + return NO; + } + return (fileName && type); +} +@end diff --git a/gcc/testsuite/objc.dg/try-catch-9.m b/gcc/testsuite/objc.dg/try-catch-9.m new file mode 100644 index 00000000000..5f6daa42bf3 --- /dev/null +++ b/gcc/testsuite/objc.dg/try-catch-9.m @@ -0,0 +1,25 @@ +/* Check that taking the address of a local variable marked 'volatile' + by the compiler does not generate untoward errors. */ +/* Developed by Ziemowit Laski . */ + +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile } */ + + +void foo (int *arg1, int *arg2) +{ + *arg1 = *arg2; +} + +void bar (int arg) { + int rcvr; + + @try { + rcvr = arg; + } + @finally { + int *rcvr0 = &rcvr; + foo (rcvr0, &arg); + } +} +