OSDN Git Service

* obj-c++.dg/bitfield-[1-5].mm: New.
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 May 2005 22:18:43 +0000 (22:18 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 May 2005 22:18:43 +0000 (22:18 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@100121 138bc75d-0d04-0410-961f-82ee72b054a4

50 files changed:
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/bitfield-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/bitfield-2.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/bitfield-3.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/bitfield-4.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/bitfield-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/class-protocol-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-10.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-11.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-2.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-3.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-4.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-6.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-7.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-8.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/comp-types-9.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/encode-4.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/encode-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/encode-6.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/encode-7.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/encode-8.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/layout-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-10.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-11.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-12.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-13.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-14.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-15.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-16.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-17.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-18.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-19.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-20.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-21.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-8.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/method-9.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/objc-gc-3.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/try-catch-10.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/bitfield-5.m [new file with mode: 0644]
gcc/testsuite/objc.dg/class-protocol-1.m
gcc/testsuite/objc.dg/comp-types-1.m
gcc/testsuite/objc.dg/comp-types-10.m [new file with mode: 0644]
gcc/testsuite/objc.dg/comp-types-5.m
gcc/testsuite/objc.dg/comp-types-6.m
gcc/testsuite/objc.dg/comp-types-9.m [new file with mode: 0644]
gcc/testsuite/objc.dg/layout-1.m [new file with mode: 0644]
gcc/testsuite/objc.dg/method-9.m
gcc/testsuite/objc.dg/objc-gc-4.m [new file with mode: 0644]
gcc/testsuite/objc.dg/try-catch-9.m [new file with mode: 0644]

index c3d153f..e46a771 100644 (file)
@@ -1,3 +1,27 @@
+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
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-1.mm b/gcc/testsuite/obj-c++.dg/bitfield-1.mm
new file mode 100644 (file)
index 0000000..c792025
--- /dev/null
@@ -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 <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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-2.mm b/gcc/testsuite/obj-c++.dg/bitfield-2.mm
new file mode 100644 (file)
index 0000000..7f778b5
--- /dev/null
@@ -0,0 +1,78 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-3.mm b/gcc/testsuite/obj-c++.dg/bitfield-3.mm
new file mode 100644 (file)
index 0000000..d607a3e
--- /dev/null
@@ -0,0 +1,57 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-4.mm b/gcc/testsuite/obj-c++.dg/bitfield-4.mm
new file mode 100644 (file)
index 0000000..4aa2a8b
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/bitfield-5.mm b/gcc/testsuite/obj-c++.dg/bitfield-5.mm
new file mode 100644 (file)
index 0000000..b6716df
--- /dev/null
@@ -0,0 +1,29 @@
+
+/* Make sure that bitfield types are printed correctly, and that ivar redeclaration
+  (@interface vs. @implementation) checks take the bitfield width into account.  */
+/* Author: Ziemowit Laski   <zlaski@apple.com>  */
+/* { dg-do compile } */
+
+@interface Base {
+  int i;
+}
+@end
+
+@interface WithBitfields: Base {
+  void *isa;
+  unsigned a: 3;
+  signed b: 4;
+  int c: 5;
+}
+@end
+
+@implementation WithBitfields {
+  char *isa;  /* { dg-error "conflicting instance variable type .char \\*isa." } */
+  /* { dg-error "previous declaration of .void \\*isa." "" { target *-*-* } 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 (file)
index 0000000..b8200d0
--- /dev/null
@@ -0,0 +1,442 @@
+
+/* Check Class <protocol> types */
+/* Author: David Ayers <d.ayers@inode.at> */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+#include <objc/objc-api.h>
+
+@protocol MyProto1
++(void)doItClass1;
+-(void)doItInstance1;
+@end
+
+@protocol MyProto2
++(void)doItClass2;
+-(void)doItInstance2;
+@end
+
+@interface MyClass1 <MyProto1>
+{
+  Class isa;
+}
+@end
+@implementation MyClass1
++(void)doItClass1{}
+-(void)doItInstance1{}
+@end
+
+@interface MyClass2 : MyClass1 <MyProto2>
+@end
+@implementation MyClass2
++(void)doItClass2{}
+-(void)doItInstance2{}
+@end
+
+@interface MyClass3
+{
+  Class isa;
+}
+@end
+@interface MyClass4 : MyClass3 <MyProto1>
+@end
+
+/*----------------------------------------*/
+
+Class cls = 0;
+Class <MyProto1> clsP1 = 0;
+Class <MyProto2> 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) <MyProto3>
+@end
+@interface MyClass2 (Category2) <MyProto4>
+@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 <MyProto1>
++(void)doItClass5;
+-(void)doItInstance5;
+@end
+
+@protocol MyProto6 <MyProto2>
++(void)doItClass6;
+-(void)doItInstance6;
+@end
+
+@interface MyClass1 (Category3) <MyProto5>
+@end
+@interface MyClass2 (Category4) <MyProto6>
+@end
+
+Class <MyProto5> clsP5 = 0;
+Class <MyProto6> 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) <FwProto>
+@end
+
+Class <FwProto> 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 <MyProto8>
++(void)doItClass9;
+-(void)doItInstance9;
+@end
+
+@interface MyClass1 (InheritedNonRoot) <MyProto9>
+@end
+
+Class <MyProto8> clsP8 = 0;
+Class <MyProto9> 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 <MyOtherProto1>
+@end
+
+Class <MyOtherProto1> 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 <MyProto1> objP1 = nil;
+id <MyProto2> objP2 = nil;
+id <MyProto5> objP5 = nil;
+int num = 0;
+void *ptr = 0;
+
+MyClass1 *mc1 = nil;
+
+void
+testComptypes(void)
+{
+  { /* id <protocol>, id <protocol>  */
+    objP1 == objP2;  /* { dg-warning "lacks a cast" } */
+    objP2 == objP1;  /* { dg-warning "lacks a cast" } */
+
+    objP1 == objP5;
+    objP5 == objP1;
+  }
+  { /* id <protocol>, SomeClass *  */
+    mc1 == objP1;
+    objP1 == mc1;
+
+    mc1 == objP2; /* { dg-warning "lacks a cast" } */
+    objP2 == mc1; /* { dg-warning "lacks a cast" } */
+  }
+  { /* id <protocol>, id  */
+    obj == objP1;
+    objP1 == obj;
+  }
+  { /* id <protocol>, Class  */
+    cls == objP1; /* { dg-warning "lacks a cast" } */
+    objP1 == cls; /* { dg-warning "lacks a cast" } */
+  }
+  { /* id <protocol>, non-ObjC  */
+    num == objP1; /* { dg-warning "between pointer" } */
+    objP1 == num; /* { dg-warning "between pointer" } */
+
+    ptr == objP1;
+    objP1 == ptr;
+  }
+  { /* Class <protocol>, Class <protocol> */
+    clsP1 == clsP2; /* { dg-warning "lacks a cast" } */
+    clsP2 == clsP1; /* { dg-warning "lacks a cast" } */
+
+    clsP1 == clsP5;
+    clsP5 == clsP1;
+  }
+  { /* Class <protocol>, SomeClass * */
+    mc1 == clsP1; /* { dg-warning "lacks a cast" } */
+    clsP1 == mc1; /* { dg-warning "lacks a cast" } */
+  }
+  { /* Class <protocol>, id */
+    obj == clsP1;
+    clsP1 == obj;
+  }
+  { /* Class <protocol>, Class */
+    cls == clsP1;
+    clsP1 == cls;
+  }
+  { /* Class <protocol>, non-ObjC */
+    num == clsP1; /* { dg-warning "between pointer" } */
+    clsP1 == num; /* { dg-warning "between pointer" } */
+
+    ptr == clsP1;
+    clsP1 == ptr;
+  }
+  { /* Class <protocol>, id <protocol> */
+    clsP1 == objP1; /* { dg-warning "lacks a cast" } */
+    objP1 == clsP1; /* { dg-warning "lacks a cast" } */
+  }
+
+  { /* id <protocol>, id <protocol>  */
+    objP1 = objP2; /* { dg-warning "does not conform" } */
+    objP2 = objP1; /* { dg-warning "does not conform" } */
+
+    objP1 = objP5;
+    objP5 = objP1; /* { dg-warning "does not conform" } */
+  }
+  { /* id <protocol>, SomeClass *  */
+    mc1 = objP1;
+    objP1 = mc1;
+
+    mc1 = objP2; /* { dg-warning "does not conform" } */
+    objP2 = mc1; /* { dg-warning "does not implement" } */
+  }
+  { /* id <protocol>, id  */
+    obj = objP1;
+    objP1 = obj;
+  }
+  { /* id <protocol>, Class  */
+    cls = objP1; /* { dg-warning "distinct Objective\\-C type" } */
+    objP1 = cls; /* { dg-warning "distinct Objective\\-C type" } */
+  }
+  { /* id <protocol>, non-ObjC  */
+    num = objP1; /* { dg-error "invalid conversion" } */
+    objP1 = num; /* { dg-error "invalid conversion" } */
+
+    ptr = objP1;
+    objP1 = ptr; /* { dg-error "invalid conversion" } */
+  }
+  { /* Class <protocol>, Class <protocol> */
+    clsP1 = clsP2; /* { dg-warning "does not conform" } */
+    clsP2 = clsP1; /* { dg-warning "does not conform" } */
+
+    clsP1 = clsP5;
+    clsP5 = clsP1; /* { dg-warning "does not conform" } */
+  }
+  { /* Class <protocol>, 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 <protocol>, id */
+    obj = clsP1;
+    clsP1 = obj;
+  }
+  { /* Class <protocol>, Class */
+    cls = clsP1;
+    clsP1 = cls;
+  }
+  { /* Class <protocol>, non-ObjC */
+    num = clsP1; /* { dg-error "invalid conversion" } */
+    clsP1 = num; /* { dg-error "invalid conversion" } */
+
+    ptr = clsP1;
+    clsP1 = ptr; /* { dg-error "invalid conversion" } */
+  }
+  { /* Class <protocol>, id <protocol> */
+    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 (file)
index 0000000..3abcde5
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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
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 (file)
index 0000000..8cd5340
--- /dev/null
@@ -0,0 +1,28 @@
+/* { 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
+
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 (file)
index 0000000..0704378
--- /dev/null
@@ -0,0 +1,88 @@
+/* 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;
+}
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 (file)
index 0000000..2bea015
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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;
+}
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 (file)
index 0000000..6867f82
--- /dev/null
@@ -0,0 +1,64 @@
+/* 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;
+}
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 (file)
index 0000000..99f6772
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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;
+}
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 (file)
index 0000000..23b84ed
--- /dev/null
@@ -0,0 +1,33 @@
+/* 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;
+}
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 (file)
index 0000000..e235581
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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;
+}
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 (file)
index 0000000..490f4ff
--- /dev/null
@@ -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 (file)
index 0000000..f092c9e
--- /dev/null
@@ -0,0 +1,25 @@
+/* { 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
diff --git a/gcc/testsuite/obj-c++.dg/encode-4.mm b/gcc/testsuite/obj-c++.dg/encode-4.mm
new file mode 100644 (file)
index 0000000..25c0b50
--- /dev/null
@@ -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 <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;
+}  
diff --git a/gcc/testsuite/obj-c++.dg/encode-5.mm b/gcc/testsuite/obj-c++.dg/encode-5.mm
new file mode 100644 (file)
index 0000000..9a36326
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/encode-6.mm b/gcc/testsuite/obj-c++.dg/encode-6.mm
new file mode 100644 (file)
index 0000000..1ee1171
--- /dev/null
@@ -0,0 +1,75 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/encode-7.mm b/gcc/testsuite/obj-c++.dg/encode-7.mm
new file mode 100644 (file)
index 0000000..f2cb693
--- /dev/null
@@ -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 <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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/encode-8.mm b/gcc/testsuite/obj-c++.dg/encode-8.mm
new file mode 100644 (file)
index 0000000..5f61cb8
--- /dev/null
@@ -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 <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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/layout-1.mm b/gcc/testsuite/obj-c++.dg/layout-1.mm
new file mode 100644 (file)
index 0000000..fe8ab3d
--- /dev/null
@@ -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 <objc/Object.h>
+
+@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 (file)
index 0000000..4c7ccb8
--- /dev/null
@@ -0,0 +1,45 @@
+/* Test for sending messages to aliased classes (and instances thereof).  */
+/* Author: Ziemowit Laski <zlaski@apple.com>.  */
+/* { dg-options "-lobjc" } */
+/* { dg-do run } */
+
+#include <objc/Object.h>
+
+extern "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 (file)
index 0000000..c8d092d
--- /dev/null
@@ -0,0 +1,25 @@
+/* Check if class references (generated for the NeXT runtime) are appropriately 
+   folded.  This test is safe to run on all targets.  */
+/* Author: Ziemowit Laski <zlaski@apple.com>.  */
+/* { dg-options "-fnext-runtime" } */
+/* { dg-do compile } */
+
+#include <objc/Object.h>
+
+typedef Object ObjectTypedef1;
+typedef ObjectTypedef1 ObjectTypedef2;
+@compatibility_alias ObjectAlias1 ObjectTypedef2;
+@compatibility_alias ObjectAlias2 ObjectAlias1;
+typedef ObjectAlias2 ObjectTypedef3;
+
+void foo(void) {
+  id obj = [Object new];
+  obj = [ObjectTypedef1 new];
+  obj = [ObjectTypedef2 new];
+  obj = [ObjectTypedef3 new];
+  obj = [ObjectAlias1 new];
+  obj = [ObjectAlias2 new];
+}
+
+/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
+/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */
diff --git a/gcc/testsuite/obj-c++.dg/method-12.mm b/gcc/testsuite/obj-c++.dg/method-12.mm
new file mode 100644 (file)
index 0000000..21f4bb9
--- /dev/null
@@ -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 <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" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/method-13.mm b/gcc/testsuite/obj-c++.dg/method-13.mm
new file mode 100644 (file)
index 0000000..adf6dfe
--- /dev/null
@@ -0,0 +1,27 @@
+/* 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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/method-14.mm b/gcc/testsuite/obj-c++.dg/method-14.mm
new file mode 100644 (file)
index 0000000..4a13b7d
--- /dev/null
@@ -0,0 +1,14 @@
+/* Check if casting the receiver type causes method lookup to succeed.  This was broken
+   in Objective-C++.  */
+/* Contributed by Ziemowit Laski <zlaski@apple.com>  */
+/* { dg-do compile } */
+
+@interface A
+@end
+
+@interface B: A
+- (void)f;
+@end
+
+void g(A *p) { [(B *)p f];  }
+
diff --git a/gcc/testsuite/obj-c++.dg/method-15.mm b/gcc/testsuite/obj-c++.dg/method-15.mm
new file mode 100644 (file)
index 0000000..9d9099e
--- /dev/null
@@ -0,0 +1,43 @@
+/* Check if finding multiple signatures for a method is handled gracefully when method lookup succeeds (see also method-7.m).  */
+/* Contributed by Ziemowit Laski <zlaski@apple.com>  */
+/* { dg-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
diff --git a/gcc/testsuite/obj-c++.dg/method-16.mm b/gcc/testsuite/obj-c++.dg/method-16.mm
new file mode 100644 (file)
index 0000000..f4a9efc
--- /dev/null
@@ -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 <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 } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/method-17.mm b/gcc/testsuite/obj-c++.dg/method-17.mm
new file mode 100644 (file)
index 0000000..556830f
--- /dev/null
@@ -0,0 +1,32 @@
+/* When there is only one candidate method available, make sure the
+   compiler uses its argument/return types when constructing the
+   message sends (so that proper C/C++ argument conversions may
+   take place).  */
+/* { dg-do run } */
+
+#include <objc/Object.h>
+extern "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 (file)
index 0000000..411caac
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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
diff --git a/gcc/testsuite/obj-c++.dg/method-19.mm b/gcc/testsuite/obj-c++.dg/method-19.mm
new file mode 100644 (file)
index 0000000..55890f5
--- /dev/null
@@ -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 <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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/method-20.mm b/gcc/testsuite/obj-c++.dg/method-20.mm
new file mode 100644 (file)
index 0000000..9698225
--- /dev/null
@@ -0,0 +1,17 @@
+/* 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:" } } */
diff --git a/gcc/testsuite/obj-c++.dg/method-21.mm b/gcc/testsuite/obj-c++.dg/method-21.mm
new file mode 100644 (file)
index 0000000..94291a5
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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
diff --git a/gcc/testsuite/obj-c++.dg/method-8.mm b/gcc/testsuite/obj-c++.dg/method-8.mm
new file mode 100644 (file)
index 0000000..310437a
--- /dev/null
@@ -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 (file)
index 0000000..4509c4a
--- /dev/null
@@ -0,0 +1,33 @@
+/* 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 } */
+
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 (file)
index 0000000..df0a44c
--- /dev/null
@@ -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 <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
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 (file)
index 0000000..5f6daa4
--- /dev/null
@@ -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 <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);
+  }
+}
+
diff --git a/gcc/testsuite/objc.dg/bitfield-5.m b/gcc/testsuite/objc.dg/bitfield-5.m
new file mode 100644 (file)
index 0000000..ddd3b03
--- /dev/null
@@ -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 <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;
+}
index ffa2435..f97f231 100644 (file)
@@ -313,9 +313,9 @@ testComptypes(void)
   { /* id <protocol>, 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 <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" } */
   }
 }
 
