Commit d1e270fe by Ziemowit Laski Committed by Mike Stump

bitfield-[1-5].mm: New.

        * 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.

From-SVN: r100121
parent 37e0a9e8
2005-05-24 Ziemowit Laski <zlaski@apple.com>
* 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 <janis187@us.ibm.com>
* gcc.dg/altivec-vec-merge.c: Make test usable on GNU/Linux targets
......
/* 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 <zlaski@apple.com>. */
/* { dg-options "-Wpadded -Wabi" } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <stdlib.h>
#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;
}
/* Check if bitfield ivars are inherited correctly (i.e., without
being "promoted" to ints). */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
#include <objc/Object.h>
#include <stdlib.h>
#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;
}
/* Check if bitfield ivars are correctly @encode'd when
the NeXT runtime is used. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { 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;
}
/* 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/Object.h>
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;
}
/* 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 *-*-* } 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
/* Yet another mysterious gimplifier crasher. */
/* { dg-do compile } */
/* { dg-options "-O3" } */
@class NSString;
@protocol NSObject
@end
@interface NSObject <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
/* { dg-do compile } */
#include <objc/Object.h>
@protocol Foo
- (id)meth1;
- (id)meth2:(int)arg;
@end
@interface Derived1: Object
@end
@interface Derived2: Object
+ (Derived1 *)new;
@end
id<Foo> 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
/* Test various ObjC types assignments and comparisons. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol MyProtocol
- (void) foo;
@end
@interface MyClass
@end
@interface MyOtherClass <MyProtocol>
- (void) foo;
@end
int main()
{
id obj = nil;
id<MyProtocol> 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<MyProtocol>' 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<MyProtocol>' (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;
}
/* Test simple ObjC types casts. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol MyProtocol
- (void) foo;
@end
@interface MyClass
@end
int main()
{
id obj = nil;
id<MyProtocol> 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<MyProtocol>)obj;
obj_p = (id<MyProtocol>)obj_c;
obj_p = (id<MyProtocol>)obj_C;
obj_C = (Class)obj;
obj_C = (Class)obj_p;
obj_C = (Class)obj_c;
return 0;
}
/* Test assignments and comparisons between protocols (obscure case). */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol MyProtocolA
- (void) methodA;
@end
@protocol MyProtocolB
- (void) methodB;
@end
@protocol MyProtocolAB <MyProtocolA, MyProtocolB>
@end
@protocol MyProtocolAC <MyProtocolA>
- (void) methodC;
@end
int main()
{
id<MyProtocolA> obj_a = nil;
id<MyProtocolB> obj_b = nil;
id<MyProtocolAB> obj_ab = nil;
id<MyProtocolAC> 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;
}
/* Test errors for assignments and comparisons between ObjC and C++ types. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { 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
@interface MyClass
@end
int main()
{
id obj = nil;
id <MyProtocol> 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;
}
/* Test assignments and comparisons involving `one-off' protocols. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol MyProtocol
- (void) method;
@end
@interface MyClass
@end
int main()
{
id obj = nil;
id <MyProtocol> obj_p = nil;
MyClass<MyProtocol> *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;
}
/* Test assignments and comparisons involving category protocols. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@protocol MyProtocol
- (void) method;
@end
@interface MyClass
@end
@interface MyClass (Addition) <MyProtocol>
- (void) method;
@end
@interface MyOtherClass : MyClass
@end
int main()
{
id <MyProtocol> 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;
}
/* { 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
/* { dg-do compile } */
/* Another gimplifier ICE... */
#include <objc/Object.h>
@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
/* 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 <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 "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;
}
/* 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 "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;
}
/* 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 "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;
}
/* 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 <alexander@malmberg.org> */
#include <objc/Object.h>
#include <stdlib.h>
#include <stdio.h>
#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 <objc/objc-api.h>
#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;
}
/* 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 <zlaski@apple.com>. */
/* { dg-options "-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 *char_ptr = @encode(char *);
if(strcmp(BOOL_ptr, "^c"))
abort();
if(strcmp(char_ptr, "*"))
abort();
return 0;
}
/* Ensure that we do not get bizarre warnings referring to
__attribute__((packed)) or some such. */
/* { dg-do compile } */
/* { dg-options "-Wpadded -Wpacked -Wabi" } */
#include <objc/Object.h>
@interface Derived1: Object
{ }
@end
@interface Derived2: Object
- (id) foo;
@end
/* 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 "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;
}
/* 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" } } */
/* Check that sending messages to variables of type 'Class' does not involve instance methods, unless they reside in root classes. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-options "-Wstrict-selector-match" } */
/* { dg-do compile } */
#include <objc/Protocol.h>
@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" } */
}
/* Check if finding multiple signatures for a method is handled gracefully. Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-options "-Wstrict-selector-match" } */
/* { 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;
}
/* 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]; }
/* 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-options "-Wstrict-selector-match" } */
/* { 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 argument 1 of .initWithData:. from distinct Objective\\-C type" "" { target *-*-* } 33 } */
return result;
}
@end
/* 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 *-*-* } 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 } */
}
/* 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 "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;
}
/* Contributed by Igor Seleznev <selez@mail.ru>. */
/* This used to be broken. */
#include <objc/objc.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
/* 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 <zlaski@apple.com>. */
/* { dg-do run } */
#include <objc/objc.h>
#ifdef __NEXT_RUNTIME__
#include <objc/objc-runtime.h>
#define OBJC_GETCLASS objc_getClass
#else
#include <objc/objc-api.h>
#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;
}
/* Test if context-sensitive "in", "out", "byref", etc., qualifiers can be
used as method selectors. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { 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:" } } */
/* Test for spurious "may or may not return a value" warnings. */
/* { dg-do compile } */
/* { dg-options "-Wextra" } */
#include <objc/Object.h>
@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
/* 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
/* Test for lookup of class (factory) methods. */
/* Author: Ziemowit Laski <zlaski@apple.com>. */
/* { 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 } */
/* Test looking up fields in superclasses in the context of write-barriers
(where component references get rewritten). */
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-options "-fobjc-gc" } */
#include <objc/Object.h>
@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
/* Check that taking the address of a local variable marked 'volatile'
by the compiler does not generate untoward errors. */
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { 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);
}
}
/* 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 <zlaski@apple.com>. */
/* { dg-options "-Wpadded" } */
/* { dg-do run } */
#include <objc/objc.h>
#include <objc/Object.h>
#include <stdlib.h>
#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;
}
......@@ -314,8 +314,8 @@ testComptypes(void)
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 <protocol>, id */
obj == objP1;
......@@ -371,10 +371,10 @@ testComptypes(void)
objP5 = objP1; /* { dg-warning "does not conform" } */
}
{ /* id <protocol>, 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 <protocol>, id */
......@@ -382,8 +382,8 @@ testComptypes(void)
objP1 = obj;
}
{ /* id <protocol>, 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 <protocol>, non-ObjC */
num = objP1; /* { dg-warning "makes integer" } */
......@@ -401,11 +401,11 @@ testComptypes(void)
}
{ /* Class <protocol>, 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 <protocol>, id */
obj = clsP1;
......@@ -423,8 +423,8 @@ testComptypes(void)
clsP1 = ptr;
}
{ /* Class <protocol>, id <protocol> */
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" } */
}
}
......
......@@ -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<MyProtocol>' 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<MyProtocol>' (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" } */
......
/* { dg-do compile } */
#include <objc/Object.h>
@protocol Foo
- (id)meth1;
- (id)meth2:(int)arg;
@end
@interface Derived1: Object
@end
@interface Derived2: Object
+ (Derived1 *)new;
@end
id<Foo> 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
......@@ -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 */
......
/* Test assignments and comparisons involving category protocols. */
/* Author: Nicola Pero <nicola@brainstorm.co.uk>. */
/* { dg-do compile } */
#include <objc/objc.h>
@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 */
......
/* Yet another mysterious gimplifier crasher. */
/* { dg-do compile } */
/* { dg-options "-O3" } */
@class NSString;
@protocol NSObject
@end
@interface NSObject <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
/* Ensure that we do not get bizarre warnings referring to
__attribute__((packed)) or some such. */
/* { dg-do compile } */
/* { dg-options "-Wpadded -Wpacked" } */
#include <objc/Object.h>
@interface Derived1: Object
{ }
@end
@interface Derived2: Object
- (id) foo;
@end
......@@ -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
/* Test looking up fields in superclasses in the context of write-barriers
(where component references get rewritten). */
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-options "-fobjc-gc" } */
#include <objc/Object.h>
@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
/* Check that taking the address of a local variable marked 'volatile'
by the compiler does not generate untoward errors. */
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { 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);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment