diff options
author | Ziemowit Laski <zlaski@apple.com> | 2005-05-26 01:53:56 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 2005-05-26 01:53:56 +0000 |
commit | 7cb56e5cd481d9da6400cec836eb3c69b6908cf6 (patch) | |
tree | 3eb22dddf7c7416df4c11d602f1d6f9c6c6454f4 /gcc/testsuite/obj-c++.dg | |
parent | 047c2765978683fb89087064711d1aafa3c17f0e (diff) | |
download | gcc-7cb56e5cd481d9da6400cec836eb3c69b6908cf6.zip gcc-7cb56e5cd481d9da6400cec836eb3c69b6908cf6.tar.gz gcc-7cb56e5cd481d9da6400cec836eb3c69b6908cf6.tar.bz2 |
next_mapping.h: Update for C++.
* objc/execute/next_mapping.h: Update for C++.
* obj-c++.dg/selector-1.mm: Move to...
* obj-c++.dg/selector-4.mm: here...
* obj-c++.dg/comp-types-1.mm: New.
* obj-c++.dg/cxx-class-1.mm: New.
* obj-c++.dg/cxx-ivars-1.mm: New.
* obj-c++.dg/cxx-ivars-2.mm: New.
* obj-c++.dg/cxx-ivars-3.mm: New.
* obj-c++.dg/cxx-scope-1.mm: New.
* obj-c++.dg/cxx-scope-2.mm: New.
* obj-c++.dg/defs.mm: New.
* obj-c++.dg/empty-private-1.mm: New.
* obj-c++.dg/encode-1.mm: New.
* obj-c++.dg/encode-2.mm: New.
* obj-c++.dg/encode-3.mm: New.
* obj-c++.dg/extern-c-1.mm: New.
* obj-c++.dg/extra-semi.mm: New.
* obj-c++.dg/fix-and-continue-2.mm: New.
* obj-c++.dg/isa-field-1.mm: New.
* obj-c++.dg/ivar-list-semi.mm: New.
* obj-c++.dg/local-decl-1.mm: New.
* obj-c++.dg/lookup-1.mm: New.
* obj-c++.dg/lookup-2.mm: New.
* obj-c++.dg/method-1.mm: New.
* obj-c++.dg/method-2.mm: New.
* obj-c++.dg/method-3.mm: New.
* obj-c++.dg/method-4.mm: New.
* obj-c++.dg/method-5.mm: New.
* obj-c++.dg/method-6.mm: New.
* obj-c++.dg/method-7.mm: New.
* obj-c++.dg/no-extra-load.mm: New.
* obj-c++.dg/overload-1.mm: New.
* obj-c++.dg/pragma-1.mm: New.
* obj-c++.dg/pragma-2.mm: New.
* obj-c++.dg/private-1.mm: New.
* obj-c++.dg/private-2.mm: New.
* obj-c++.dg/proto-qual-1.mm: New.
* obj-c++.dg/qual-types-1.mm: New.
* obj-c++.dg/stubify-1.mm: New.
* obj-c++.dg/stubify-2.mm: New.
* obj-c++.dg/super-class-1.mm: New.
* obj-c++.dg/super-class-2.mm: New.
* obj-c++.dg/super-dealloc-1.mm: New.
* obj-c++.dg/super-dealloc-2.mm: New.
* obj-c++.dg/template-1.mm: New.
* obj-c++.dg/template-2.mm: New.
* obj-c++.dg/template-3.mm: New.
* obj-c++.dg/template-4.mm: New.
* obj-c++.dg/template-5.mm: New.
* obj-c++.dg/template-6.mm: New.
* obj-c++.dg/try-catch-1.mm: New.
* obj-c++.dg/try-catch-2.mm: New.
* obj-c++.dg/try-catch-3.mm: New.
* obj-c++.dg/try-catch-4.mm: New.
* obj-c++.dg/try-catch-5.mm: New.
* obj-c++.dg/try-catch-6.mm: New.
* obj-c++.dg/try-catch-7.mm: New.
* obj-c++.dg/try-catch-8.mm: New.
* obj-c++.dg/try-catch-9.mm: New.
* obj-c++.dg/va-meth-1.mm: New.
Co-Authored-By: Mike Stump <mrs@apple.com>
From-SVN: r100181
Diffstat (limited to 'gcc/testsuite/obj-c++.dg')
58 files changed, 2027 insertions, 20 deletions
diff --git a/gcc/testsuite/obj-c++.dg/comp-types-1.mm b/gcc/testsuite/obj-c++.dg/comp-types-1.mm new file mode 100644 index 0000000..6d4e86e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/comp-types-1.mm @@ -0,0 +1,16 @@ +/* { dg-do compile } */ + +@interface A ++ new; +@end + +@interface B : A +@end + +int main(int argc, char **argv) { + B *b = [B new]; + A *a = b; + + return (b == a); +} + diff --git a/gcc/testsuite/obj-c++.dg/cxx-class-1.mm b/gcc/testsuite/obj-c++.dg/cxx-class-1.mm new file mode 100644 index 0000000..64fed0f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-class-1.mm @@ -0,0 +1,18 @@ +/* Test that Objective-C++ is able to chew through a simple C++ class hierarchy. + This was broken in earlier ObjC++ incarnations. */ + +struct foo +{ + foo(void *a) {}; +}; + +struct bar : foo +{ + bar() : foo((char*)0) {}; +}; + +class apple : foo +{ +public: + apple() : foo(0) { }; +}; diff --git a/gcc/testsuite/obj-c++.dg/cxx-ivars-1.mm b/gcc/testsuite/obj-c++.dg/cxx-ivars-1.mm new file mode 100644 index 0000000..6e5812c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-ivars-1.mm @@ -0,0 +1,42 @@ +// Check if ivars may be accessed via the C++ dot notation. + +// { dg-do run } +// { dg-options "-fno-objc-call-cxx-cdtors" } + +#include <objc/Object.h> +#include <stdlib.h> +#define CHECK_IF(expr) if(!(expr)) abort() + +struct cxx_struct { + int a, b; + void set_values (int _a, int _b = 3) { + a = _a; b = _b; + } + ~cxx_struct (void) { + a = b = 99; + } +}; + +@interface Manip : Object { + int c; + cxx_struct s; // { dg-warning "user-defined destructor" } + // { dg-warning "constructors and destructors will not be invoked" "" { target *-*-* } 22 } +} +- (void) manipulate_ivars; +@end + +@implementation Manip +- (void) manipulate_ivars { + s.set_values (7); + CHECK_IF (s.a == 7 && s.b == 3); + s.~cxx_struct(); + CHECK_IF (s.a == 99 && s.b == 99); +} +@end + +int main (void) +{ + Manip *obj = [Manip new]; + [obj manipulate_ivars]; + [obj free]; +} diff --git a/gcc/testsuite/obj-c++.dg/cxx-ivars-2.mm b/gcc/testsuite/obj-c++.dg/cxx-ivars-2.mm new file mode 100644 index 0000000..bf9ca6af --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-ivars-2.mm @@ -0,0 +1,76 @@ +// Check if the '- .cxx_construct' and '-.cxx_destruct' methods get called +// and if they perform their desired function. + +// { dg-do run } +// { dg-options "-fobjc-call-cxx-cdtors" } + +#include <objc/Object.h> +#include <stdlib.h> +#define CHECK_IF(expr) if(!(expr)) abort() + +static int ctor1_called, ctor2_called, dtor1_called; + +struct bar { + int a, b; + bar(void) { + a = 5; b = 6; + ctor1_called++; + } + ~bar(void) { + a = b = 99; + dtor1_called++; + } +}; + +struct boo: bar { + int c; + boo(int _c = 9): c(_c) { + ctor2_called++; + } +}; + +@interface Baz: Object { +@public + bar aa; +} +@end + +@implementation Baz +@end + +@interface Foo: Baz { +@public + int a; + boo bb; + bar b; + float c; + bar d; +} +@end + +@implementation Foo +@end + +int main (void) +{ + CHECK_IF(!ctor1_called && !ctor2_called && !dtor1_called); /* are we sane? */ + + Baz *baz = [Baz new]; + CHECK_IF(ctor1_called && !ctor2_called && !dtor1_called); + CHECK_IF(baz->aa.a == 5 && baz->aa.b == 6); + ctor1_called = 0; /* reset */ + + [baz free]; + CHECK_IF(!ctor1_called && !ctor2_called && dtor1_called); + dtor1_called = 0; /* reset */ + + Foo *foo = [Foo new]; + CHECK_IF(ctor1_called && ctor2_called && !dtor1_called); + CHECK_IF(foo->bb.a == 5 && foo->bb.b == 6 && foo->bb.c == 9); + CHECK_IF(foo->b.a == 5 && foo->b.b == 6); + CHECK_IF(foo->d.a == 5 && foo->d.b == 6); + ctor1_called = ctor2_called = 0; /* reset */ + + [foo free]; + CHECK_IF(!ctor1_called && !ctor2_called && dtor1_called); +} diff --git a/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm b/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm new file mode 100644 index 0000000..ca5e5ed --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm @@ -0,0 +1,46 @@ +// Check if ObjC classes with non-POD C++ ivars are specially marked in the metadata. + +// { dg-do run { target *-*-darwin* } } +// { dg-options "-fobjc-call-cxx-cdtors -fnext-runtime" } + +#include <objc/objc-runtime.h> +#include <stdlib.h> +#define CHECK_IF(expr) if(!(expr)) abort() + +#ifndef CLS_HAS_CXX_STRUCTORS +#define CLS_HAS_CXX_STRUCTORS 0x2000L +#endif + +struct cxx_struct { + int a, b; + cxx_struct (void) { a = b = 55; } +}; + +@interface Foo { + int c; + cxx_struct s; +} +@end + +@interface Bar: Foo { + float f; +} +@end + +@implementation Foo +@end + +@implementation Bar +@end + +int main (void) +{ + Class cls; + + cls = objc_getClass("Foo"); + CHECK_IF(cls->info & CLS_HAS_CXX_STRUCTORS); + cls = objc_getClass("Bar"); + CHECK_IF(!(cls->info & CLS_HAS_CXX_STRUCTORS)); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/cxx-scope-1.mm b/gcc/testsuite/obj-c++.dg/cxx-scope-1.mm new file mode 100644 index 0000000..952facc --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-scope-1.mm @@ -0,0 +1,53 @@ +/* Handle C++ scoping ('::') operators in ObjC message receivers gracefully. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdlib.h> + +@class Derived; + +Derived *inst[3]; + +struct CxxClass { + static Derived *get_instance(int); +}; + +Derived *CxxClass::get_instance(int offs) { + return inst[offs]; +} + +@interface Derived: Object { + int value; +} +-(id)initWithValue:(int)val; +-(int)derived_meth; +@end + +@implementation Derived +-(id)initWithValue:(int)val { + [super init]; + value = val; + return self; +} +- (int)derived_meth { + return value; +} +@end + +int main(void) { + int r; + inst[1] = [[::Derived alloc] initWithValue:7]; + inst[2] = [[Derived alloc] initWithValue:77]; + + r = [CxxClass::get_instance(2) derived_meth]; + if (r != 77) + abort(); + + r = [CxxClass::get_instance(1) derived_meth]; + if (r != 7) + abort(); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/cxx-scope-2.mm b/gcc/testsuite/obj-c++.dg/cxx-scope-2.mm new file mode 100644 index 0000000..a5bce39 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/cxx-scope-2.mm @@ -0,0 +1,19 @@ +/* Make sure Objective-C++ can distinguish ObjC classes from C++ classes. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ + +#include <objc/Object.h> +#include <iostream> +#include <string> + +@interface iostream: Object +@end + +int main(void) { + id i = [std::iostream new]; /* { dg-warning "not an Objective\\-C class name or alias" } */ + i = [iostream new]; + i = [std::basic_string<char> new]; /* { dg-warning "not an Objective\\-C class name or alias" } */ + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/defs.mm b/gcc/testsuite/obj-c++.dg/defs.mm new file mode 100644 index 0000000..3027985 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/defs.mm @@ -0,0 +1,43 @@ +/* Check @defs() in Objective-C++ */ +/* Contributed by Devang Patel <dpatel@apple.com> */ + +/* { dg-options "-lobjc" } */ +/* { dg-do run } */ + +#include <stdlib.h> +#include <objc/objc.h> +#include <objc/Object.h> + +extern void abort(void); + +@interface A : Object +{ + @public + int a; +} +@end + +struct A_defs +{ + @defs(A); +}; + +@implementation A +- init +{ + a = 42; + return self; +} +@end + + +int main() +{ + A *a = [A init]; + struct A_defs *a_defs = (struct A_defs *)a; + + if (a->a != a_defs->a) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/empty-private-1.mm b/gcc/testsuite/obj-c++.dg/empty-private-1.mm new file mode 100644 index 0000000..b8b90b0 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/empty-private-1.mm @@ -0,0 +1,9 @@ +/* Test for no entry after @private token. */ + +/* { do-do compile } */ + +@interface foo +{ +@private +} +@end diff --git a/gcc/testsuite/obj-c++.dg/encode-1.mm b/gcc/testsuite/obj-c++.dg/encode-1.mm new file mode 100644 index 0000000..c5f5ea9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-1.mm @@ -0,0 +1,23 @@ +/* Test for graceful encoding of const-qualified fields and parameters. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ + +struct Cxx { + const struct Cxx *next; +}; + +@interface ObjC { + const struct Cxx *obj; +} +- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d; +@end + +@implementation ObjC +- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d { + obj = d; + return self; +} +@end + +/* { dg-final { scan-assembler "@\[0-9\]+@0:\[0-9\]+r\\^{Cxx=\\^r{Cxx}}\[0-9\]+\\^r{Cxx}" } } */ diff --git a/gcc/testsuite/obj-c++.dg/encode-2.mm b/gcc/testsuite/obj-c++.dg/encode-2.mm new file mode 100644 index 0000000..232ac0e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-2.mm @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +template <class T> +struct Vec { + T x, y; + int z; +}; + +Vec<double> dd; +const char *enc = @encode(Vec<float>); +const char *enc2 = @encode(Vec<double>); + +/* { dg-final { scan-assembler "{Vec<float>=ffi}" } } */ +/* { dg-final { scan-assembler "{Vec<double>=ddi}" } } */ diff --git a/gcc/testsuite/obj-c++.dg/encode-3.mm b/gcc/testsuite/obj-c++.dg/encode-3.mm new file mode 100644 index 0000000..c67a972 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/encode-3.mm @@ -0,0 +1,30 @@ +/* { dg-do run } */ + +#include <stdlib.h> +#include <string.h> + +template <class T> +struct Vec { + T x, y; + long z; + long long zz; +}; + +Vec<double> dd; +const char *enc = @encode(Vec<float>); +const char *enc2 = @encode(Vec<double>); + +int main(void) { + char *encode = @encode(long); + + if (strcmp (encode, "l")) + abort(); + + if (strcmp (enc, "{Vec<float>=fflq}")) + abort(); + + if (strcmp (enc2, "{Vec<double>=ddlq}")) + abort(); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/extern-c-1.mm b/gcc/testsuite/obj-c++.dg/extern-c-1.mm new file mode 100644 index 0000000..c5fec6f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/extern-c-1.mm @@ -0,0 +1,18 @@ +/* Test extern c support inside @implementation */ +/* Devang Patel <dpatel@apple.com>. */ + +#include <objc/objc.h> + +@interface Extern +@end + +@implementation Extern + +extern "C" void NSRegisterElement(id element); + +- init { + NSRegisterElement(self); + return self; +} + +@end diff --git a/gcc/testsuite/obj-c++.dg/extra-semi.mm b/gcc/testsuite/obj-c++.dg/extra-semi.mm new file mode 100644 index 0000000..ad55596 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/extra-semi.mm @@ -0,0 +1,10 @@ +/* Allow extra semicolons in between method declarations, + for old times' sake. */ + +/* { dg-do compile } */ + +@interface Foo + -(Foo *) expiration; + -(void) setExpiration:(Foo *) date;; + -(int) getVersion; +@end diff --git a/gcc/testsuite/obj-c++.dg/fix-and-continue-2.mm b/gcc/testsuite/obj-c++.dg/fix-and-continue-2.mm new file mode 100644 index 0000000..33cb846 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/fix-and-continue-2.mm @@ -0,0 +1,24 @@ +/* Static variables, even if local, require indirect access through a stub + if -mfix-and-continue is enabled. */ + +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do assemble { target *-*-darwin* } } */ +/* { dg-options "-mfix-and-continue" } */ + +#include <objc/Object.h> + +@interface Foo: Object ++ (Object *)indexableFileTypes; +@end + +@implementation Foo ++ (Object *)indexableFileTypes +{ + static Object *fileTypes = 0; + if(!fileTypes) { + fileTypes = [Object new]; + } + return fileTypes; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/isa-field-1.mm b/gcc/testsuite/obj-c++.dg/isa-field-1.mm new file mode 100644 index 0000000..ce1d9ff --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/isa-field-1.mm @@ -0,0 +1,43 @@ +/* Ensure there are no bizarre difficulties with accessing the 'isa' field of objects. */ +/* { dg-do compile } */ + +#include <objc/Object.h> + +@interface Object (Test) +- (Class) test1: (id)object; +@end + +@interface Derived: Object +- (Class) test2: (id)object; +@end + +@implementation Object (Test) + +Class test1(id object) { + Class cls = object->isa; + return cls; +} +- (Class) test1: (id)object { + Class cls = object->isa; + return cls; +} + +@end + +@implementation Derived + +Class test2(id object) { + Class cls = object->isa; + return cls; +} +- (Class) test2: (id)object { + Class cls = object->isa; + return cls; +} + +@end + +Class test3(id object) { + Class cls = object->isa; + return cls; +} diff --git a/gcc/testsuite/obj-c++.dg/ivar-list-semi.mm b/gcc/testsuite/obj-c++.dg/ivar-list-semi.mm new file mode 100644 index 0000000..21bd3a3 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/ivar-list-semi.mm @@ -0,0 +1,12 @@ +/* Allow for an optional semicolon following the ivar block. */ +/* Contributed by: Ziemowit Laski <zlaski@apple.com>. */ + +#include <objc/Object.h> + +@interface Tink : Object { +@private + unsigned long mCode[4]; +}; +- (id)initWithProc:(void *)inProc; +- (void *)getUniqueProc; +@end diff --git a/gcc/testsuite/obj-c++.dg/local-decl-1.mm b/gcc/testsuite/obj-c++.dg/local-decl-1.mm new file mode 100644 index 0000000..0d7389d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/local-decl-1.mm @@ -0,0 +1,44 @@ +/* Test for ivar access inside of class methods. It should be allowed + (with a warning), but only if no other declarations with the same + name are seen. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do compile } */ + +#include <objc/Object.h> + +@interface Sprite: Object { + int sprite, spree; +} ++ (void)setFoo:(int)foo; ++ (void)setSprite:(int)sprite; +- (void)setFoo:(int)foo; +- (void)setSprite:(int)sprite; +@end + +int spree = 23; + +@implementation Sprite ++ (void)setFoo:(int)foo { + sprite = foo; /* { dg-warning "instance variable .sprite. accessed in class method" } */ + spree = foo; +} ++ (void)setSprite:(int)sprite { + int spree; + sprite = 15; + spree = 17; + ((Sprite *)self)->sprite = 16; /* NB: This is how one _should_ access */ + ((Sprite *)self)->spree = 18; /* ivars from within class methods! */ +} +- (void)setFoo:(int)foo { + sprite = foo; + spree = foo; +} +- (void)setSprite:(int)sprite { + int spree; + sprite = 15; /* { dg-warning "local declaration of .sprite. hides instance variable" } */ + self->sprite = 16; + spree = 17; /* { dg-warning "local declaration of .spree. hides instance variable" } */ + self->spree = 18; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/lookup-1.mm b/gcc/testsuite/obj-c++.dg/lookup-1.mm new file mode 100644 index 0000000..e149e5c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/lookup-1.mm @@ -0,0 +1,8 @@ +/* Simple test to check Objectivec-C++ qualified type lookup. */ +/* Devang Patel <dpatel@apple.com>. */ + +@interface A +{ + A *ap; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/lookup-2.mm b/gcc/testsuite/obj-c++.dg/lookup-2.mm new file mode 100644 index 0000000..f694ec9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/lookup-2.mm @@ -0,0 +1,56 @@ +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdlib.h> + +class MyWidget { + public: + int a; + MyWidget(void) { a = 17; } +}; + +MyWidget gWidget; + +@protocol MyProto +- (MyWidget *)widget; +@end + +@interface Foo: Object +@end + +@interface Bar: Foo <MyProto> +@end + +@interface Container: Object ++ (MyWidget *)elementForView:(Foo *)view; +@end + +@implementation Foo +@end + +@implementation Bar +- (MyWidget *)widget { + return &gWidget; +} +@end + +@implementation Container ++ (MyWidget *)elementForView:(Foo *)view +{ + MyWidget *widget = nil; + if ([view conformsTo:@protocol(MyProto)]) { + widget = [(Foo <MyProto> *)view widget]; + } + return widget; +} +@end + +int main(void) { + id view = [Bar new]; + MyWidget *w = [Container elementForView: view]; + + if (!w || w->a != 17) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/method-1.mm b/gcc/testsuite/obj-c++.dg/method-1.mm new file mode 100644 index 0000000..fdab6b7 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-1.mm @@ -0,0 +1,30 @@ +/* Test whether casting 'id' to a specific class removes method lookup + ambiguity. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do compile } */ + +#include <objc/objc.h> + +@class Int1, Int2; + +@interface Int1 ++ (Int1 *)classMethod1; ++ (id)classMethod2; +- (Int1 *)instanceMethod:(Int2 *)arg; /* { dg-bogus "using" } */ +@end + +@interface Int2: Int1 ++ (Int1 *)classMethod1; ++ (id)classMethod2; +- (id)int2Method; +- (int)instanceMethod:(int)arg; /* { dg-bogus "also found" } */ +@end + +int main(void) { + id i = [(Int2 *)[Int1 classMethod1] int2Method]; /* { dg-bogus "may not respond to" } */ + int j = [(Int2 *)[Int2 classMethod2] instanceMethod: 45]; /* { dg-bogus "multiple methods" } */ + /* { dg-bogus "invalid conversion" "" { target *-*-* } 25 } */ + /* { dg-bogus "invalid conversion" "" { target *-*-* } 25 } */ + return j; +} diff --git a/gcc/testsuite/obj-c++.dg/method-2.mm b/gcc/testsuite/obj-c++.dg/method-2.mm new file mode 100644 index 0000000..a76055e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-2.mm @@ -0,0 +1,56 @@ +/* Test if prior method lookup at method @implementation time is not + overly aggressive, leading to methods being found in other classes. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do compile } */ + +#include <objc/Object.h> + +@class NSString; + +@protocol NSMenuItem ++ (void)setUsesUserKeyEquivalents:(BOOL)flag; ++ (BOOL)usesUserKeyEquivalents; +@end + +@interface NSMenuItem : Object <NSMenuItem> { + @private + id _menu; +} +@end + +@interface NSResponder : Object <NSMenuItem> +{ + id _nextResponder; +} +@end + +@interface Object(NSMenuValidation) +- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem; +@end + +@interface NSResponder (NSStandardKeyBindingMethods) +- (void)insertText:(id)insertString; +- (void)doCommandBySelector:(SEL)aSelector; +@end + +@interface NSView : NSResponder +{ + id _superview; + id _subviews; +} +@end + +@interface SKTGraphicView : NSView { + @private + float _gridSpacing; +} +@end + +@implementation SKTGraphicView +- (BOOL)validateMenuItem:(NSMenuItem *)item { + return (BOOL)1; +} +- (void)insertText:(NSString *)str { +} +@end diff --git a/gcc/testsuite/obj-c++.dg/method-3.mm b/gcc/testsuite/obj-c++.dg/method-3.mm new file mode 100644 index 0000000..9dab8c5 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-3.mm @@ -0,0 +1,24 @@ +/* Do not warn about "slightly" mismatched method signatures if + -Wstrict-selector-match is off. */ + +/* { dg-do compile } */ +/* { dg-options "-Wno-strict-selector-match" } */ + +#include <objc/objc.h> + +@interface Base +- (id) meth1: (Base *)arg1; +- (id) window; +@end + +@interface Derived: Base +- (id) meth1: (Derived *)arg1; +- (Base *) window; +@end + +void foo(void) { + id r; + + [r meth1:r]; + [r window]; +} diff --git a/gcc/testsuite/obj-c++.dg/method-4.mm b/gcc/testsuite/obj-c++.dg/method-4.mm new file mode 100644 index 0000000..1d8d7ea --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-4.mm @@ -0,0 +1,24 @@ +/* Warn about "slightly" mismatched method signatures if + -Wstrict-selector-match is on. */ + +/* { dg-do compile } */ +/* { dg-options "-Wstrict-selector-match" } */ + +#include <objc/objc.h> + +@interface Base +- (id) meth1: (Base *)arg1; /* { dg-warning "using .\\-\\(id\\)meth1:\\(Base \\*\\)arg1." } */ +- (id) window; /* { dg-warning "using .\\-\\(id\\)window" } */ +@end + +@interface Derived: Base +- (id) meth1: (Derived *)arg1; /* { dg-warning "also found .\\-\\(id\\)meth1:\\(Derived \\*\\)arg1." } */ +- (Base *) window; /* { dg-warning "also found .\\-\\(Base \\*\\)window." } */ +@end + +void foo(void) { + id r; + + [r meth1:r]; /* { dg-warning "multiple methods named .\\-meth1:. found" } */ + [r window]; /* { dg-warning "multiple methods named .\\-window. found" } */ +} diff --git a/gcc/testsuite/obj-c++.dg/method-5.mm b/gcc/testsuite/obj-c++.dg/method-5.mm new file mode 100644 index 0000000..17c841a4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-5.mm @@ -0,0 +1,30 @@ +/* Do not warn about "slightly" mismatched method signatures if + -Wstrict-selector-match is off. */ + +/* { dg-do compile } */ +/* { dg-options "-Wno-strict-selector-match" } */ + +#include <objc/objc.h> + +typedef enum { en1_1, en1_2 } En1; +typedef enum { en2_1, en2_2 } En2; +typedef struct { int a, b; } St1; +typedef struct { unsigned a, b; } St2; + +@interface Base +- (id) meth1: (En1)arg1; +- (St1) window; +@end + +@interface Derived: Base +- (id) meth1: (En2)arg1; +- (St2)window; +@end + +void foo(void) { + id r; + En1 en; + + [r meth1:en]; + [r window]; +} diff --git a/gcc/testsuite/obj-c++.dg/method-6.mm b/gcc/testsuite/obj-c++.dg/method-6.mm new file mode 100644 index 0000000..5fc0d73 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-6.mm @@ -0,0 +1,19 @@ +/* The following should NOT generate "may not respond to" warnings, + since a forward-declared @class (instance) should be treated like a + 'Class') ('id'). */ + +/* { dg-do compile } */ + +#include <objc/Object.h> + +@class NotKnown; + +void foo(NotKnown *n) { + [NotKnown new]; + [n nonexistent_method]; /* { dg-warning "no .\\-nonexistent_method. method found" } */ +} + +/* { 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/method-7.mm b/gcc/testsuite/obj-c++.dg/method-7.mm new file mode 100644 index 0000000..e9e2d3a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/method-7.mm @@ -0,0 +1,21 @@ +/* Check if sending messages to "underspecified" objects is handled gracefully. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do compile } */ + +@class UnderSpecified; +typedef struct NotAClass { + int a, b; +} NotAClass; + +void foo(UnderSpecified *u, NotAClass *n) { + [n nonexistent_method]; /* { dg-warning "invalid receiver type" } */ + /* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } 12 } */ + [NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */ + [u nonexistent_method]; /* { dg-warning "no .\\-nonexistent_method. method found" } */ + [UnderSpecified nonexistent_method]; /* { dg-warning "no .\\+nonexistent_method. method found" } */ +} + +/* { 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/no-extra-load.mm b/gcc/testsuite/obj-c++.dg/no-extra-load.mm new file mode 100644 index 0000000..7b4a360 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/no-extra-load.mm @@ -0,0 +1,24 @@ +// Radar 3926484 + +// { dg-do compile } + +#include <objc/Object.h> +#include <iostream> + +@interface Greeter : Object +- (void) greet: (const char *)msg; +@end + +@implementation Greeter +- (void) greet: (const char *)msg { std::cout << msg; } +@end + +int +main () +{ + std::cout << "Hello from C++\n"; + Greeter *obj = [Greeter new]; + [obj greet: "Hello from Objective-C\n"]; +} + +/* { dg-final { scan-assembler-not "L_objc_msgSend\\\$non_lazy_ptr" } } */ diff --git a/gcc/testsuite/obj-c++.dg/overload-1.mm b/gcc/testsuite/obj-c++.dg/overload-1.mm new file mode 100644 index 0000000..d499989 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/overload-1.mm @@ -0,0 +1,11 @@ +// Make sure we can overload on ObjC classes +// Radar 3960754 + +// { dg-do compile } + +@class A, B; + +struct X { + void call(A*); + void call(B*); +}; diff --git a/gcc/testsuite/obj-c++.dg/pragma-1.mm b/gcc/testsuite/obj-c++.dg/pragma-1.mm new file mode 100644 index 0000000..3d3539e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/pragma-1.mm @@ -0,0 +1,11 @@ +/* It is OK to use #pragma inside @interface body. This test checks that. */ +/* Devang Patel <dpatel@apple.com>. */ + +@interface A +{ + int p; +} ++(int) foo; +#pragma Mark foobar +-(int) bar; +@end diff --git a/gcc/testsuite/obj-c++.dg/pragma-2.mm b/gcc/testsuite/obj-c++.dg/pragma-2.mm new file mode 100644 index 0000000..14c4d79 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/pragma-2.mm @@ -0,0 +1,23 @@ +/* It is OK to use #pragma inside @implementation body. This test checks that. */ +/* Ziemowit Laski <zlaski@apple.com>. */ + +@interface A +{ + int p; +} ++(int) foo; +-(int) bar; +@end + +@implementation A +#pragma mark - +#pragma mark init / dealloc ++ (int)foo { + return 1; +} +#pragma mark - +#pragma mark Private Functions +- (int)bar { + return 2; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/private-1.mm b/gcc/testsuite/obj-c++.dg/private-1.mm new file mode 100644 index 0000000..c4ec5ff --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/private-1.mm @@ -0,0 +1,60 @@ +/* Test errors for accessing @private and @protected variables. */ +/* Based on work by: Nicola Pero <nicola@brainstorm.co.uk>. */ + +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface MySuperClass +{ +@private + int _private; + +@protected + int _protected; + +@public + int _public; +} +- (void) test; +@end + +@implementation MySuperClass +- (void) test +{ + _private = 12; /* Ok */ + _protected = 12; /* Ok */ + _public = 12; /* Ok */ +} +@end + + +@interface MyClass : MySuperClass +@end + +@implementation MyClass +- (void) test +{ + /* Private variables simply don't exist in the subclass. */ + _private = 12; /* { dg-error "._private. was not declared in this scope" } */ + + _protected = 12; /* Ok */ + _public = 12; /* Ok */ +} +@end + +int main (void) +{ + MyClass *m = nil; + + if (m != nil) + { + int access; + + access = m->_private; /* { dg-error "is @private" } */ + access = m->_protected; /* { dg-error "is @protected" } */ + access = m->_public; /* Ok */ + } + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/private-2.mm b/gcc/testsuite/obj-c++.dg/private-2.mm new file mode 100644 index 0000000..3e6ff11 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/private-2.mm @@ -0,0 +1,56 @@ +/* Test warnings for shadowing instance variables. */ +/* Based on work by: Nicola Pero <nicola@brainstorm.co.uk>. */ + +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface MySuperClass +{ +@private + int _private; + +@protected + int _protected; + +@public + int _public; +} +- (void) test; +@end + +@implementation MySuperClass +- (void) test +{ + /* FIXME: I wonder if the warnings shouldn't be better generated + when the variable is declared, rather than used! */ + int _private = 12; + int _protected = 12; + int _public = 12; + int a; + + a = _private; /* { dg-warning "hides instance variable" } */ + a = _protected; /* { dg-warning "hides instance variable" } */ + a = _public; /* { dg-warning "hides instance variable" } */ +} +@end + + +@interface MyClass : MySuperClass +@end + +@implementation MyClass +- (void) test +{ + int _private = 12; + int _protected = 12; + int _public = 12; + int a; + + /* The private variable can be shadowed without warnings, because + * it's invisible, and not accessible, to the subclass! */ + a = _private; /* Ok */ + a = _protected; /* { dg-warning "hides instance variable" } */ + a = _public; /* { dg-warning "hides instance variable" } */ +} +@end diff --git a/gcc/testsuite/obj-c++.dg/proto-qual-1.mm b/gcc/testsuite/obj-c++.dg/proto-qual-1.mm new file mode 100644 index 0000000..d9bbf3a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/proto-qual-1.mm @@ -0,0 +1,52 @@ +/* Check that protocol qualifiers are compiled and encoded properly. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do run } */ + +#include <objc/Protocol.h> +#ifndef __NEXT_RUNTIME__ +#include <objc/objc-api.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +/* The encoded parameter sizes will be rounded up to match pointer alignment. */ +#define ROUND(s,a) (a * ((s + a - 1) / a)) +#define aligned_sizeof(T) ROUND(sizeof(T),__alignof(void *)) + +#define CHECK_IF(expr) if(!(expr)) abort() + +@protocol Retain ++ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2; +- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2; +@end + +@interface Foo <Retain> ++ (oneway void)retainArgument:(out bycopy id)arg with:(in signed char **)arg2; +@end + +@implementation Foo ++ (oneway void)retainArgument:(out bycopy id)arg1 with:(in signed char **)arg2 { } +- (bycopy) address:(byref inout id)location with:(out short unsigned **)arg2 { return nil; } +@end + +Protocol *proto = @protocol(Retain); +struct objc_method_description *meth; +unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7; + +static void scan_initial(const char *pattern) { + totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1; + sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3, + &offs4, &offs5, &offs6, &offs7); + CHECK_IF(!offs0 && offs1 == aligned_sizeof(id) && offs2 == offs1 + aligned_sizeof(SEL) && totsize >= offs2); +} + +int main(void) { + meth = [proto descriptionForInstanceMethod: @selector(address:with:)]; + scan_initial("O@%u@%u:%uNR@%uo^^S%u"); + CHECK_IF(offs3 == offs2 + aligned_sizeof(id) && totsize == offs3 + aligned_sizeof(unsigned)); + meth = [proto descriptionForClassMethod: @selector(retainArgument:with:)]; + scan_initial("Vv%u@%u:%uOo@%un^*%u"); + CHECK_IF(offs3 == offs2 + aligned_sizeof(id) && totsize == offs3 + aligned_sizeof(char **)); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/qual-types-1.mm b/gcc/testsuite/obj-c++.dg/qual-types-1.mm new file mode 100644 index 0000000..db8195c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/qual-types-1.mm @@ -0,0 +1,68 @@ +/* Test if ObjC++ can distinguish protocol qualifiers from + template arguments. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdlib.h> + +#define CHECK_IF(expr) if(!(expr)) abort() + +@protocol Zone ++ allocFromZone:(void *)zone; +- copyFromZone:(void *)zone; +@end + +@protocol Init <Zone> ++ initialize; +- init; +@end + +@interface Foo: Object +{ @public int val; } +- init; +@end + +template <class T, class U> struct X { + T x; U y; +}; + +X<int, float> xx; + +template <typename T> struct Holder +{ + T *obj; + static int counter; + Holder(void) { obj = [[T alloc] init]; } + ~Holder(void) { [obj free]; --counter; } + id <Init, Zone> getObjId(void) { return obj; } + Object <Zone, Init> *getObj(void) { return obj; } +}; + +typedef Holder <Foo <Init, Zone> > FooHolder; + +@implementation Foo +-(id) init { + [super init]; + val = ++FooHolder::counter; + return self; +} +@end + +template <typename T> +int Holder<T>::counter = 0; + +int main (void) { + CHECK_IF(FooHolder::counter == 0); + { + FooHolder holder; + CHECK_IF(holder.obj->val == 1); + CHECK_IF(FooHolder::counter == 1); + FooHolder holder2; + CHECK_IF(holder2.obj->val == 2); + CHECK_IF(FooHolder::counter == 2); + } + CHECK_IF(FooHolder::counter == 0); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/selector-1.mm b/gcc/testsuite/obj-c++.dg/selector-1.mm index b9cc5e0..d34f8c8 100644 --- a/gcc/testsuite/obj-c++.dg/selector-1.mm +++ b/gcc/testsuite/obj-c++.dg/selector-1.mm @@ -1,26 +1,30 @@ -/* Test warning for non existing selectors. */ -/* Contributed by Devang Patel <dpatel@apple.com>. */ -/* { dg-options "-Wselector -fnext-runtime" } */ -/* { dg-do compile } */ +/* Test whether including C++ keywords such as 'and', 'or', + 'not', etc., is allowed inside ObjC selectors (as it must be). */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ -typedef struct objc_object { struct objc_class *class_pointer; } *id; -typedef struct objc_selector *SEL; +/* { dg-do compile } */ -@interface Foo -- (void) foo; -- (void) bar; +@interface Int1 ++ (int)and_eq:(int)arg1 and:(int)arg2; +- (int)or_eq:(int)arg1 or:(int)arg3; +- (int)not:(int)arg1 xor:(int)arg2; +- (void)bitand:(char)c1 bitor:(char)c2; +- (void)compl:(float)f1 xor_eq:(double)d1; +- (void)not_eq; @end -@implementation Foo -- (void) bar -{ -} - -- (void) foo -{ - SEL a,b,c; - a = @selector(b1ar); /* { dg-warning "creating selector for nonexistent method .b1ar." } */ - b = @selector(bar); -} +@implementation Int1 ++ (int)and_eq:(int)arg1 and:(int)arg2 { return arg1 + arg2; } +- (int)or_eq:(int)arg1 or:(int)arg3 { return arg1 + arg3; } +- (int)not:(int)arg1 xor:(int)arg2 { return arg1 + arg2; } +- (void)bitand:(char)c1 bitor:(char)c2 { } +- (void)compl:(float)f1 xor_eq:(double)d1 { } +- (void)not_eq { } @end +/* { dg-final { scan-assembler "\\+\\\[Int1 and_eq:and:\\]|c_Int1__and_eq_and" } } */ +/* { dg-final { scan-assembler "\\-\\\[Int1 or_eq:or:\\]|i_Int1__or_eq_or" } } */ +/* { dg-final { scan-assembler "\\-\\\[Int1 not:xor:\\]|i_Int1__not_xor" } } */ +/* { dg-final { scan-assembler "\\-\\\[Int1 bitand:bitor:\\]|i_Int1__bitand_bitor" } } */ +/* { dg-final { scan-assembler "\\-\\\[Int1 compl:xor_eq:\\]|i_Int1__compl_xor_eq" } } */ +/* { dg-final { scan-assembler "\\-\\\[Int1 not_eq\\]|i_Int1__not_eq" } } */ diff --git a/gcc/testsuite/obj-c++.dg/stubify-1.mm b/gcc/testsuite/obj-c++.dg/stubify-1.mm new file mode 100644 index 0000000..dd7ce3b --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/stubify-1.mm @@ -0,0 +1,37 @@ +/* All calls must be properly stubified. Complain about any "call + _objc_msgSend<end-of-line>" without the $stub suffix. */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-Os -mdynamic-no-pic -fno-exceptions" } */ + +typedef struct objc_object { } *id ; +int x = 41 ; + +extern "C" { + extern id objc_msgSend(id self, char * op, ...); + extern int bogonic (int, int, int); +} + +@interface Document {} +- (Document *) window; +- (Document *) class; +- (Document *) close; +@end +@implementation Document +- (Document *) class { } +- (Document *) close { } +- (Document *) window { } +- (void)willEndCloseSheet:(void *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { + [[self window] close]; + ((void (*)(id, char *, int))objc_msgSend)([self class], (char *)contextInfo, 1); + ((void (*)(id, char *, int))bogonic)([self class], (char *)contextInfo, 1); + bogonic (3, 4, 5); + x++; +} +@end + +/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_objc_msgSend\n" } } */ +/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_objc_msgSend\\\$stub\n" } } */ +/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_bogonic\n" } } */ +/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_bogonic\\\$stub\n" } } */ +/* { dg-final { scan-assembler-not "\\\$non_lazy_ptr" } } */ diff --git a/gcc/testsuite/obj-c++.dg/stubify-2.mm b/gcc/testsuite/obj-c++.dg/stubify-2.mm new file mode 100644 index 0000000..0bbfd31 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/stubify-2.mm @@ -0,0 +1,31 @@ +/* All calls must be properly stubified. */ +/* Testcase extracted from TextEdit:Document.m. */ + +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump" } */ + +typedef struct objc_object { } *id ; +int x = 41 ; +extern id objc_msgSend(id self, char * op, ...); +extern int bogonic (int, int, int) ; +@interface Document {} +- (Document *) window; +- (Document *) class; +- (Document *) close; +@end +@implementation Document +- (Document *) class { } +- (Document *) close { } +- (Document *) window { } +- (void)willEndCloseSheet:(void *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { + [[self window] close]; + ((void (*)(id, char *, int))objc_msgSend)([self class], (char *)contextInfo, 1); + ((void (*)(id, char *, int))bogonic)([self class], (char *)contextInfo, 1); + bogonic (3, 4, 5); + x++; +} +@end + +/* Any symbol_ref of an un-stubified objc_msgSend is an error; look + for "objc_msgSend" in quotes, without the $stub suffix. */ +/* { dg-final { scan-file-not stubify-2.mm.03.jump "symbol_ref.*\"objc_msgSend\"" } } */ diff --git a/gcc/testsuite/obj-c++.dg/super-class-1.mm b/gcc/testsuite/obj-c++.dg/super-class-1.mm new file mode 100644 index 0000000..7887036 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/super-class-1.mm @@ -0,0 +1,30 @@ +/* Test calling super from within a category method. */ + +/* { dg-do compile } */ + +#include <objc/objc.h> + +@interface NSObject +@end +@interface NSMenuItem: NSObject +@end + +@interface NSObject (Test) ++ (int) test_func; +@end + +@implementation NSObject (Test) ++ (int) test_func +{} +@end + +@interface NSMenuItem (Test) ++ (int) test_func; +@end + +@implementation NSMenuItem (Test) ++ (int) test_func +{ + return [super test_func]; /* { dg-bogus "invalid use of undefined type" } */ +} /* { dg-bogus "forward declaration of" "" { target *-*-* } 28 } */ +@end diff --git a/gcc/testsuite/obj-c++.dg/super-class-2.mm b/gcc/testsuite/obj-c++.dg/super-class-2.mm new file mode 100644 index 0000000..41e2fd2b --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/super-class-2.mm @@ -0,0 +1,35 @@ +/* Bail out gracefully if attempting to derive from a class that has only been + forward-declared (via @class). Conversely, @compatibility_alias declarations + should be traversed to find the @interface. */ + +/* { dg-do compile } */ + +#include <objc/Object.h> + +@class MyWpModule; + +@compatibility_alias MyObject Object; +@compatibility_alias FictitiousModule MyWpModule; + +@protocol MySelTarget +- (id) meth1; +@end + +@protocol Img +- (id) meth2; +@end + +@interface FunnyModule: FictitiousModule <Img> /* { dg-error ".MyWpModule., superclass of .FunnyModule." } */ +- (id) meth2; +@end + +@interface MyProjWpModule : MyWpModule <MySelTarget, Img> /* { dg-error ".MyWpModule., superclass of .MyProjWpModule." } */ { + id i1, i2; +} +- (id) meth1; +- (id) meth2; +@end + +@interface AnotherModule: MyObject <MySelTarget> +- (id) meth1; +@end diff --git a/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm b/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm new file mode 100644 index 0000000..0ab177b --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/super-dealloc-1.mm @@ -0,0 +1,46 @@ +/* Check for warnings about missing [super dealloc] calls. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ + +@interface Foo { + void *isa; +} +- (void) dealloc; +- (void) some_other; +@end + +@interface Bar: Foo { + void *casa; +} +- (void) dealloc; +@end + +@interface Baz: Bar { + void *usa; +} +- (void) dealloc; +@end + +@implementation Foo +- (void) dealloc { + isa = 0; /* Should not warn here. */ +} +- (void) some_other { + isa = (void *)-1; +} +@end + +@implementation Bar +- (void) dealloc { + casa = 0; + [super some_other]; +} /* { dg-warning "method possibly missing a .super dealloc. call" } */ +@end + +@implementation Baz +- (void) dealloc { + usa = 0; + [super dealloc]; /* Should not warn here. */ +} +@end diff --git a/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm b/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm new file mode 100644 index 0000000..80dcf49 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/super-dealloc-2.mm @@ -0,0 +1,46 @@ +/* Check for warnings about missing [super dealloc] calls. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ + +@interface Foo { + void *isa; +} +- (void) dealloc; +- (void) some_other; +@end + +@interface Bar: Foo { + void *casa; +} +- (void) dealloc0; +@end + +@interface Baz: Bar { + void *usa; +} +- (void) dealloc; +@end + +@implementation Foo +- (void) dealloc { + isa = 0; /* Should not warn here. */ +} +- (void) some_other { + isa = (void *)-1; +} +@end + +@implementation Bar +- (void) dealloc0 { + casa = 0; + [super some_other]; /* Should not warn here. */ +} +@end + +@implementation Baz +- (void) dealloc { + usa = 0; + [super dealloc0]; +} /* { dg-warning "method possibly missing a .super dealloc. call" } */ +@end diff --git a/gcc/testsuite/obj-c++.dg/template-1.mm b/gcc/testsuite/obj-c++.dg/template-1.mm new file mode 100644 index 0000000..4b0a3df --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-1.mm @@ -0,0 +1,49 @@ +/* Test for using ObjC classes as C++ template parameters. */ +/* Author: 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) meth; +@end + +@interface Derived: Base +- (int) meth; +@end + +static int count = 0; + +template <class T> struct Templ +{ + T *m; + int i; + Templ(): i(55), m([[T alloc] init]) { count++; } + ~Templ() { [m free]; count--; } +}; + +@implementation Base +- (int) meth { return 333; } +@end + +@implementation Derived +- (int) meth { return 666; } +@end + +int main (void) { + CHECK_IF(count == 0); + { + Templ<Derived> derived; + CHECK_IF(derived.i == 55 && count == 1); + Templ<Base> base; + CHECK_IF(base.i == 55 && count == 2); + CHECK_IF([base.m meth] == 333); + CHECK_IF([derived.m meth] == 666); + } + CHECK_IF(count == 0); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/template-2.mm b/gcc/testsuite/obj-c++.dg/template-2.mm new file mode 100644 index 0000000..346dab6 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-2.mm @@ -0,0 +1,29 @@ +/* Test if ObjC classes (and pointers thereto) can participate + in C++ overloading. Correct handling of cv-qualifiers is + key here. */ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do compile } */ + +@interface foo { + int a, b; +} +@end + +struct bar { + int c, d; +}; + +template <class _Tp> +struct allocator { + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + pointer address(reference __x) const { return &__x; } + const_pointer address(const_reference __x) const { return &__x; } +}; + +allocator<bar *> b; +allocator<foo *> d; diff --git a/gcc/testsuite/obj-c++.dg/template-3.mm b/gcc/testsuite/obj-c++.dg/template-3.mm new file mode 100644 index 0000000..662e44d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-3.mm @@ -0,0 +1,80 @@ +/* Test for passing arguments to ObjC methods in the context of template + expansion. */ +/* 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 ObjCClass : Object +{ +@public + int info; +} +-(id) init; +-(id) initWithInformation: (int) whatInfo; +-(id) initWithInformation: (int) whatInfo andInfo: (int) info2; +@end + +void foo(int info) { + ObjCClass *mObj1 = [[ObjCClass alloc] init]; + ObjCClass *mObj2 = [[ObjCClass alloc] initWithInformation: info]; + ObjCClass *mObj3 = [[ObjCClass alloc] initWithInformation: info andInfo: 39]; + + CHECK_IF(mObj1->info == 666); + CHECK_IF(mObj2->info == info); + CHECK_IF(mObj3->info == info + 39); +} + +template <class WrappedObjCClass> +class ObjCObjectWrapper +{ + public: + ObjCObjectWrapper(int info); + WrappedObjCClass *mObj1, *mObj2, *mObj3; +}; + +template <class WrappedObjCClass> +ObjCObjectWrapper<WrappedObjCClass>::ObjCObjectWrapper(int info) +{ + mObj1 = [[WrappedObjCClass alloc] init]; + mObj2 = [[WrappedObjCClass alloc] initWithInformation: info]; + mObj3 = [[WrappedObjCClass alloc] initWithInformation: info andInfo: 67]; +} + +@implementation ObjCClass +-(id) init { + return [self initWithInformation:666]; +} +-(id) initWithInformation: (int) whatInfo { + [super init]; + info = whatInfo; + return self; +} +-(id) initWithInformation: (int) whatInfo andInfo: (int) info2 { + [super init]; + info = whatInfo + info2; + return self; +} +@end + +ObjCObjectWrapper<ObjCClass> staticInstance(42); + +int main(void) { + ObjCObjectWrapper<ObjCClass> stackInstance(47); + + foo(89); + + CHECK_IF(staticInstance.mObj1->info == 666); + CHECK_IF(staticInstance.mObj2->info == 42); + CHECK_IF(staticInstance.mObj3->info == 42 + 67); + + CHECK_IF(stackInstance.mObj1->info == 666); + CHECK_IF(stackInstance.mObj2->info == 47); + CHECK_IF(stackInstance.mObj3->info == 47 + 67); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/template-4.mm b/gcc/testsuite/obj-c++.dg/template-4.mm new file mode 100644 index 0000000..6500cff --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-4.mm @@ -0,0 +1,81 @@ +/* Author: Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdarg.h> +#include <stdlib.h> + +#ifdef __NEXT_RUNTIME__ +/* The following ain't pretty, but does allow us to have just one copy + of next_mapping.h. */ +#include "../objc/execute/next_mapping.h" +#else +#include <objc/NXConstStr.h> +#endif + +#define CHECK_IF(expr) if(!(expr)) abort() + +template <class ARR, class TYPE> class TestT +{ +public: + TYPE k; + int abc(ARR *array) { + return [array count] * k; + } + TestT(TYPE _k): k(_k) { } +}; + +template <class TYPE> +const char *getDesc(void) { + return [TYPE name]; +} + +@class Array; + +template <class TYPE> +int abc(TYPE *xyz, Array *array) { + return [xyz count] + [array count]; +} + +@interface Array: Object { + id *arr; + int count; +} ++ (id)arrayWithObjects:(id)first, ... ; +- (int)count; +@end + +@implementation Array ++ (id)arrayWithObjects:(id)first, ... { + Array *a = [Array new]; + a->count = 0; + a->arr = (id *) calloc(8, sizeof(id)); + + va_list args; + va_start (args, first); + + a->arr[a->count++] = first; + + for (id el; el = va_arg(args, id); a->count++) + a->arr[a->count] = el; + + return a; +} +- (int)count { + return count; +} +@end + +int main(void) { + CHECK_IF(!strcmp ([@"Object" cString], getDesc<Object>())); + CHECK_IF(!strcmp ([@"Array" cString], getDesc<Array>())); + + Array* a1 = [Array arrayWithObjects:@"One", @"Two", @"Three", nil]; + Array* a2 = [Array arrayWithObjects:@"Four", @"Five", nil]; + + TestT<Array, int> t(7); + CHECK_IF(t.abc(a1) + t.abc(a2) == 35); + CHECK_IF(abc(a1, a2) * t.k == 35); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/template-5.mm b/gcc/testsuite/obj-c++.dg/template-5.mm new file mode 100644 index 0000000..79ed57d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-5.mm @@ -0,0 +1,17 @@ +// Test that extern template does not get emitted. +// Author: Matt Austern <austern@apple.com> + +// { dg-do compile } +// { dg-options "" } +// { dg-final { scan-assembler-not ".globl __ZN3FooIiE5identEi" } } + +template <typename X> +struct Foo { + X ident(X x) { return x; } +}; + +extern template struct Foo<int>; + +int abcde(Foo<int>& foo, int n) { + return foo.ident(n); +} diff --git a/gcc/testsuite/obj-c++.dg/template-6.mm b/gcc/testsuite/obj-c++.dg/template-6.mm new file mode 100644 index 0000000..c9b82c0 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/template-6.mm @@ -0,0 +1,16 @@ +// Test that extern template does not get emitted. +// Author: Matt Austern <austern@apple.com> + +// { dg-do compile } +// { dg-options "" } +// { dg-final { scan-assembler-not ".globl __ZN3FooIiE5identEi" } } + +template <typename X> + struct Foo { X ident(X x); }; + +template <typename X> + X Foo<X>::ident(X x) { return x; } + +extern template struct Foo<int>; + +int abcde(Foo<int>& foo, int n) { return foo.ident(n); } diff --git a/gcc/testsuite/obj-c++.dg/try-catch-1.mm b/gcc/testsuite/obj-c++.dg/try-catch-1.mm new file mode 100644 index 0000000..db9b02f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-1.mm @@ -0,0 +1,42 @@ +/* Test if the compiler accepts @throw / @try..@catch..@finally syntax. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do compile } */ + +#include <objc/Object.h> +#include <stdio.h> +#include <setjmp.h> + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static int exc_control = 0; + +int proc() { + if(exc_control) { + printf ("Throwing (%d)... ", exc_control); + @throw [Frob new]; + } + return 1; +} + +int foo() +{ + @try { + return proc(); + } + @catch (Frob* ex) { + if(exc_control > 1) { + printf("Rethrowing (%d)... ", exc_control); + @throw; + } + return 0; + } + @finally { + printf("In @finally block (%d)... ", exc_control); + } +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-2.mm b/gcc/testsuite/obj-c++.dg/try-catch-2.mm new file mode 100644 index 0000000..77ef153 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-2.mm @@ -0,0 +1,78 @@ +/* Test out '@catch(id foo) {...}', which should catch + all uncaught exceptions. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fobjc-exceptions" } */ +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdio.h> + +/* The following is not required in actual user code; we include it + here to check that the compiler generates an internal definition of + _setjmp that is consistent with what <setjmp.h> provides. */ +#include <setjmp.h> + +extern "C" void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static Frob* _connection = nil; + +//-------------------------------------------------------------------- + + +void test (Object* sendPort) +{ + int cleanupPorts = 1; + Frob* receivePort = nil; + + @try { + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + receivePort = (Frob *) -1; + _connection = (Frob *) -1; + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + receivePort = nil; + sendPort = nil; + cleanupPorts = 0; + + printf ("receivePort = %p\n", receivePort); + printf ("sendPort = %p\n", sendPort); + printf ("cleanupPorts = %d\n", cleanupPorts); + printf ("---\n"); + + @throw [Object new]; + } + @catch(Frob *obj) { + printf ("Exception caught by incorrect handler!\n"); + CHECK_IF(0); + } + @catch(id exc) { + printf ("Exception caught by correct handler.\n"); + printf ("receivePort = %p (expected 0x0)\n", receivePort); + printf ("sendPort = %p (expected 0x0)\n", sendPort); + printf ("cleanupPorts = %d (expected 0)\n", cleanupPorts); + printf ("---"); + CHECK_IF(!receivePort); + CHECK_IF(!sendPort); + CHECK_IF(!cleanupPorts); + } +} + +int main (void) { + test((Object *)-1); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-3.mm b/gcc/testsuite/obj-c++.dg/try-catch-3.mm new file mode 100644 index 0000000..9341ce5 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-3.mm @@ -0,0 +1,18 @@ +/* Test if caught exception objects are accessible inside the + @catch block. (Yes, I managed to break this.) */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ +/* { dg-options "-fobjc-exceptions" } */ + +#include <objc/Object.h> + +const char *foo(void) +{ + @try { + return "foo"; + } + @catch (Object* theException) { + return [theException name]; + } +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-4.mm b/gcc/testsuite/obj-c++.dg/try-catch-4.mm new file mode 100644 index 0000000..8dc0331 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-4.mm @@ -0,0 +1,25 @@ +/* Check that the compiler does not incorrectly complain about + exceptions being caught by previous @catch blocks. */ +/* Author: Ziemowit Laski <zlaski@apple.com> */ + +/* { dg-do compile } */ +/* { dg-options "-Wall -fobjc-exceptions" } */ + +@interface Exception +@end + +@interface FooException : Exception +@end + +extern void foo(); + +void test() +{ + @try { + foo(); + } + @catch (FooException* fe) { + } + @catch (Exception* e) { + } +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-5.mm b/gcc/testsuite/obj-c++.dg/try-catch-5.mm new file mode 100644 index 0000000..f12d7e2 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-5.mm @@ -0,0 +1,26 @@ +/* Check that the compiler does correctly complain about + exceptions being caught by previous @catch blocks. */ +/* Force the use of NeXT runtime to see that we don't ICE after + generating the warning message. */ + +/* { dg-do compile } */ +/* { dg-options "-Wall -fnext-runtime -fobjc-exceptions" } */ + +@interface Exception +@end + +@interface FooException : Exception +@end + +extern void foo(); + +void test() +{ + @try { + foo(); + } + @catch (Exception* e) { /* { dg-warning "earlier handler" } */ + } + @catch (FooException* fe) { /* { dg-warning "will be caught" } */ + } +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-6.mm b/gcc/testsuite/obj-c++.dg/try-catch-6.mm new file mode 100644 index 0000000..e0022b2 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-6.mm @@ -0,0 +1,14 @@ +/* A very simple @try-@catch example. */ + +/* { dg-do compile } */ +/* { dg-options "-fobjc-exceptions" } */ + +int foo(void) { + @try { + return 2; + } + @catch (id foo) { + return 1; + } + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-7.mm b/gcc/testsuite/obj-c++.dg/try-catch-7.mm new file mode 100644 index 0000000..e322672 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-7.mm @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fobjc-exceptions" } */ + +#include <objc/Object.h> + +int main (int argc, const char * argv[]) { + Object * pool = [Object new]; + int a; + + if ( 1 ) { + @try { + a = 1; + } + @catch (Object *e) { + a = 2; + } + @finally { + a = 3; + } + } + + [pool free]; + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/try-catch-8.mm b/gcc/testsuite/obj-c++.dg/try-catch-8.mm new file mode 100644 index 0000000..b1e1cd1 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-8.mm @@ -0,0 +1,27 @@ +/* Test for graceful compilation of @synchronized statements. */ + +/* { dg-do compile } */ +/* { dg-options "-fobjc-exceptions" } */ + +#include <objc/Object.h> + +@interface Derived: Object +- (id) meth; +@end + +@implementation Derived +- (id) meth { + return self; +} + +static Derived* rewriteDict(void) { + static Derived *sDict = 0; + if (sDict == 0) { + @synchronized ([Derived class]) { + if (sDict == 0) + sDict = [Derived new]; + } + } + return sDict; +} +@end diff --git a/gcc/testsuite/obj-c++.dg/try-catch-9.mm b/gcc/testsuite/obj-c++.dg/try-catch-9.mm new file mode 100644 index 0000000..18721b4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/try-catch-9.mm @@ -0,0 +1,65 @@ +/* Check that local variables that get modified inside the @try + block survive until the @catch block is reached. */ +/* Developed by Ziemowit Laski <zlaski@apple.com>. */ + +/* { dg-options "-fobjc-exceptions -O2" } */ +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdlib.h> +#include <stdio.h> + +int gi1 = 9, gi2 = 19; +float gf1 = 9.0, gf2 = 19.0; +id obj2 = nil; + +void foo (int arg1, float *arg2) +{ + int *pi = &gi1; + float *pf = &gf1; + id obj1 = nil; + int local1 = 45, local2 = 47; + float local3 = 3.0, local4 = 4.0; + register int local5 = 15; + static float local6 = 16.0; + + @try { + local1 = 123; + local2 = 345; + local3 = 5.0; + local4 = 6.0; + local5 = 17; + local6 = 18.0; + pi = &gi2; + pf = &gf2; + obj2 = obj1 = [Object new]; + arg1 = 17; + arg2 = &gf2; + + @throw [Object new]; + } + @catch (Object *obj) { + if (local1 != 123 || local2 != 345 || local3 != 5.0 + || local4 != 6.0 || local5 != 17 || local6 != 18.0) { + printf("Abort 1\n"); + abort(); + } + if (pi != &gi2 || pf != &gf2) { + printf("Abort 2\n"); + abort(); + } + if (!obj1 || obj1 != obj2) { + printf("Abort 3\n"); + abort(); + } + if (arg1 != 17 || arg2 != &gf2) { + printf("Abort 4\n"); + abort(); + } + } +} + +int main(void) { + foo(15, &gf1); + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/va-meth-1.mm b/gcc/testsuite/obj-c++.dg/va-meth-1.mm new file mode 100644 index 0000000..6d24b7f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/va-meth-1.mm @@ -0,0 +1,74 @@ +/* Based on objc/execute/va_method.m, by Nicola Pero */ + +/* { dg-do run } */ + +#include <objc/Object.h> +#include <stdarg.h> +#include <stdlib.h> + +/* Test methods with "C-style" trailing arguments, with or without ellipsis. */ + +@interface MathClass: Object +/* sum positive numbers; -1 ends the list */ ++ (int) sum: (int) firstNumber, int secondNumber, ...; ++ (int) prod: (int) firstNumber, int secondNumber, int thirdNumber; ++ (int) minimum: (int) firstNumber, ...; +@end + +extern "C" int some_func(id self, SEL _cmd, int firstN, int secondN, int thirdN, ...) { + return firstN + secondN + thirdN; +} + +@implementation MathClass ++ (int) sum: (int) firstNumber, int secondNumber, ... +{ + va_list ap; + int sum = 0, number = 0; + + va_start (ap, secondNumber); + number = firstNumber + secondNumber; + + while (number >= 0) + { + sum += number; + number = va_arg (ap, int); + } + + va_end (ap); + + return sum; +} ++ (int) prod: (int) firstNumber, int secondNumber, int thirdNumber { + return firstNumber * secondNumber * thirdNumber; +} ++ (int) minimum: (int) firstNumber, ... +{ + va_list ap; + int minimum = 999, number = 0; + + va_start (ap, firstNumber); + number = firstNumber; + + while (number >= 0) + { + minimum = (minimum < number ? minimum: number); + number = va_arg (ap, int); + } + + va_end (ap); + + return minimum; +} +@end + +int main (void) +{ + if ([MathClass sum: 1, 2, 3, 4, 5, -1] != 15) + abort (); + if ([MathClass prod: 4, 5, 6] != 120) + abort (); + if ([MathClass minimum: 17, 9, 133, 84, 35, -1] != 9) + abort (); + + return 0; +} |