index 310b226..5bf59a7 100644 (file)
@@ -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" } */
diff --git a/gcc/testsuite/objc.dg/comp-types-10.m b/gcc/testsuite/objc.dg/comp-types-10.m
new file mode 100644 (file)
index 0000000..8cd5340
--- /dev/null
@@ -0,0 +1,28 @@
+/* { 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
+
index f4d3dfc..c112ecb 100644 (file)
@@ -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 */
index 9403b53..e235581 100644 (file)
@@ -1,6 +1,7 @@
 /* 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 */
 
diff --git a/gcc/testsuite/objc.dg/comp-types-9.m b/gcc/testsuite/objc.dg/comp-types-9.m
new file mode 100644 (file)
index 0000000..3abcde5
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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
diff --git a/gcc/testsuite/objc.dg/layout-1.m b/gcc/testsuite/objc.dg/layout-1.m
new file mode 100644 (file)
index 0000000..6fb1142
--- /dev/null
@@ -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 <objc/Object.h>
+
+@interface Derived1: Object
+{ }
+@end
+
+@interface Derived2: Object
+- (id) foo;
+@end
+
index 28f6a1b..ade5d64 100644 (file)
@@ -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 (file)
index 0000000..df0a44c
--- /dev/null
@@ -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 <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
diff --git a/gcc/testsuite/objc.dg/try-catch-9.m b/gcc/testsuite/objc.dg/try-catch-9.m
new file mode 100644 (file)
index 0000000..5f6daa4
--- /dev/null
@@ -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 <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);
+  }
+}
+