From c01f56c8de151c82d958e10fa59f54dc85e9623c Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 4 Sep 2008 04:36:23 +0000 Subject: [PATCH] Add some Objective-C code generation tests. - Note that these don't really test anything other than that code generation doesn't fail or crash. Better than nothing though! llvm-svn: 55761 --- clang/test/CodeGenObjC/constant-strings.m | 4 + clang/test/CodeGenObjC/dot-syntax-1.m | 264 ++++++++++++++++++ clang/test/CodeGenObjC/dot-syntax.m | 98 +++++++ clang/test/CodeGenObjC/hidden.m | 19 ++ clang/test/CodeGenObjC/link-errors.m | 39 +++ clang/test/CodeGenObjC/messages-2.m | 139 +++++++++ clang/test/CodeGenObjC/messages.m | 21 ++ .../CodeGenObjC/predefined-expr-in-method.m | 17 ++ clang/test/CodeGenObjC/property.m | 41 +++ 9 files changed, 642 insertions(+) create mode 100644 clang/test/CodeGenObjC/constant-strings.m create mode 100644 clang/test/CodeGenObjC/dot-syntax-1.m create mode 100644 clang/test/CodeGenObjC/dot-syntax.m create mode 100644 clang/test/CodeGenObjC/hidden.m create mode 100644 clang/test/CodeGenObjC/link-errors.m create mode 100644 clang/test/CodeGenObjC/messages-2.m create mode 100644 clang/test/CodeGenObjC/messages.m create mode 100644 clang/test/CodeGenObjC/predefined-expr-in-method.m create mode 100644 clang/test/CodeGenObjC/property.m diff --git a/clang/test/CodeGenObjC/constant-strings.m b/clang/test/CodeGenObjC/constant-strings.m new file mode 100644 index 000000000000..879f91a43248 --- /dev/null +++ b/clang/test/CodeGenObjC/constant-strings.m @@ -0,0 +1,4 @@ +// RUN: clang -fnext-runtime -emit-llvm -o %t %s + +id a = @"Hello World!"; + diff --git a/clang/test/CodeGenObjC/dot-syntax-1.m b/clang/test/CodeGenObjC/dot-syntax-1.m new file mode 100644 index 000000000000..cd12d85c0ecc --- /dev/null +++ b/clang/test/CodeGenObjC/dot-syntax-1.m @@ -0,0 +1,264 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +#include + +@interface Root +-(id) alloc; +-(id) init; +@end + +// Property above methods... + +@interface Top0 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot0 : Top0 +-(int) x; +-(void) setX: (int) arg; +@end + +@implementation Top0 +-(int) _getX { + printf("-[ Top0 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top0 _setX: %d ]\n", arg); +} +@end + +@implementation Bot0 +-(int) x { + printf("-[ Bot0 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot0 _setX: %d ]\n", arg); +} +@end + +// Methods above property... + +@interface Top1 : Root +-(int) x; +-(void) setX: (int) arg; +@end + +@interface Bot1 : Top1 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top1 +-(int) x { + printf("-[ Top1 x ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top1 setX: %d ]\n", arg); +} +@end + +@implementation Bot1 +-(int) _getX { + printf("-[ Bot1 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot1 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 1) + +@interface Top2 : Root +-(int) x; +-(void) _setX: (int) arg; +@end + +@interface Bot2 : Top2 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top2 +-(int) x { + printf("-[ Top2 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top2 _setX: %d ]\n", arg); +} +@end + +@implementation Bot2 +-(int) _getX { + printf("-[ Bot2 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot2 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 2) + +@interface Top3 : Root +-(int) _getX; +-(void) setX: (int) arg; +@end + +@interface Bot3 : Top3 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top3 +-(int) _getX { + printf("-[ Top3 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top3 setX: %d ]\n", arg); +} +@end + +@implementation Bot3 +-(int) x { + printf("-[ Bot3 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot3 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 3) + +@interface Top4 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot4 : Top4 +-(int) _getX; +-(void) setX: (int) arg; +@end + +@implementation Top4 +-(int) x { + printf("-[ Top4 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top4 _setX: %d ]\n", arg); +} +@end + +@implementation Bot4 +-(int) _getX { + printf("-[ Bot4 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot4 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 4) + +@interface Top5 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot5 : Top5 +-(int) x; +-(void) _setX: (int) arg; +@end + +@implementation Top5 +-(int) _getX { + printf("-[ Top5 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top5 setX: %d ]\n", arg); +} +@end + +@implementation Bot5 +-(int) x { + printf("-[ Bot5 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot5 _setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top6 : Root +-(int) x; +@end + +@interface Bot6 : Top6 +-(void) setX: (int) arg; +@end + +@implementation Top6 +-(int) x { + printf("-[ Top6 x ]\n"); + return 0; +} +@end + +@implementation Bot6 +-(void) setX: (int) arg { + printf("-[ Bot5 setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top7 : Root +-(void) setX: (int) arg; +@end + +@interface Bot7 : Top7 +-(int) x; +@end + +@implementation Top7 +-(void) setX: (int) arg { + printf("-[ Top7 setX: %d ]\n", arg); +} +@end + +@implementation Bot7 +-(int) x { + printf("-[ Bot7 x ]\n"); + return 0; +} +@end + +// + +// FIXME: Two more (thats it?) interesting cases. Method access on +// getter w/o setter and method access on setter w/o getter. + +int main() { +#define test(N) { \ + Bot##N *ob = [[Bot##N alloc] init]; \ + int x = ob.x; \ + ob.x = 10; } + + test(0); + test(1); + test(2); + test(3); + test(4); + test(5); + // test(6); + // test(7); + + return 0; +} + diff --git a/clang/test/CodeGenObjC/dot-syntax.m b/clang/test/CodeGenObjC/dot-syntax.m new file mode 100644 index 000000000000..39e9c49309c0 --- /dev/null +++ b/clang/test/CodeGenObjC/dot-syntax.m @@ -0,0 +1,98 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +#include + +@interface Root +-(id) alloc; +-(id) init; +@end + +typedef struct { + float x, y, z[2]; +} S; + +@interface A : Root { + int myX; + // __complex myY; + S myZ; +} + +@property int x; +//@property __complex int y; +@property S z; +@end + +@implementation A +-(int) x { + printf("-[A x] = %d\n", myX); + return myX; +} +-(void) setX: (int) arg { + myX = arg; + printf("-[A setX: %d]\n", myX); +} + +// FIXME: Add back +#if 0 +-(__complex int) y { + printf("-[A y] = (%d, %d)\n", __real myY, __imag myY); + return myY; +} +-(void) setY: (__complex int) arg { + myY = arg; + printf("-[A setY: (%d, %d)]\n", __real myY, __imag myY); +} +#endif + +-(S) z { + printf("-[A z] = { %f, %f, { %f, %f } }\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); + return myZ; +} +-(void) setZ: (S) arg { + myZ = arg; + printf("-[A setZ: { %f, %f, { %f, %f } } ]\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); +} + +@end + +int main() { +#define SWAP(T,a,b) { T a_tmp = a; a = b; b = a_tmp; } + A *a = [[A alloc] init]; + A *b = [[A alloc] init]; + int a0 = 23; + // __complex a1 = 25 + 10i; + S a2 = { 246, 458, {275, 12} }; + int b0 = 42673; + // __complex b1 = 15 + 13i; + S b2 = { 26, 2, {367, 13} }; + + a.x = a0; + // a.y = a1; + a.z = a2; + + a.x += a0; + // a.y += a1; + // Yay, no compound assign of structures. A GCC extension in the + // works, perhaps? + + b.x = b0; + // b.y = b1; + b.z = b2; + + int x0 = (b.x = b0); + printf("(b.x = b0): %d\n", x0); + + // int x1 = __real (b.y = b1); + // printf("__real (b.y = b1) = %d\n", x1); + + float x2 = (b.z = b2).x; + printf("(b.z = b2).x: %f\n", x2); + + SWAP(int, a.x, b.x); + // SWAP(__complex int, a.y, b.y); + SWAP(S, a.z, b.z); + + return 0; +} diff --git a/clang/test/CodeGenObjC/hidden.m b/clang/test/CodeGenObjC/hidden.m new file mode 100644 index 000000000000..2cc3aefde49c --- /dev/null +++ b/clang/test/CodeGenObjC/hidden.m @@ -0,0 +1,19 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +__attribute__((visibility("hidden"))) +@interface Hidden ++(void) bar; +@end + +@implementation Hidden ++(void) bar {} +@end + +__attribute__((visibility("default"))) +@interface Default ++(void) bar; +@end + +@implementation Default ++(void) bar {} +@end diff --git a/clang/test/CodeGenObjC/link-errors.m b/clang/test/CodeGenObjC/link-errors.m new file mode 100644 index 000000000000..8e0a0ecde945 --- /dev/null +++ b/clang/test/CodeGenObjC/link-errors.m @@ -0,0 +1,39 @@ +// RUN: clang -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep '.lazy_reference .objc_class_name_A' %t | count 1 && +// RUN: grep '.lazy_reference .objc_class_name_Unknown' %t | count 1 && +// RUN: grep '.lazy_reference .objc_class_name_Protocol' %t | count 1 && +// RUN: clang -DWITH_IMPL -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep '.lazy_reference .objc_class_name_Root' %t | count 1 + +@interface Root +-(id) alloc; +-(id) init; +@end + +@protocol P; + +@interface A : Root +@end + +@interface A (Category) ++(void) foo; +@end + +#ifdef WITH_IMPL +@implementation A +@end +#endif + +@interface Unknown ++test; +@end + + +int main() { + id x = @protocol(P); + [ A alloc ]; + [ A foo ]; + [ Unknown test ]; + return 0; +} + diff --git a/clang/test/CodeGenObjC/messages-2.m b/clang/test/CodeGenObjC/messages-2.m new file mode 100644 index 000000000000..dcea93b8616d --- /dev/null +++ b/clang/test/CodeGenObjC/messages-2.m @@ -0,0 +1,139 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +#include + +@interface Root +@end + +typedef struct { + int x, y, z[10]; +} MyPoint; +typedef struct { + float width, height; +} MySize; + +@interface A : Root ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; ++(float) returnAFloat; ++(double) returnADouble; ++(MyPoint) returnAPoint; ++(void) printThisSize: (MySize) arg0; ++(MySize) returnASize; + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; +-(float) returnAFloat; +-(double) returnADouble; +-(MyPoint) returnAPoint; +-(void) printThisSize: (MySize) arg0; +-(MySize) returnASize; +@end +@interface B : A +@end + +@implementation A ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("(CLASS) theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} ++(float) returnAFloat { + return 15.; +} ++(double) returnADouble { + return 25.; +} ++(MyPoint) returnAPoint { + MyPoint x = { 35, 45 }; + return x; +} ++(void) printThisSize: (MySize) arg0 { + printf("(CLASS) theSize: { %f, %f }\n", + arg0.width, arg0.height); +} ++(MySize) returnASize { + MySize x = { 32, 44 }; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} +-(float) returnAFloat { + return 10.; +} +-(double) returnADouble { + return 20.; +} +-(MyPoint) returnAPoint { + MyPoint x = { 30, 40 }; + return x; +} +-(void) printThisSize: (MySize) arg0 { + printf("theSize: { %f, %f }\n", + arg0.width, arg0.height); +} +-(MySize) returnASize { + MySize x = { 22, 34 }; + return x; +} +@end + +@implementation B ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} ++(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} ++(float) returnAFloat { + return [ super returnAFloat ]*2; +} ++(double) returnADouble { + return [ super returnADouble ]*2; +} ++(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} ++(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} +-(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} +-(float) returnAFloat { + return [ super returnAFloat ]*2; +} +-(double) returnADouble { + return [ super returnADouble ]*2; +} +-(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} +-(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} +@end diff --git a/clang/test/CodeGenObjC/messages.m b/clang/test/CodeGenObjC/messages.m new file mode 100644 index 000000000000..fab3c5d85808 --- /dev/null +++ b/clang/test/CodeGenObjC/messages.m @@ -0,0 +1,21 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +typedef struct { + int x; + int y; + int z[10]; +} MyPoint; + +void f0(id a) { + int i; + MyPoint pt = { 1, 2}; + + [a print0]; + [a print1: 10]; + [a print2: 10 and: "hello" and: 2.2]; + [a takeStruct: pt ]; + + void *s = @selector(print0); + for (i=0; i<2; ++i) + [a performSelector:s]; +} diff --git a/clang/test/CodeGenObjC/predefined-expr-in-method.m b/clang/test/CodeGenObjC/predefined-expr-in-method.m new file mode 100644 index 000000000000..d835ed827b33 --- /dev/null +++ b/clang/test/CodeGenObjC/predefined-expr-in-method.m @@ -0,0 +1,17 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +@interface A +@end +@implementation A ++(void) foo { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n", __PRETTY_FUNCTION__); + return 0; +} +@end + +int main() { + [A foo]; + return 0; +} diff --git a/clang/test/CodeGenObjC/property.m b/clang/test/CodeGenObjC/property.m new file mode 100644 index 000000000000..0ec23a4d3e6c --- /dev/null +++ b/clang/test/CodeGenObjC/property.m @@ -0,0 +1,41 @@ +// RUN: clang -fnext-runtime --emit-llvm -o %t %s + +#include + +@interface Root +-(id) alloc; +-(id) init; +@end + +@interface A : Root { + int x; +} +@property int x; +@property int y; +@property int z; +@property(readonly) int ro; +@end + +@implementation A +@dynamic x; +@synthesize x; +@synthesize y = x; +@synthesize z = x; +@synthesize ro = x; +-(int) y { + return x + 1; +} +-(void) setZ: (int) arg { + x = arg - 1; +} +@end + +@interface A (Cat) +@property int dyn; +@end + +@implementation A (Cat) +-(int) dyn { + return 10; +} +@end