summaryrefslogtreecommitdiff
path: root/BlocksRuntime
diff options
context:
space:
mode:
authorBlaine Garst <blaine@apple.com>2010-08-04 23:34:21 +0000
committerBlaine Garst <blaine@apple.com>2010-08-04 23:34:21 +0000
commit86d0ba4286ec42dcd055bd22434c7f40009834bd (patch)
tree60a555b7d78f7ca88f86145c911847200a5895f7 /BlocksRuntime
parentdada27592510a7f922a3198fd1dff1e391734182 (diff)
downloadcompiler-rt-86d0ba4286ec42dcd055bd22434c7f40009834bd.tar.gz
add unit tests
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@110278 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'BlocksRuntime')
-rw-r--r--BlocksRuntime/tests/block-static.c25
-rw-r--r--BlocksRuntime/tests/blockimport.c51
-rw-r--r--BlocksRuntime/tests/byrefaccess.c34
-rw-r--r--BlocksRuntime/tests/byrefcopy.c41
-rw-r--r--BlocksRuntime/tests/byrefcopycopy.c46
-rw-r--r--BlocksRuntime/tests/byrefcopyinner.c32
-rw-r--r--BlocksRuntime/tests/byrefcopyint.c69
-rw-r--r--BlocksRuntime/tests/byrefcopystack.c41
-rw-r--r--BlocksRuntime/tests/byrefsanity.c73
-rw-r--r--BlocksRuntime/tests/byrefstruct.c57
-rw-r--r--BlocksRuntime/tests/c99.c20
-rw-r--r--BlocksRuntime/tests/cast.c37
-rw-r--r--BlocksRuntime/tests/constassign.c28
-rw-r--r--BlocksRuntime/tests/copy-block-literal-rdar6439600.c29
-rw-r--r--BlocksRuntime/tests/copyconstructor.C85
-rw-r--r--BlocksRuntime/tests/copynull.c37
-rw-r--r--BlocksRuntime/tests/dispatch_async.c57
-rw-r--r--BlocksRuntime/tests/dispatch_call_Block_with_release.c31
-rw-r--r--BlocksRuntime/tests/fail.c107
-rw-r--r--BlocksRuntime/tests/flagsisa.c21
-rw-r--r--BlocksRuntime/tests/globalexpression.c42
-rw-r--r--BlocksRuntime/tests/goto.c34
-rw-r--r--BlocksRuntime/tests/hasdescriptor.c29
-rw-r--r--BlocksRuntime/tests/josh.C32
-rw-r--r--BlocksRuntime/tests/k-and-r.c33
-rw-r--r--BlocksRuntime/tests/large-struct.c51
-rw-r--r--BlocksRuntime/tests/localisglobal.c42
-rw-r--r--BlocksRuntime/tests/macro.c14
-rw-r--r--BlocksRuntime/tests/makefile70
-rw-r--r--BlocksRuntime/tests/modglobal.c18
-rw-r--r--BlocksRuntime/tests/nestedimport.c44
-rw-r--r--BlocksRuntime/tests/nullblockisa.c43
-rw-r--r--BlocksRuntime/tests/objectRRGC.c77
-rw-r--r--BlocksRuntime/tests/objectassign.c76
-rw-r--r--BlocksRuntime/tests/orbars.c23
-rw-r--r--BlocksRuntime/tests/rdar6396238.c32
-rw-r--r--BlocksRuntime/tests/rdar6405500.c29
-rw-r--r--BlocksRuntime/tests/rdar6414583.c31
-rw-r--r--BlocksRuntime/tests/recursive-block.c55
-rw-r--r--BlocksRuntime/tests/recursive-test.c74
-rw-r--r--BlocksRuntime/tests/recursiveassign.c44
-rw-r--r--BlocksRuntime/tests/reference.C95
-rw-r--r--BlocksRuntime/tests/rettypepromotion.c36
-rw-r--r--BlocksRuntime/tests/returnfunctionptr.c23
-rw-r--r--BlocksRuntime/tests/shorthandexpression.c24
-rw-r--r--BlocksRuntime/tests/sizeof.c26
-rw-r--r--BlocksRuntime/tests/small-struct.c45
-rw-r--r--BlocksRuntime/tests/structmember.c45
-rw-r--r--BlocksRuntime/tests/testfilerunner.h110
-rw-r--r--BlocksRuntime/tests/testfilerunner.m805
-rw-r--r--BlocksRuntime/tests/varargs-bad-assign.c44
-rw-r--r--BlocksRuntime/tests/varargs.c39
-rw-r--r--BlocksRuntime/tests/variadic.c66
-rw-r--r--BlocksRuntime/tests/voidarg.c27
54 files changed, 3199 insertions, 0 deletions
diff --git a/BlocksRuntime/tests/block-static.c b/BlocksRuntime/tests/block-static.c
new file mode 100644
index 000000000..d38c816cf
--- /dev/null
+++ b/BlocksRuntime/tests/block-static.c
@@ -0,0 +1,25 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// testfilerunner CONFIG
+
+#include <stdio.h>
+
+
+int main(int argc, char **argv) {
+ static int numberOfSquesals = 5;
+
+ ^{ numberOfSquesals = 6; }();
+
+ if (numberOfSquesals == 6) {
+ printf("%s: success\n", argv[0]);
+ return 0;
+ }
+ printf("**** did not update static local, rdar://6177162\n");
+ return 1;
+
+}
+
diff --git a/BlocksRuntime/tests/blockimport.c b/BlocksRuntime/tests/blockimport.c
new file mode 100644
index 000000000..178fce439
--- /dev/null
+++ b/BlocksRuntime/tests/blockimport.c
@@ -0,0 +1,51 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * blockimport.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/13/08.
+ *
+ */
+
+
+//
+// pure C nothing more needed
+// CONFIG rdar://6289344
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+
+
+
+
+int main(int argc, char *argv[]) {
+ int i = 1;
+ int (^intblock)(void) = ^{ return i*10; };
+
+ void (^vv)(void) = ^{
+ if (argc > 0) {
+ printf("intblock returns %d\n", intblock());
+ }
+ };
+
+#if 0
+ //printf("Block dump %s\n", _Block_dump(vv));
+ {
+ struct Block_layout *layout = (struct Block_layout *)(void *)vv;
+ printf("isa %p\n", layout->isa);
+ printf("flags %x\n", layout->flags);
+ printf("descriptor %p\n", layout->descriptor);
+ printf("descriptor->size %d\n", layout->descriptor->size);
+ }
+#endif
+ void (^vvcopy)(void) = Block_copy(vv);
+ Block_release(vvcopy);
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefaccess.c b/BlocksRuntime/tests/byrefaccess.c
new file mode 100644
index 000000000..456555333
--- /dev/null
+++ b/BlocksRuntime/tests/byrefaccess.c
@@ -0,0 +1,34 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefaccess.m
+// test that byref access to locals is accurate
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+// CONFIG
+
+#include <stdio.h>
+
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ __block int i = 10;
+
+ callVoidVoid(^{ ++i; });
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefcopy.c b/BlocksRuntime/tests/byrefcopy.c
new file mode 100644
index 000000000..513b63c27
--- /dev/null
+++ b/BlocksRuntime/tests/byrefcopy.c
@@ -0,0 +1,41 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefcopy.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+
+// CONFIG
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ int __block i = 10;
+
+ void (^block)(void) = ^{ ++i; };
+ //printf("original (old style) is %s\n", _Block_dump_old(block));
+ //printf("original (new style) is %s\n", _Block_dump(block));
+ void (^blockcopy)(void) = Block_copy(block);
+ //printf("copy is %s\n", _Block_dump(blockcopy));
+ // use a copy & see that it updates i
+ callVoidVoid(block);
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefcopycopy.c b/BlocksRuntime/tests/byrefcopycopy.c
new file mode 100644
index 000000000..d6fafc152
--- /dev/null
+++ b/BlocksRuntime/tests/byrefcopycopy.c
@@ -0,0 +1,46 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6255170
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <Block.h>
+#include <Block_private.h>
+#include <assert.h>
+
+
+int
+main(int argc, char *argv[])
+{
+ __block int var = 0;
+ int shouldbe = 0;
+ void (^b)(void) = ^{ var++; /*printf("var is at %p with value %d\n", &var, var);*/ };
+ __typeof(b) _b;
+ //printf("before copy...\n");
+ b(); ++shouldbe;
+ size_t i;
+
+ for (i = 0; i < 10; i++) {
+ _b = Block_copy(b); // make a new copy each time
+ assert(_b);
+ ++shouldbe;
+ _b(); // should still update the stack
+ Block_release(_b);
+ }
+
+ //printf("after...\n");
+ b(); ++shouldbe;
+
+ if (var != shouldbe) {
+ printf("Hmm, var is %d but should be %d\n", var, shouldbe);
+ return 1;
+ }
+ printf("%s: Success!!\n", argv[0]);
+
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefcopyinner.c b/BlocksRuntime/tests/byrefcopyinner.c
new file mode 100644
index 000000000..07770933a
--- /dev/null
+++ b/BlocksRuntime/tests/byrefcopyinner.c
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <Block.h>
+#include <stdio.h>
+
+// CONFIG rdar://6225809
+// fixed in 5623
+
+int main(int argc, char *argv[]) {
+ __block int a = 42;
+ int* ap = &a; // just to keep the address on the stack.
+
+ void (^b)(void) = ^{
+ //a; // workaround, a should be implicitly imported
+ Block_copy(^{
+ a = 2;
+ });
+ };
+
+ Block_copy(b);
+
+ if(&a == ap) {
+ printf("**** __block heap storage should have been created at this point\n");
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefcopyint.c b/BlocksRuntime/tests/byrefcopyint.c
new file mode 100644
index 000000000..d632f88a0
--- /dev/null
+++ b/BlocksRuntime/tests/byrefcopyint.c
@@ -0,0 +1,69 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * byrefcopyint.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 12/1/08.
+ *
+ */
+
+//
+// byrefcopyid.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+// Tests copying of blocks with byref ints
+// CONFIG rdar://6414583 -C99
+
+#include <stdio.h>
+#include <string.h>
+#include <Block.h>
+#include <Block_private.h>
+
+
+
+
+typedef void (^voidVoid)(void);
+
+voidVoid dummy;
+
+void callVoidVoid(voidVoid closure) {
+ closure();
+}
+
+
+voidVoid testRoutine(const char *whoami) {
+ __block int dumbo = strlen(whoami);
+ dummy = ^{
+ //printf("incring dumbo from %d\n", dumbo);
+ ++dumbo;
+ };
+
+
+ voidVoid copy = Block_copy(dummy);
+
+
+ return copy;
+}
+
+int main(int argc, char *argv[]) {
+ voidVoid array[100];
+ for (int i = 0; i < 100; ++i) {
+ array[i] = testRoutine(argv[0]);
+ array[i]();
+ }
+ for (int i = 0; i < 100; ++i) {
+ Block_release(array[i]);
+ }
+
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefcopystack.c b/BlocksRuntime/tests/byrefcopystack.c
new file mode 100644
index 000000000..d119afa36
--- /dev/null
+++ b/BlocksRuntime/tests/byrefcopystack.c
@@ -0,0 +1,41 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefcopystack.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG rdar://6255170
+
+void (^bumpi)(void);
+int (^geti)(void);
+
+void setClosures() {
+ int __block i = 10;
+ bumpi = Block_copy(^{ ++i; });
+ geti = Block_copy(^{ return i; });
+}
+
+int main(int argc, char *argv[]) {
+ setClosures();
+ bumpi();
+ int i = geti();
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/byrefsanity.c b/BlocksRuntime/tests/byrefsanity.c
new file mode 100644
index 000000000..dfa16b0dd
--- /dev/null
+++ b/BlocksRuntime/tests/byrefsanity.c
@@ -0,0 +1,73 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <Block.h>
+
+int
+main(int argc, char *argv[])
+{
+ __block int var = 0;
+ void (^b)(void) = ^{ var++; };
+
+ //sanity(b);
+ b();
+ printf("%s: success!\n", argv[0]);
+ return 0;
+}
+
+
+#if 1
+/* replicated internal data structures: BEWARE, MAY CHANGE!!! */
+
+enum {
+ BLOCK_REFCOUNT_MASK = (0xffff),
+ BLOCK_NEEDS_FREE = (1 << 24),
+ BLOCK_HAS_COPY_DISPOSE = (1 << 25),
+ BLOCK_NO_COPY = (1 << 26), // interim byref: no copies allowed
+ BLOCK_IS_GC = (1 << 27),
+ BLOCK_IS_GLOBAL = (1 << 28),
+};
+
+struct byref_id {
+ struct byref_id *forwarding;
+ int flags;//refcount;
+ int size;
+ void (*byref_keep)(struct byref_id *dst, struct byref_id *src);
+ void (*byref_destroy)(struct byref_id *);
+ int var;
+};
+struct Block_basic2 {
+ void *isa;
+ int Block_flags; // int32_t
+ int Block_size; // XXX should be packed into Block_flags
+ void (*Block_invoke)(void *);
+ void (*Block_copy)(void *dst, void *src);
+ void (*Block_dispose)(void *);
+ struct byref_id *ref;
+};
+
+void sanity(void *arg) {
+ struct Block_basic2 *bb = (struct Block_basic2 *)arg;
+ if ( ! (bb->Block_flags & BLOCK_HAS_COPY_DISPOSE)) {
+ printf("missing copy/dispose helpers for byref data\n");
+ exit(1);
+ }
+ struct byref_id *ref = bb->ref;
+ if (ref->forwarding != ref) {
+ printf("forwarding pointer should be %p but is %p\n", ref, ref->forwarding);
+ exit(1);
+ }
+}
+#endif
+
+
+
diff --git a/BlocksRuntime/tests/byrefstruct.c b/BlocksRuntime/tests/byrefstruct.c
new file mode 100644
index 000000000..a3dc44e2c
--- /dev/null
+++ b/BlocksRuntime/tests/byrefstruct.c
@@ -0,0 +1,57 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ unsigned long ps[30];
+ int qs[30];
+} BobTheStruct;
+
+int main (int argc, const char * argv[]) {
+ __block BobTheStruct fiddly;
+ BobTheStruct copy;
+
+ void (^incrementFiddly)() = ^{
+ int i;
+ for(i=0; i<30; i++) {
+ fiddly.ps[i]++;
+ fiddly.qs[i]++;
+ }
+ };
+
+ memset(&fiddly, 0xA5, sizeof(fiddly));
+ memset(&copy, 0x2A, sizeof(copy));
+
+ int i;
+ for(i=0; i<30; i++) {
+ fiddly.ps[i] = i * i * i;
+ fiddly.qs[i] = -i * i * i;
+ }
+
+ copy = fiddly;
+ incrementFiddly();
+
+ if ( &copy == &fiddly ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ for(i=0; i<30; i++) {
+ //printf("[%d]: fiddly.ps: %lu, copy.ps: %lu, fiddly.qs: %d, copy.qs: %d\n", i, fiddly.ps[i], copy.ps[i], fiddly.qs[i], copy.qs[i]);
+ if ( (fiddly.ps[i] != copy.ps[i] + 1) || (fiddly.qs[i] != copy.qs[i] + 1) ) {
+ printf("%s: struct contents were not incremented.", argv[0]);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/c99.c b/BlocksRuntime/tests/c99.c
new file mode 100644
index 000000000..8f31ab3fd
--- /dev/null
+++ b/BlocksRuntime/tests/c99.c
@@ -0,0 +1,20 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// c99.m
+//
+// CONFIG C99 rdar://problem/6399225
+
+#import <stdio.h>
+#import <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ void (^blockA)(void) = ^ { ; };
+ blockA();
+ printf("%s: success\n", argv[0]);
+ exit(0);
+}
diff --git a/BlocksRuntime/tests/cast.c b/BlocksRuntime/tests/cast.c
new file mode 100644
index 000000000..5bef2c19d
--- /dev/null
+++ b/BlocksRuntime/tests/cast.c
@@ -0,0 +1,37 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * cast.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE should allow casting of a Block reference to an arbitrary pointer and back
+// CONFIG open
+
+#include <stdio.h>
+
+
+
+int main(int argc, char *argv[]) {
+
+ void (^aBlock)(void);
+ int *ip;
+ char *cp;
+ double *dp;
+
+ ip = (int *)aBlock;
+ cp = (char *)aBlock;
+ dp = (double *)aBlock;
+ aBlock = (void (^)(void))ip;
+ aBlock = (void (^)(void))cp;
+ aBlock = (void (^)(void))dp;
+ printf("%s: success", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/constassign.c b/BlocksRuntime/tests/constassign.c
new file mode 100644
index 000000000..537cb2df0
--- /dev/null
+++ b/BlocksRuntime/tests/constassign.c
@@ -0,0 +1,28 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// constassign.c
+// bocktest
+//
+// Created by Blaine Garst on 3/21/08.
+//
+// shouldn't be able to assign to a const pointer
+// CONFIG error: assignment of read-only
+
+#import <stdio.h>
+
+void foo(void) { printf("I'm in foo\n"); }
+void bar(void) { printf("I'm in bar\n"); }
+
+int main(int argc, char *argv[]) {
+ void (*const fptr)(void) = foo;
+ void (^const blockA)(void) = ^ { printf("hello\n"); };
+ blockA = ^ { printf("world\n"); } ;
+ fptr = bar;
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/copy-block-literal-rdar6439600.c b/BlocksRuntime/tests/copy-block-literal-rdar6439600.c
new file mode 100644
index 000000000..6fa488eee
--- /dev/null
+++ b/BlocksRuntime/tests/copy-block-literal-rdar6439600.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6439600
+
+#import <stdio.h>
+#import <stdlib.h>
+
+#define NUMBER_OF_BLOCKS 100
+int main (int argc, const char * argv[]) {
+ int (^x[NUMBER_OF_BLOCKS])();
+ int i;
+
+ for(i=0; i<NUMBER_OF_BLOCKS; i++) x[i] = ^{ return i; };
+
+ for(i=0; i<NUMBER_OF_BLOCKS; i++) {
+ if (x[i]() != i) {
+ printf("%s: failure, %d != %d\n", argv[0], x[i](), i);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/BlocksRuntime/tests/copyconstructor.C b/BlocksRuntime/tests/copyconstructor.C
new file mode 100644
index 000000000..626d33e80
--- /dev/null
+++ b/BlocksRuntime/tests/copyconstructor.C
@@ -0,0 +1,85 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG C++ rdar://6243400,rdar://6289367
+
+
+int constructors = 0;
+int destructors = 0;
+
+
+#define CONST const
+
+class TestObject
+{
+public:
+ TestObject(CONST TestObject& inObj);
+ TestObject();
+ ~TestObject();
+
+ TestObject& operator=(CONST TestObject& inObj);
+
+ int version() CONST { return _version; }
+private:
+ mutable int _version;
+};
+
+TestObject::TestObject(CONST TestObject& inObj)
+
+{
+ ++constructors;
+ _version = inObj._version;
+ //printf("%p (%d) -- TestObject(const TestObject&) called\n", this, _version);
+}
+
+
+TestObject::TestObject()
+{
+ _version = ++constructors;
+ //printf("%p (%d) -- TestObject() called\n", this, _version);
+}
+
+
+TestObject::~TestObject()
+{
+ //printf("%p -- ~TestObject() called\n", this);
+ ++destructors;
+}
+
+
+TestObject& TestObject::operator=(CONST TestObject& inObj)
+{
+ //printf("%p -- operator= called\n", this);
+ _version = inObj._version;
+ return *this;
+}
+
+
+
+void testRoutine() {
+ TestObject one;
+
+ void (^b)(void) = ^{ printf("my const copy of one is %d\n", one.version()); };
+}
+
+
+
+int main(int argc, char *argv[]) {
+ testRoutine();
+ if (constructors == 0) {
+ printf("No copy constructors!!!\n");
+ return 1;
+ }
+ if (constructors != destructors) {
+ printf("%d constructors but only %d destructors\n", constructors, destructors);
+ return 1;
+ }
+ printf("%s:success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/copynull.c b/BlocksRuntime/tests/copynull.c
new file mode 100644
index 000000000..c49e499f3
--- /dev/null
+++ b/BlocksRuntime/tests/copynull.c
@@ -0,0 +1,37 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * copynull.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/15/08.
+ *
+ */
+
+#import <stdio.h>
+#import <Block.h>
+#import <Block_private.h>
+
+// CONFIG rdar://6295848
+
+int main(int argc, char *argv[]) {
+
+ void (^block)(void) = (void (^)(void))0;
+ void (^blockcopy)(void) = Block_copy(block);
+
+ if (blockcopy != (void (^)(void))0) {
+ printf("whoops, somehow we copied NULL!\n");
+ return 1;
+ }
+ // make sure we can also
+ Block_release(blockcopy);
+ // and more secretly
+ //_Block_destroy(blockcopy);
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/dispatch_async.c b/BlocksRuntime/tests/dispatch_async.c
new file mode 100644
index 000000000..e3e517c54
--- /dev/null
+++ b/BlocksRuntime/tests/dispatch_async.c
@@ -0,0 +1,57 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <dispatch/dispatch.h>
+#include <unistd.h>
+//#import <Foundation/Foundation.h>
+#include <Block.h>
+
+// CONFIG rdar://problem/6371811
+
+const char *whoami = "nobody";
+
+void EnqueueStuff(dispatch_queue_t q)
+{
+ __block CFIndex counter;
+
+ // above call has a side effect: it works around:
+ // <rdar://problem/6225809> __block variables not implicitly imported into intermediate scopes
+ dispatch_async(q, ^{
+ counter = 0;
+ });
+
+
+ dispatch_async(q, ^{
+ //printf("outer block.\n");
+ counter++;
+ dispatch_async(q, ^{
+ //printf("inner block.\n");
+ counter--;
+ if(counter == 0) {
+ printf("%s: success\n", whoami);
+ exit(0);
+ }
+ });
+ if(counter == 0) {
+ printf("already done? inconceivable!\n");
+ exit(1);
+ }
+ });
+}
+
+int main (int argc, const char * argv[]) {
+ dispatch_queue_t q = dispatch_queue_create("queue", NULL);
+
+ whoami = argv[0];
+
+ EnqueueStuff(q);
+
+ dispatch_main();
+ printf("shouldn't get here\n");
+ return 1;
+}
diff --git a/BlocksRuntime/tests/dispatch_call_Block_with_release.c b/BlocksRuntime/tests/dispatch_call_Block_with_release.c
new file mode 100644
index 000000000..9e06f69ba
--- /dev/null
+++ b/BlocksRuntime/tests/dispatch_call_Block_with_release.c
@@ -0,0 +1,31 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG
+
+void callsomething(const char *format, int argument) {
+}
+
+void
+dispatch_call_Block_with_release2(void *block)
+{
+ void (^b)(void) = (void (^)(void))block;
+ b();
+ Block_release(b);
+}
+
+int main(int argc, char *argv[]) {
+ void (^b1)(void) = ^{ callsomething("argc is %d\n", argc); };
+ void (^b2)(void) = ^{ callsomething("hellow world\n", 0); }; // global block now
+
+ dispatch_call_Block_with_release2(Block_copy(b1));
+ dispatch_call_Block_with_release2(Block_copy(b2));
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/fail.c b/BlocksRuntime/tests/fail.c
new file mode 100644
index 000000000..28dbc2d15
--- /dev/null
+++ b/BlocksRuntime/tests/fail.c
@@ -0,0 +1,107 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * fail.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/16/08.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+
+bool readfile(char *buffer, const char *from) {
+ int fd = open(from, 0);
+ if (fd < 0) return false;
+ int count = read(fd, buffer, 512);
+ if (count < 0) return false;
+ buffer[count] = 0; // zap newline
+ return true;
+}
+
+// basic idea, take compiler args, run compiler, and verify that expected failure matches any existing one
+
+int main(int argc, char *argv[]) {
+ if (argc == 1) return 0;
+ char *copy[argc+1]; // make a copy
+ // find and strip off -e "errorfile"
+ char *errorfile = NULL;
+ int counter = 0, i = 0;
+ for (i = 1; i < argc; ++i) { // skip 0 arg which is "fail"
+ if (!strncmp(argv[i], "-e", 2)) {
+ errorfile = argv[++i];
+ }
+ else {
+ copy[counter++] = argv[i];
+ }
+ }
+ copy[counter] = NULL;
+ pid_t child = fork();
+ char buffer[512];
+ if (child == 0) {
+ // in child
+ sprintf(buffer, "/tmp/errorfile_%d", getpid());
+ close(1);
+ int fd = creat(buffer, 0777);
+ if (fd != 1) {
+ fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
+ exit(1);
+ }
+ close(2);
+ dup(1);
+ int result = execv(copy[0], copy);
+ exit(10);
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ exit(1);
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) == 0) {
+ printf("compiler exited normally, not good under these circumstances\n");
+ exit(1);
+ }
+ //printf("exit status of child %d was %d\n", child, WEXITSTATUS(status));
+ sprintf(buffer, "/tmp/errorfile_%d", child);
+ if (errorfile) {
+ //printf("ignoring error file: %s\n", errorfile);
+ char desired[512];
+ char got[512];
+ bool gotErrorFile = readfile(desired, errorfile);
+ bool gotOutput = readfile(got, buffer);
+ if (!gotErrorFile && gotOutput) {
+ printf("didn't read errorfile %s, it should have something from\n*****\n%s\n*****\nin it.\n",
+ errorfile, got);
+ exit(1);
+ }
+ else if (gotErrorFile && gotOutput) {
+ char *where = strstr(got, desired);
+ if (!where) {
+ printf("didn't find contents of %s in %s\n", errorfile, buffer);
+ exit(1);
+ }
+ }
+ else {
+ printf("errorfile %s and output %s inconsistent\n", errorfile, buffer);
+ exit(1);
+ }
+ }
+ unlink(buffer);
+ printf("success\n");
+ exit(0);
+}
+
diff --git a/BlocksRuntime/tests/flagsisa.c b/BlocksRuntime/tests/flagsisa.c
new file mode 100644
index 000000000..5d4b2dcb4
--- /dev/null
+++ b/BlocksRuntime/tests/flagsisa.c
@@ -0,0 +1,21 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+
+/* CONFIG rdar://6310599
+ */
+
+int main(int argc, char *argv[])
+{
+ __block int flags;
+ __block void *isa;
+
+ ^{ flags=1; isa = (void *)isa; };
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
+
diff --git a/BlocksRuntime/tests/globalexpression.c b/BlocksRuntime/tests/globalexpression.c
new file mode 100644
index 000000000..eeedd75e7
--- /dev/null
+++ b/BlocksRuntime/tests/globalexpression.c
@@ -0,0 +1,42 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// testfilerunner CONFIG
+
+#import <stdio.h>
+#import <Block.h>
+
+int global;
+
+void (^gblock)(int) = ^(int x){ global = x; };
+
+int main(int argc, char *argv[]) {
+ gblock(1);
+ if (global != 1) {
+ printf("%s: *** did not set global to 1\n", argv[0]);
+ return 1;
+ }
+ void (^gblockcopy)(int) = Block_copy(gblock);
+ if (gblockcopy != gblock) {
+ printf("global copy %p not a no-op %p\n", (void *)gblockcopy, (void *)gblock);
+ return 1;
+ }
+ Block_release(gblockcopy);
+ gblock(3);
+ if (global != 3) {
+ printf("%s: *** did not set global to 3\n", argv[0]);
+ return 1;
+ }
+ gblockcopy = Block_copy(gblock);
+ gblockcopy(5);
+ if (global != 5) {
+ printf("%s: *** did not set global to 5\n", argv[0]);
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
+
diff --git a/BlocksRuntime/tests/goto.c b/BlocksRuntime/tests/goto.c
new file mode 100644
index 000000000..7e5b08adb
--- /dev/null
+++ b/BlocksRuntime/tests/goto.c
@@ -0,0 +1,34 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * goto.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/17/08.
+ *
+ */
+
+// CONFIG rdar://6289031
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ __block int val = 0;
+
+ ^{ val = 1; }();
+
+ if (val == 0) {
+ goto out_bad; // error: local byref variable val is in the scope of this goto
+ }
+
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+out_bad:
+ printf("%s: val not updated!\n", argv[0]);
+ return 1;
+}
diff --git a/BlocksRuntime/tests/hasdescriptor.c b/BlocksRuntime/tests/hasdescriptor.c
new file mode 100644
index 000000000..429adb9bd
--- /dev/null
+++ b/BlocksRuntime/tests/hasdescriptor.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+
+
+// CONFIG C
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int main(int argc, char *argv[]) {
+ void (^inner)(void) = ^ { printf("argc was %d\n", argc); };
+ void (^outer)(void) = ^{
+ inner();
+ inner();
+ };
+ //printf("size of inner is %ld\n", Block_size(inner));
+ //printf("size of outer is %ld\n", Block_size(outer));
+ if (Block_size(inner) != Block_size(outer)) {
+ printf("not the same size, using old compiler??\n");
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/josh.C b/BlocksRuntime/tests/josh.C
new file mode 100644
index 000000000..dbc7369e8
--- /dev/null
+++ b/BlocksRuntime/tests/josh.C
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG C++ GC RR open rdar://6347910
+
+
+
+struct MyStruct {
+ int something;
+};
+
+struct TestObject {
+
+ void test(void){
+ {
+ MyStruct first; // works
+ }
+ void (^b)(void) = ^{
+ MyStruct inner; // fails to compile!
+ };
+ }
+};
+
+
+
+int main(int argc, char *argv[]) {
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/k-and-r.c b/BlocksRuntime/tests/k-and-r.c
new file mode 100644
index 000000000..16b9cc643
--- /dev/null
+++ b/BlocksRuntime/tests/k-and-r.c
@@ -0,0 +1,33 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG error: incompatible block pointer types assigning
+
+#import <stdio.h>
+#import <stdlib.h>
+
+int main(int argc, char *argv[]) {
+#ifndef __cplusplus
+ char (^rot13)();
+ rot13 = ^(char c) { return (char)(((c - 'a' + 13) % 26) + 'a'); };
+ char n = rot13('a');
+ char c = rot13('p');
+ if ( n != 'n' || c != 'c' ) {
+ printf("%s: rot13('a') returned %c, rot13('p') returns %c\n", argv[0], n, c);
+ exit(1);
+ }
+#else
+// yield characteristic error message for C++
+#error incompatible block pointer types assigning
+#endif
+#ifndef __clang__
+// yield characteristic error message for C++
+#error incompatible block pointer types assigning
+#endif
+ printf("%s: success\n", argv[0]);
+ exit(0);
+}
diff --git a/BlocksRuntime/tests/large-struct.c b/BlocksRuntime/tests/large-struct.c
new file mode 100644
index 000000000..1867bd02d
--- /dev/null
+++ b/BlocksRuntime/tests/large-struct.c
@@ -0,0 +1,51 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ unsigned long ps[30];
+ int qs[30];
+} BobTheStruct;
+
+int main (int argc, const char * argv[]) {
+ BobTheStruct inny;
+ BobTheStruct outty;
+ BobTheStruct (^copyStruct)(BobTheStruct);
+ int i;
+
+ memset(&inny, 0xA5, sizeof(inny));
+ memset(&outty, 0x2A, sizeof(outty));
+
+ for(i=0; i<30; i++) {
+ inny.ps[i] = i * i * i;
+ inny.qs[i] = -i * i * i;
+ }
+
+ copyStruct = ^(BobTheStruct aBigStruct){ return aBigStruct; }; // pass-by-value intrinsically copies the argument
+
+ outty = copyStruct(inny);
+
+ if ( &inny == &outty ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ for(i=0; i<30; i++) {
+ if ( (inny.ps[i] != outty.ps[i]) || (inny.qs[i] != outty.qs[i]) ) {
+ printf("%s: struct contents did not match.", argv[0]);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/BlocksRuntime/tests/localisglobal.c b/BlocksRuntime/tests/localisglobal.c
new file mode 100644
index 000000000..75a79dff4
--- /dev/null
+++ b/BlocksRuntime/tests/localisglobal.c
@@ -0,0 +1,42 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * localisglobal.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/29/08.
+ *
+ * works in all configurations
+ * CONFIG rdar://6230297
+ */
+
+#include <stdio.h>
+
+void (^global)(void) = ^{ printf("hello world\n"); };
+
+int aresame(void *first, void *second) {
+ long *f = (long *)first;
+ long *s = (long *)second;
+ return *f == *s;
+}
+int main(int argc, char *argv[]) {
+ int i = 10;
+ void (^local)(void) = ^ { printf("hi %d\n", i); };
+ void (^localisglobal)(void) = ^ { printf("hi\n"); };
+
+ if (aresame(local, localisglobal)) {
+ printf("local block could be global, but isn't\n");
+ return 1;
+ }
+ if (!aresame(global, localisglobal)) {
+ printf("local block is not global, not stack, what is it??\n");
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+
+}
diff --git a/BlocksRuntime/tests/macro.c b/BlocksRuntime/tests/macro.c
new file mode 100644
index 000000000..988c0689b
--- /dev/null
+++ b/BlocksRuntime/tests/macro.c
@@ -0,0 +1,14 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6718399
+#include <Block.h>
+
+void foo() {
+ void (^bbb)(void) = Block_copy(^ {
+ int j, cnt;
+ });
+}
diff --git a/BlocksRuntime/tests/makefile b/BlocksRuntime/tests/makefile
new file mode 100644
index 000000000..2734bcae3
--- /dev/null
+++ b/BlocksRuntime/tests/makefile
@@ -0,0 +1,70 @@
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+CCDIR=/usr/bin
+#CCDIR=/Volumes/Keep/gcc/usr/bin
+
+all: std
+
+clean:
+ rm -fr *.dSYM *.o *-bin testfilerunner
+
+TFR = ~public/bin/testfilerunner
+
+testfilerunner: testfilerunner.h testfilerunner.m
+ gcc -fobjc-gc-only -g -arch x86_64 -arch i386 -std=gnu99 testfilerunner.m -o testfilerunner -framework Foundation
+
+tests:
+ grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) --
+
+open:
+ grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) -open --
+
+fast:
+ grep CONFIG *.[cmCM] | $(TFR) -fast $(CCDIR) --
+
+std:
+ grep CONFIG *.[cmCM] | $(TFR) --
+
+clang:
+ grep CONFIG *.[cmCM] | $(TFR) -clang -fast --
+
+fastd:
+ grep CONFIG *.[cmCM] | $(TFR) -fast --
+
+
+# Hack Alert: arguably most of the following belongs in libclosure's Makefile; sticking it here until I get around to grokking what goes on in that file.
+sudid:
+ @echo Enabling sudo: # Hack Alert: enable sudo first thing so we don't hang at the password prompt later
+ @sudo echo Thanks
+
+
+RootsDirectory ?= /tmp/
+# Note: the libsystem project (built by the libsystemroot target below) uses the ALTUSRLOCALLIBSYSTEM variable, so we use it here to maintain parity
+ALTUSRLOCALLIBSYSTEM ?= $(RootsDirectory)/alt-usr-local-lib-system/
+altusrlocallibsystem:
+ ditto /usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM) # FIXME: conditionalize this copy
+
+
+# <rdar://problem/6456031> ER: option to not require extra privileges (-nosudo or somesuch)
+Buildit ?= ~rc/bin/buildit -rootsDirectory $(RootsDirectory) -arch i386 -arch ppc -arch x86_64
+blocksroot: sudid clean altusrlocallibsystem
+ sudo $(Buildit) ..
+ ditto $(RootsDirectory)/libclosure.roots/libclosure~dst/usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM)
+
+
+LibsystemVersion ?= 121
+LibsystemPath ?= ~rc/Software/SnowLeopard/Projects/Libsystem/Libsystem-$(LibsystemVersion)
+LibsystemTmpPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion)
+libsystemroot: blocksroot
+ ditto $(LibsystemPath) $(LibsystemTmpPath) # FIXME: conditionalize this copy
+ sudo ALTUSRLOCALLIBSYSTEM=$(ALTUSRLOCALLIBSYSTEM) $(Buildit) $(LibsystemTmpPath)
+
+
+# Defaults to product of the libsystemroot target but does not automatically rebuild that, make both targets if you want a fresh root
+LibsystemRootPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion).roots/Libsystem-$(LibsystemVersion)~dst/usr/lib/
+roottests:
+ grep CONFIG *.[cmCM] | $(TFR) -dyld $(LibsystemRootPath) -- # FIXME: figure out if I can "call" the std target instead of duplicating it
+
diff --git a/BlocksRuntime/tests/modglobal.c b/BlocksRuntime/tests/modglobal.c
new file mode 100644
index 000000000..562d5a5cc
--- /dev/null
+++ b/BlocksRuntime/tests/modglobal.c
@@ -0,0 +1,18 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+#include <stdio.h>
+
+// CONFIG
+
+int AGlobal;
+
+int main(int argc, char *argv[]) {
+ void (^f)(void) = ^ { AGlobal++; };
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+
+}
diff --git a/BlocksRuntime/tests/nestedimport.c b/BlocksRuntime/tests/nestedimport.c
new file mode 100644
index 000000000..e8066922f
--- /dev/null
+++ b/BlocksRuntime/tests/nestedimport.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// nestedimport.m
+// testObjects
+//
+// Created by Blaine Garst on 6/24/08.
+//
+// pure C nothing more needed
+// CONFIG
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int Global = 0;
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ int i = 1;
+
+ void (^vv)(void) = ^{
+ if (argc > 0) {
+ callVoidVoid(^{ Global = i; });
+ }
+ };
+
+ i = 2;
+ vv();
+ if (Global != 1) {
+ printf("%s: error, Global not set to captured value\n", argv[0]);
+ exit(1);
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/nullblockisa.c b/BlocksRuntime/tests/nullblockisa.c
new file mode 100644
index 000000000..ba0282e82
--- /dev/null
+++ b/BlocksRuntime/tests/nullblockisa.c
@@ -0,0 +1,43 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// nullblockisa.m
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+// CONFIG rdar://6244520
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Block_private.h>
+
+
+void check(void (^b)(void)) {
+ struct _custom {
+ struct Block_layout layout;
+ struct Block_byref *innerp;
+ } *custom = (struct _custom *)(void *)(b);
+ //printf("block is at %p, size is %lx, inner is %p\n", (void *)b, Block_size(b), innerp);
+ if (custom->innerp->isa != (void *)NULL) {
+ printf("not a NULL __block isa\n");
+ exit(1);
+ }
+ return;
+}
+
+int main(int argc, char *argv[]) {
+
+ __block int i;
+
+ check(^{ printf("%d\n", ++i); });
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
+
diff --git a/BlocksRuntime/tests/objectRRGC.c b/BlocksRuntime/tests/objectRRGC.c
new file mode 100644
index 000000000..2cefea2af
--- /dev/null
+++ b/BlocksRuntime/tests/objectRRGC.c
@@ -0,0 +1,77 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * objectRRGC.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/31/08.
+ *
+ * Test that the runtime honors the new callouts properly for retain/release and GC
+ * CON FIG C rdar://6175959
+ */
+
+
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int AssignCalled = 0;
+int DisposeCalled = 0;
+
+// local copy instead of libSystem.B.dylib copy
+void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
+ //printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
+ AssignCalled = 1;
+}
+
+void _Block_object_dispose(const void *object, const int isWeak) {
+ //printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
+ DisposeCalled = 1;
+}
+
+struct MyStruct {
+ long isa;
+ long field;
+};
+
+typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
+
+int main(int argc, char *argv[]) {
+ // create a block
+ struct MyStruct X;
+ MyStruct_t xp = (MyStruct_t)&X;
+ xp->field = 10;
+ void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
+ // should be a copy helper generated with a calls to above routines
+ // Lets find out!
+ struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
+ if ((bl->flags & BLOCK_HAS_DESCRIPTOR) != BLOCK_HAS_DESCRIPTOR) {
+ printf("using old runtime layout!\n");
+ return 1;
+ }
+ if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
+ printf("no copy dispose!!!!\n");
+ return 1;
+ }
+ // call helper routines directly. These will, in turn, we hope, call the stubs above
+ long destBuffer[256];
+ //printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
+ //printf("dump is %s\n", _Block_dump(myBlock));
+ bl->descriptor->copy(destBuffer, bl);
+ bl->descriptor->dispose(bl);
+ if (AssignCalled == 0) {
+ printf("did not call assign helper!\n");
+ return 1;
+ }
+ if (DisposeCalled == 0) {
+ printf("did not call dispose helper\n");
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/objectassign.c b/BlocksRuntime/tests/objectassign.c
new file mode 100644
index 000000000..1c4f48414
--- /dev/null
+++ b/BlocksRuntime/tests/objectassign.c
@@ -0,0 +1,76 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * objectassign.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/28/08.
+ *
+ * This just tests that the compiler is issuing the proper helper routines
+ * CONFIG C rdar://6175959
+ */
+
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int AssignCalled = 0;
+int DisposeCalled = 0;
+
+// local copy instead of libSystem.B.dylib copy
+void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
+ //printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
+ AssignCalled = 1;
+}
+
+void _Block_object_dispose(const void *object, const int isWeak) {
+ //printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
+ DisposeCalled = 1;
+}
+
+struct MyStruct {
+ long isa;
+ long field;
+};
+
+typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
+
+int main(int argc, char *argv[]) {
+ if (__APPLE_CC__ < 5627) {
+ printf("need compiler version %d, have %d\n", 5627, __APPLE_CC__);
+ return 0;
+ }
+ // create a block
+ struct MyStruct X;
+ MyStruct_t xp = (MyStruct_t)&X;
+ xp->field = 10;
+ void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
+ // should be a copy helper generated with a calls to above routines
+ // Lets find out!
+ struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
+ if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
+ printf("no copy dispose!!!!\n");
+ return 1;
+ }
+ // call helper routines directly. These will, in turn, we hope, call the stubs above
+ long destBuffer[256];
+ //printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
+ //printf("dump is %s\n", _Block_dump(myBlock));
+ bl->descriptor->copy(destBuffer, bl);
+ bl->descriptor->dispose(bl);
+ if (AssignCalled == 0) {
+ printf("did not call assign helper!\n");
+ return 1;
+ }
+ if (DisposeCalled == 0) {
+ printf("did not call dispose helper\n");
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/orbars.c b/BlocksRuntime/tests/orbars.c
new file mode 100644
index 000000000..18a924445
--- /dev/null
+++ b/BlocksRuntime/tests/orbars.c
@@ -0,0 +1,23 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * orbars.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/17/08.
+ *
+ * CONFIG rdar://6276695 error: before ‘|’ token
+ */
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int i = 10;
+ void (^b)(void) = ^(void){ | i | printf("hello world, %d\n", ++i); };
+ printf("%s: success :-(\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/rdar6396238.c b/BlocksRuntime/tests/rdar6396238.c
new file mode 100644
index 000000000..280415643
--- /dev/null
+++ b/BlocksRuntime/tests/rdar6396238.c
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6396238
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int count = 0;
+
+void (^mkblock(void))(void)
+{
+ count++;
+ return ^{
+ count++;
+ };
+}
+
+int main (int argc, const char * argv[]) {
+ mkblock()();
+ if (count != 2) {
+ printf("%s: failure, 2 != %d\n", argv[0], count);
+ exit(1);
+ } else {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ }
+ return 0;
+}
diff --git a/BlocksRuntime/tests/rdar6405500.c b/BlocksRuntime/tests/rdar6405500.c
new file mode 100644
index 000000000..1ab4624bc
--- /dev/null
+++ b/BlocksRuntime/tests/rdar6405500.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6405500
+
+#include <stdio.h>
+#include <stdlib.h>
+#import <dispatch/dispatch.h>
+#import <objc/objc-auto.h>
+
+int main (int argc, const char * argv[]) {
+ __block void (^blockFu)(size_t t);
+ blockFu = ^(size_t t){
+ if (t == 20) {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ } else
+ dispatch_async(dispatch_get_main_queue(), ^{ blockFu(20); });
+ };
+
+ dispatch_apply(10, dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT), blockFu);
+
+ dispatch_main();
+ printf("shouldn't get here\n");
+ return 1;
+}
diff --git a/BlocksRuntime/tests/rdar6414583.c b/BlocksRuntime/tests/rdar6414583.c
new file mode 100644
index 000000000..2ada04d3d
--- /dev/null
+++ b/BlocksRuntime/tests/rdar6414583.c
@@ -0,0 +1,31 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6414583
+
+// a smaller case of byrefcopyint
+
+#include <Block.h>
+#include <dispatch/dispatch.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ __block int c = 1;
+
+ //printf("&c = %p - c = %i\n", &c, c);
+
+ int i;
+ for(i =0; i < 2; i++) {
+ dispatch_block_t block = Block_copy(^{ c = i; });
+
+ block();
+// printf("%i: &c = %p - c = %i\n", i, &c, c);
+
+ Block_release(block);
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/recursive-block.c b/BlocksRuntime/tests/recursive-block.c
new file mode 100644
index 000000000..454ad4826
--- /dev/null
+++ b/BlocksRuntime/tests/recursive-block.c
@@ -0,0 +1,55 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+#include <stdlib.h>
+
+// CONFIG
+
+
+int cumulation = 0;
+
+int doSomething(int i) {
+ cumulation += i;
+ return cumulation;
+}
+
+void dirtyStack() {
+ int i = random();
+ int j = doSomething(i);
+ int k = doSomething(j);
+ doSomething(i + j + k);
+}
+
+typedef void (^voidVoid)(void);
+
+voidVoid testFunction() {
+ int i = random();
+ __block voidVoid inner = ^{ doSomething(i); };
+ //printf("inner, on stack, is %p\n", (void*)inner);
+ /*__block*/ voidVoid outer = ^{
+ //printf("will call inner block %p\n", (void *)inner);
+ inner();
+ };
+ //printf("outer looks like: %s\n", _Block_dump(outer));
+ voidVoid result = Block_copy(outer);
+ //Block_release(inner);
+ return result;
+}
+
+
+int main(int argc, char **argv) {
+ voidVoid block = testFunction();
+ dirtyStack();
+ block();
+ Block_release(block);
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/BlocksRuntime/tests/recursive-test.c b/BlocksRuntime/tests/recursive-test.c
new file mode 100644
index 000000000..f79914863
--- /dev/null
+++ b/BlocksRuntime/tests/recursive-test.c
@@ -0,0 +1,74 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6416474
+// was rdar://5847976
+// was rdar://6348320
+
+#include <stdio.h>
+#include <Block.h>
+
+int verbose = 0;
+
+int main(int argc, char* argv[]) {
+
+ if (argc > 1) verbose = 1;
+
+ __block void (^recursive_local_block)(int);
+
+ if (verbose) printf("recursive_local_block is a local recursive block\n");
+ recursive_local_block = ^(int i) {
+ if (verbose) printf("%d\n", i);
+ if (i > 0) {
+ recursive_local_block(i - 1);
+ }
+ };
+
+ if (verbose) printf("recursive_local_block's address is %p, running it:\n", (void*)recursive_local_block);
+ recursive_local_block(5);
+
+ if (verbose) printf("Creating other_local_block: a local block that calls recursive_local_block\n");
+
+ void (^other_local_block)(int) = ^(int i) {
+ if (verbose) printf("other_local_block running\n");
+ recursive_local_block(i);
+ };
+
+ if (verbose) printf("other_local_block's address is %p, running it:\n", (void*)other_local_block);
+
+ other_local_block(5);
+
+#if __APPLE_CC__ >= 5627
+ if (verbose) printf("Creating other_copied_block: a Block_copy of a block that will call recursive_local_block\n");
+
+ void (^other_copied_block)(int) = Block_copy(^(int i) {
+ if (verbose) printf("other_copied_block running\n");
+ recursive_local_block(i);
+ });
+
+ if (verbose) printf("other_copied_block's address is %p, running it:\n", (void*)other_copied_block);
+
+ other_copied_block(5);
+#endif
+
+ __block void (^recursive_copy_block)(int);
+
+ if (verbose) printf("Creating recursive_copy_block: a Block_copy of a block that will call recursive_copy_block recursively\n");
+
+ recursive_copy_block = Block_copy(^(int i) {
+ if (verbose) printf("%d\n", i);
+ if (i > 0) {
+ recursive_copy_block(i - 1);
+ }
+ });
+
+ if (verbose) printf("recursive_copy_block's address is %p, running it:\n", (void*)recursive_copy_block);
+
+ recursive_copy_block(5);
+
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/recursiveassign.c b/BlocksRuntime/tests/recursiveassign.c
new file mode 100644
index 000000000..f0070cbe5
--- /dev/null
+++ b/BlocksRuntime/tests/recursiveassign.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * recursiveassign.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 12/3/08.
+ *
+ */
+
+// CONFIG rdar://6639533
+
+// The compiler is prefetching x->forwarding before evaluting code that recomputes forwarding and so the value goes to a place that is never seen again.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Block.h>
+
+
+int main(int argc, char* argv[]) {
+
+ __block void (^recursive_copy_block)(int) = ^(int arg) { printf("got wrong Block\n"); exit(1); };
+
+
+ recursive_copy_block = Block_copy(^(int i) {
+ if (i > 0) {
+ recursive_copy_block(i - 1);
+ }
+ else {
+ printf("done!\n");
+ }
+ });
+
+
+ recursive_copy_block(5);
+
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
diff --git a/BlocksRuntime/tests/reference.C b/BlocksRuntime/tests/reference.C
new file mode 100644
index 000000000..f86f11e86
--- /dev/null
+++ b/BlocksRuntime/tests/reference.C
@@ -0,0 +1,95 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#import <Block.h>
+#import <stdio.h>
+#import <stdlib.h>
+
+// CONFIG C++
+
+int recovered = 0;
+
+
+
+int constructors = 0;
+int destructors = 0;
+
+#define CONST const
+
+class TestObject
+{
+public:
+ TestObject(CONST TestObject& inObj);
+ TestObject();
+ ~TestObject();
+
+ TestObject& operator=(CONST TestObject& inObj);
+
+ void test(void);
+
+ int version() CONST { return _version; }
+private:
+ mutable int _version;
+};
+
+TestObject::TestObject(CONST TestObject& inObj)
+
+{
+ ++constructors;
+ _version = inObj._version;
+ //printf("%p (%d) -- TestObject(const TestObject&) called", this, _version);
+}
+
+
+TestObject::TestObject()
+{
+ _version = ++constructors;
+ //printf("%p (%d) -- TestObject() called\n", this, _version);
+}
+
+
+TestObject::~TestObject()
+{
+ //printf("%p -- ~TestObject() called\n", this);
+ ++destructors;
+}
+
+#if 1
+TestObject& TestObject::operator=(CONST TestObject& inObj)
+{
+ //printf("%p -- operator= called", this);
+ _version = inObj._version;
+ return *this;
+}
+#endif
+
+void TestObject::test(void) {
+ void (^b)(void) = ^{ recovered = _version; };
+ void (^b2)(void) = Block_copy(b);
+ b2();
+ Block_release(b2);
+}
+
+
+
+void testRoutine() {
+ TestObject one;
+
+
+ one.test();
+}
+
+
+
+int main(int argc, char *argv[]) {
+ testRoutine();
+ if (recovered == 1) {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ }
+ printf("%s: *** didn't recover byref block variable\n", argv[0]);
+ exit(1);
+}
diff --git a/BlocksRuntime/tests/rettypepromotion.c b/BlocksRuntime/tests/rettypepromotion.c
new file mode 100644
index 000000000..597eafe8b
--- /dev/null
+++ b/BlocksRuntime/tests/rettypepromotion.c
@@ -0,0 +1,36 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * rettypepromotion.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 11/3/08.
+ *
+ */
+
+// CONFIG error:
+// C++ and C give different errors so we don't check for an exact match.
+// The error is that enum's are defined to be ints, always, even if defined with explicit long values
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+enum { LESS = -1, EQUAL, GREATER };
+
+void sortWithBlock(long (^comp)(void *arg1, void *arg2)) {
+}
+
+int main(int argc, char *argv[]) {
+ sortWithBlock(^(void *arg1, void *arg2) {
+ if (random()) return LESS;
+ if (random()) return EQUAL;
+ if (random()) return GREATER;
+ });
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/returnfunctionptr.c b/BlocksRuntime/tests/returnfunctionptr.c
new file mode 100644
index 000000000..6c7df631f
--- /dev/null
+++ b/BlocksRuntime/tests/returnfunctionptr.c
@@ -0,0 +1,23 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+
+// CONFIG rdar://6339747 but wasn't
+
+#include <stdio.h>
+
+int (*funcptr)(long);
+
+int (*(^b)(char))(long);
+
+int main(int argc, char *argv[]) {
+ // implicit is fine
+ b = ^(char x) { return funcptr; };
+ // explicit never parses
+ b = ^int (*(char x))(long) { return funcptr; };
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/shorthandexpression.c b/BlocksRuntime/tests/shorthandexpression.c
new file mode 100644
index 000000000..bf4582072
--- /dev/null
+++ b/BlocksRuntime/tests/shorthandexpression.c
@@ -0,0 +1,24 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * shorthandexpression.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/16/08.
+ *
+ * CONFIG error:
+ */
+
+
+void foo() {
+ void (^b)(void) = ^(void)printf("hello world\n");
+}
+
+int main(int argc, char *argv[]) {
+ printf("%s: this shouldn't compile\n", argv[0]);
+ return 1;
+}
diff --git a/BlocksRuntime/tests/sizeof.c b/BlocksRuntime/tests/sizeof.c
new file mode 100644
index 000000000..1f84fc16f
--- /dev/null
+++ b/BlocksRuntime/tests/sizeof.c
@@ -0,0 +1,26 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * sizeof.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+#include <stdio.h>
+
+// CONFIG error:
+
+int main(int argc, char *argv[]) {
+
+ void (^aBlock)(void) = ^{ printf("hellow world\n"); };
+
+ printf("the size of a block is %ld\n", sizeof(*aBlock));
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/small-struct.c b/BlocksRuntime/tests/small-struct.c
new file mode 100644
index 000000000..434f3c179
--- /dev/null
+++ b/BlocksRuntime/tests/small-struct.c
@@ -0,0 +1,45 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ int a;
+ int b;
+} MiniStruct;
+
+int main (int argc, const char * argv[]) {
+ MiniStruct inny;
+ MiniStruct outty;
+ MiniStruct (^copyStruct)(MiniStruct);
+
+ memset(&inny, 0xA5, sizeof(inny));
+ memset(&outty, 0x2A, sizeof(outty));
+
+ inny.a = 12;
+ inny.b = 42;
+
+ copyStruct = ^(MiniStruct aTinyStruct){ return aTinyStruct; }; // pass-by-value intrinsically copies the argument
+
+ outty = copyStruct(inny);
+
+ if ( &inny == &outty ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ if ( (inny.a != outty.a) || (inny.b != outty.b) ) {
+ printf("%s: struct contents did not match.", argv[0]);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/structmember.c b/BlocksRuntime/tests/structmember.c
new file mode 100644
index 000000000..c451d3f34
--- /dev/null
+++ b/BlocksRuntime/tests/structmember.c
@@ -0,0 +1,45 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * structmember.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/30/08.
+ * CONFIG
+ */
+#include <Block.h>
+#include <Block_private.h>
+#include <stdio.h>
+
+// CONFIG
+
+int main(int argc, char *argv[]) {
+ struct stuff {
+ long int a;
+ long int b;
+ long int c;
+ } localStuff = { 10, 20, 30 };
+ int d;
+
+ void (^a)(void) = ^ { printf("d is %d", d); };
+ void (^b)(void) = ^ { printf("d is %d, localStuff.a is %lu", d, localStuff.a); };
+
+ unsigned nominalsize = Block_size(b) - Block_size(a);
+#if __cplusplus__
+ // need copy+dispose helper for C++ structures
+ nominalsize += 2*sizeof(void*);
+#endif
+ if ((Block_size(b) - Block_size(a)) != nominalsize) {
+ printf("sizeof a is %ld, sizeof b is %ld, expected %d\n", Block_size(a), Block_size(b), nominalsize);
+ printf("dump of b is %s\n", _Block_dump(b));
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
+
diff --git a/BlocksRuntime/tests/testfilerunner.h b/BlocksRuntime/tests/testfilerunner.h
new file mode 100644
index 000000000..d4e54f029
--- /dev/null
+++ b/BlocksRuntime/tests/testfilerunner.h
@@ -0,0 +1,110 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// testfilerunner.h
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+
+#import <Cocoa/Cocoa.h>
+
+/*
+ variations:
+ four source types: C, ObjC, C++, ObjC++,
+ and for ObjC or ObjC++ we have
+ RR and GC capabilities
+ we assume C++ friendly includes for C/ObjC even if C++ isn't used
+
+
+ four compilers: C, ObjC, C++, ObjC++
+ and for ObjC or ObjC++ we can compile
+ RR, RR+GC, GC+RR, GC
+ although to test RR+GC we need to build a shell "main" in both modes
+ and/or run with GC disabled if possible.
+
+ To maximize coverage we mark files with capabilities and then ask them to be
+ compiled with each variation of compiler and option.
+ If the file doesn't have the capability it politely refuses.
+*/
+
+enum options {
+ Do64 = (1 << 0),
+ DoCPP = (1 << 1),
+ DoOBJC = (1 << 3),
+ DoGC = (1 << 4),
+ DoRR = (1 << 5),
+ DoRRGC = (1 << 6), // -fobjc-gc but main w/o so it runs in RR mode
+ DoGCRR = (1 << 7), // -fobjc-gc & run GC mode
+
+ //DoDashG = (1 << 8),
+ DoDashO = (1 << 9),
+ DoDashOs = (1 << 10),
+ DoDashO2 = (1 << 11),
+
+ DoC99 = (1 << 12), // -std=c99
+};
+
+
+@class TestFileExeGenerator;
+
+// this class will actually compile and/or run a target binary
+// XXX we don't track which dynamic libraries requested/used nor set them up
+@interface TestFileExe : NSObject {
+ NSPointerArray *compileLine;
+ int options;
+ bool shouldFail;
+ TestFileExeGenerator *generator;
+ __strong char *binaryName;
+ __strong char *sourceName;
+ __strong char *libraryPath;
+ __strong char *frameworkPath;
+}
+@property int options;
+@property(assign) NSPointerArray *compileLine;
+@property(assign) TestFileExeGenerator *generator;
+@property bool shouldFail;
+@property __strong char *binaryName;
+@property __strong char *sourceName;
+@property __strong char *libraryPath;
+@property __strong char *frameworkPath;
+- (bool) compileUnlessExists:(bool)skip;
+- (bool) run;
+@property(readonly) __strong char *radar;
+@end
+
+// this class generates an appropriate set of configurations to compile
+// we don't track which gcc we use but we should XXX
+@interface TestFileExeGenerator : NSObject {
+ bool hasObjC;
+ bool hasRR;
+ bool hasGC;
+ bool hasCPlusPlus;
+ bool wantsC99;
+ bool wants64;
+ bool wants32;
+ bool supposedToNotCompile;
+ bool open; // this problem is still open - e.g. unresolved
+ __strong char *radar; // for things already known to go wrong
+ __strong char *filename;
+ __strong char *compilerPath;
+ __strong char *errorString;
+ __strong char *warningString;
+ NSPointerArray *extraLibraries;
+}
+@property bool hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
+@property(assign) __strong char *radar;
+@property __strong char *filename;
+@property __strong char *compilerPath;
+@property __strong char *errorString;
+@property __strong char *warningString;
+- (TestFileExe *)lineForOptions:(int)options; // nil if no can do
++ (NSArray *)generatorsFromFILE:(FILE *)fd;
++ (NSArray *)generatorsFromPath:(NSString *)path;
+@end
+
+
diff --git a/BlocksRuntime/tests/testfilerunner.m b/BlocksRuntime/tests/testfilerunner.m
new file mode 100644
index 000000000..459adf889
--- /dev/null
+++ b/BlocksRuntime/tests/testfilerunner.m
@@ -0,0 +1,805 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// testfilerunner.m
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+
+#import "testfilerunner.h"
+#import <Foundation/Foundation.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+bool Everything = false; // do it also with 3 levels of optimization
+bool DoClang = false;
+
+static bool isDirectory(char *path);
+static bool isExecutable(char *path);
+static bool isYounger(char *source, char *binary);
+static bool readErrorFile(char *buffer, const char *from);
+
+__strong char *gcstrcpy2(__strong const char *arg, char *endp) {
+ unsigned size = endp - arg + 1;
+ __strong char *result = NSAllocateCollectable(size, 0);
+ strncpy(result, arg, size);
+ result[size-1] = 0;
+ return result;
+}
+__strong char *gcstrcpy1(__strong char *arg) {
+ unsigned size = strlen(arg) + 1;
+ __strong char *result = NSAllocateCollectable(size, 0);
+ strncpy(result, arg, size);
+ result[size-1] = 0;
+ return result;
+}
+
+@implementation TestFileExe
+
+@synthesize options, compileLine, shouldFail, binaryName, sourceName;
+@synthesize generator;
+@synthesize libraryPath, frameworkPath;
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString new];
+ if (shouldFail) [result appendString:@"fail"];
+ for (id x in compileLine) {
+ [result appendString:[NSString stringWithFormat:@" %s", (char *)x]];
+ }
+ return result;
+}
+
+- (__strong char *)radar {
+ return generator.radar;
+}
+
+- (bool) compileUnlessExists:(bool)skip {
+ if (shouldFail) {
+ printf("don't use this to compile anymore!\n");
+ return false;
+ }
+ if (skip && isExecutable(binaryName) && !isYounger(sourceName, binaryName)) return true;
+ int argc = [compileLine count];
+ char *argv[argc+1];
+ for (int i = 0; i < argc; ++i)
+ argv[i] = (char *)[compileLine pointerAtIndex:i];
+ argv[argc] = NULL;
+ pid_t child = fork();
+ if (child == 0) {
+ execv(argv[0], argv);
+ exit(10); // shouldn't happen
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) == 0) {
+ return true;
+ }
+ printf("run failed\n");
+ return false;
+}
+
+bool lookforIn(char *lookfor, const char *format, pid_t child) {
+ char buffer[512];
+ char got[512];
+ sprintf(buffer, format, child);
+ bool gotOutput = readErrorFile(got, buffer);
+ if (!gotOutput) {
+ printf("**** didn't get an output file %s to analyze!!??\n", buffer);
+ return false;
+ }
+ char *where = strstr(got, lookfor);
+ if (!where) {
+ printf("didn't find '%s' in output file %s\n", lookfor, buffer);
+ return false;
+ }
+ unlink(buffer);
+ return true;
+}
+
+- (bool) compileWithExpectedFailure {
+ if (!shouldFail) {
+ printf("Why am I being called?\n");
+ return false;
+ }
+ int argc = [compileLine count];
+ char *argv[argc+1];
+ for (int i = 0; i < argc; ++i)
+ argv[i] = (char *)[compileLine pointerAtIndex:i];
+ argv[argc] = NULL;
+ pid_t child = fork();
+ char buffer[512];
+ if (child == 0) {
+ // in child
+ sprintf(buffer, "/tmp/errorfile_%d", getpid());
+ close(1);
+ int fd = creat(buffer, 0777);
+ if (fd != 1) {
+ fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
+ exit(1);
+ }
+ close(2);
+ dup(1);
+ int result = execv(argv[0], argv);
+ exit(10);
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(11);
+ }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ return false;
+ }
+ }
+ else {
+ printf("***** compiler borked/ICEd/died unexpectedly (status %x)\n", status);
+ return false;
+ }
+ char *error = generator.errorString;
+
+ if (!error) return true;
+#if 0
+ char got[512];
+ sprintf(buffer, "/tmp/errorfile_%d", child);
+ bool gotOutput = readErrorFile(got, buffer);
+ if (!gotOutput) {
+ printf("**** didn't get an error file %s to analyze!!??\n", buffer);
+ return false;
+ }
+ char *where = strstr(got, error);
+ if (!where) {
+ printf("didn't find '%s' in error file %s\n", error, buffer);
+ return false;
+ }
+ unlink(buffer);
+#else
+ if (!lookforIn(error, "/tmp/errorfile_%d", child)) return false;
+#endif
+ return true;
+}
+
+- (bool) run {
+ if (shouldFail) return true;
+ if (sizeof(long) == 4 && options & Do64) {
+ return true; // skip 64-bit tests
+ }
+ int argc = 1;
+ char *argv[argc+1];
+ argv[0] = binaryName;
+ argv[argc] = NULL;
+ pid_t child = fork();
+ if (child == 0) {
+ // set up environment
+ char lpath[1024];
+ char fpath[1024];
+ char *myenv[3];
+ int counter = 0;
+ if (libraryPath) {
+ sprintf(lpath, "DYLD_LIBRARY_PATH=%s", libraryPath);
+ myenv[counter++] = lpath;
+ }
+ if (frameworkPath) {
+ sprintf(fpath, "DYLD_FRAMEWORK_PATH=%s", frameworkPath);
+ myenv[counter++] = fpath;
+ }
+ myenv[counter] = NULL;
+ if (generator.warningString) {
+ // set up stdout/stderr
+ char outfile[1024];
+ sprintf(outfile, "/tmp/stdout_%d", getpid());
+ close(2);
+ close(1);
+ creat(outfile, 0700);
+ dup(1);
+ }
+ execve(argv[0], argv, myenv);
+ exit(10); // shouldn't happen
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ if (generator.warningString) {
+ if (!lookforIn(generator.warningString, "/tmp/stdout_%d", child)) return false;
+ }
+ return true;
+ }
+ printf("**** run failed for %s\n", binaryName);
+ return false;
+}
+
+@end
+
+@implementation TestFileExeGenerator
+@synthesize filename, compilerPath, errorString;
+@synthesize hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
+@synthesize radar;
+@synthesize warningString;
+
+- (void)setFilename:(__strong char *)name {
+ filename = gcstrcpy1(name);
+}
+- (void)setCompilerPath:(__strong char *)name {
+ compilerPath = gcstrcpy1(name);
+}
+
+- (void)forMostThings:(NSMutableArray *)lines options:(int)options {
+ TestFileExe *item = nil;
+ item = [self lineForOptions:options];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|Do64];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|DoCPP];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|Do64|DoCPP];
+ if (item) [lines addObject:item];
+}
+
+/*
+ DoDashG = (1 << 8),
+ DoDashO = (1 << 9),
+ DoDashOs = (1 << 10),
+ DoDashO2 = (1 << 11),
+*/
+
+- (void)forAllThings:(NSMutableArray *)lines options:(int)options {
+ [self forMostThings:lines options:options];
+ if (!Everything) {
+ return;
+ }
+ // now do it with three explicit optimization flags
+ [self forMostThings:lines options:options | DoDashO];
+ [self forMostThings:lines options:options | DoDashOs];
+ [self forMostThings:lines options:options | DoDashO2];
+}
+
+- (NSArray *)allLines {
+ NSMutableArray *result = [NSMutableArray new];
+ TestFileExe *item = nil;
+
+ int options = 0;
+ [self forAllThings:result options:0];
+ [self forAllThings:result options:DoOBJC | DoRR];
+ [self forAllThings:result options:DoOBJC | DoGC];
+ [self forAllThings:result options:DoOBJC | DoGCRR];
+ //[self forAllThings:result options:DoOBJC | DoRRGC];
+
+ return result;
+}
+
+- (void)addLibrary:(const char *)dashLSomething {
+ if (!extraLibraries) {
+ extraLibraries = [NSPointerArray pointerArrayWithOptions:
+ NSPointerFunctionsStrongMemory |
+ NSPointerFunctionsCStringPersonality];
+ }
+ [extraLibraries addPointer:(void *)dashLSomething];
+}
+
+- (TestFileExe *)lineForOptions:(int)options { // nil if no can do
+ if (hasObjC && !(options & DoOBJC)) return nil;
+ if (hasCPlusPlus && !(options & DoCPP)) return nil;
+ if (hasObjC) {
+ if (!hasGC && (options & (DoGC|DoGCRR))) return nil; // not smart enough
+ if (!hasRR && (options & (DoRR|DoRRGC))) return nil;
+ }
+ NSPointerArray *pa = [NSPointerArray pointerArrayWithOptions:
+ NSPointerFunctionsStrongMemory |
+ NSPointerFunctionsCStringPersonality];
+ // construct path
+ char path[512];
+ path[0] = 0;
+ if (!compilerPath) compilerPath = "/usr/bin";
+ if (compilerPath) {
+ strcat(path, compilerPath);
+ strcat(path, "/");
+ }
+ if (options & DoCPP) {
+ strcat(path, DoClang ? "clang++" : "g++-4.2");
+ }
+ else {
+ strcat(path, DoClang ? "clang" : "gcc-4.2");
+ }
+ [pa addPointer:gcstrcpy1(path)];
+ if (options & DoOBJC) {
+ if (options & DoCPP) {
+ [pa addPointer:"-ObjC++"];
+ }
+ else {
+ [pa addPointer:"-ObjC"];
+ }
+ }
+ [pa addPointer:"-g"];
+ if (options & DoDashO) [pa addPointer:"-O"];
+ else if (options & DoDashO2) [pa addPointer:"-O2"];
+ else if (options & DoDashOs) [pa addPointer:"-Os"];
+ if (wantsC99 && (! (options & DoCPP))) {
+ [pa addPointer:"-std=c99"];
+ [pa addPointer:"-fblocks"];
+ }
+ [pa addPointer:"-arch"];
+ [pa addPointer: (options & Do64) ? "x86_64" : "i386"];
+
+ if (options & DoOBJC) {
+ switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
+ case DoRR:
+ break;
+ case DoGC:
+ [pa addPointer:"-fobjc-gc-only"];
+ break;
+ case DoGCRR:
+ [pa addPointer:"-fobjc-gc"];
+ break;
+ case DoRRGC:
+ printf("DoRRGC unsupported right now\n");
+ [pa addPointer:"-c"];
+ return nil;
+ }
+ [pa addPointer:"-framework"];
+ [pa addPointer:"Foundation"];
+ }
+ [pa addPointer:gcstrcpy1(filename)];
+ [pa addPointer:"-o"];
+
+ path[0] = 0;
+ strcat(path, filename);
+ strcat(path, ".");
+ strcat(path, (options & Do64) ? "64" : "32");
+ if (options & DoOBJC) {
+ switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
+ case DoRR: strcat(path, "-rr"); break;
+ case DoGC: strcat(path, "-gconly"); break;
+ case DoGCRR: strcat(path, "-gcrr"); break;
+ case DoRRGC: strcat(path, "-rrgc"); break;
+ }
+ }
+ if (options & DoCPP) strcat(path, "++");
+ if (options & DoDashO) strcat(path, "-O");
+ else if (options & DoDashO2) strcat(path, "-O2");
+ else if (options & DoDashOs) strcat(path, "-Os");
+ if (wantsC99) strcat(path, "-C99");
+ strcat(path, DoClang ? "-clang" : "-gcc");
+ strcat(path, "-bin");
+ TestFileExe *result = [TestFileExe new];
+ result.binaryName = gcstrcpy1(path); // could snarf copy in pa
+ [pa addPointer:result.binaryName];
+ for (id cString in extraLibraries) {
+ [pa addPointer:cString];
+ }
+
+ result.sourceName = gcstrcpy1(filename); // could snarf copy in pa
+ result.compileLine = pa;
+ result.options = options;
+ result.shouldFail = supposedToNotCompile;
+ result.generator = self;
+ return result;
+}
+
++ (NSArray *)generatorsFromPath:(NSString *)path {
+ FILE *fp = fopen([path fileSystemRepresentation], "r");
+ if (fp == NULL) return nil;
+ NSArray *result = [self generatorsFromFILE:fp];
+ fclose(fp);
+ return result;
+}
+
+#define LOOKFOR "CON" "FIG"
+
+char *__strong parseRadar(char *line) {
+ line = strstr(line, "rdar:"); // returns beginning
+ char *endp = line + strlen("rdar:");
+ while (*endp && *endp != ' ' && *endp != '\n')
+ ++endp;
+ return gcstrcpy2(line, endp);
+}
+
+- (void)parseLibraries:(const char *)line {
+ start:
+ line = strstr(line, "-l");
+ char *endp = (char *)line + 2;
+ while (*endp && *endp != ' ' && *endp != '\n')
+ ++endp;
+ [self addLibrary:gcstrcpy2(line, endp)];
+ if (strstr(endp, "-l")) {
+ line = endp;
+ goto start;
+ }
+}
+
++ (TestFileExeGenerator *)generatorFromLine:(char *)line filename:(char *)filename {
+ TestFileExeGenerator *item = [TestFileExeGenerator new];
+ item.filename = gcstrcpy1(filename);
+ if (strstr(line, "GC")) item.hasGC = true;
+ if (strstr(line, "RR")) item.hasRR = true;
+ if (strstr(line, "C++")) item.hasCPlusPlus = true;
+ if (strstr(line, "-C99")) {
+ item.wantsC99 = true;
+ }
+ if (strstr(line, "64")) item.wants64 = true;
+ if (strstr(line, "32")) item.wants32 = true;
+ if (strstr(line, "-l")) [item parseLibraries:line];
+ if (strstr(line, "open")) item.open = true;
+ if (strstr(line, "FAIL")) item.supposedToNotCompile = true; // old
+ // compile time error
+ if (strstr(line, "error:")) {
+ item.supposedToNotCompile = true;
+ // zap newline
+ char *error = strstr(line, "error:") + strlen("error:");
+ // make sure we have something before the newline
+ char *newline = strstr(error, "\n");
+ if (newline && ((newline-error) > 1)) {
+ *newline = 0;
+ item.errorString = gcstrcpy1(strstr(line, "error:") + strlen("error: "));
+ }
+ }
+ // run time warning
+ if (strstr(line, "runtime:")) {
+ // zap newline
+ char *error = strstr(line, "runtime:") + strlen("runtime:");
+ // make sure we have something before the newline
+ char *newline = strstr(error, "\n");
+ if (newline && ((newline-error) > 1)) {
+ *newline = 0;
+ item.warningString = gcstrcpy1(strstr(line, "runtime:") + strlen("runtime:"));
+ }
+ }
+ if (strstr(line, "rdar:")) item.radar = parseRadar(line);
+ if (item.hasGC || item.hasRR) item.hasObjC = true;
+ if (!item.wants32 && !item.wants64) { // give them both if they ask for neither
+ item.wants32 = item.wants64 = true;
+ }
+ return item;
+}
+
++ (NSArray *)generatorsFromFILE:(FILE *)fp {
+ NSMutableArray *result = [NSMutableArray new];
+ // pretend this is a grep LOOKFOR *.[cmCM][cmCM] input
+ // look for
+ // filename: ... LOOKFOR [GC] [RR] [C++] [FAIL ...]
+ char buf[512];
+ while (fgets(buf, 512, fp)) {
+ char *config = strstr(buf, LOOKFOR);
+ if (!config) continue;
+ char *filename = buf;
+ char *end = strchr(buf, ':');
+ *end = 0;
+ [result addObject:[self generatorFromLine:config filename:filename]];
+ }
+ return result;
+}
+
++ (TestFileExeGenerator *)generatorFromFilename:(char *)filename {
+ FILE *fp = fopen(filename, "r");
+ if (!fp) {
+ printf("didn't open %s!!\n", filename);
+ return nil;
+ }
+ char buf[512];
+ while (fgets(buf, 512, fp)) {
+ char *config = strstr(buf, LOOKFOR);
+ if (!config) continue;
+ fclose(fp);
+ return [self generatorFromLine:config filename:filename];
+ }
+ fclose(fp);
+ // guess from filename
+ char *ext = strrchr(filename, '.');
+ if (!ext) return nil;
+ TestFileExeGenerator *result = [TestFileExeGenerator new];
+ result.filename = gcstrcpy1(filename);
+ if (!strncmp(ext, ".m", 2)) {
+ result.hasObjC = true;
+ result.hasRR = true;
+ result.hasGC = true;
+ }
+ else if (!strcmp(ext, ".c")) {
+ ;
+ }
+ else if (!strcmp(ext, ".M") || !strcmp(ext, ".mm")) {
+ result.hasObjC = true;
+ result.hasRR = true;
+ result.hasGC = true;
+ result.hasCPlusPlus = true;
+ }
+ else if (!strcmp(ext, ".cc")
+ || !strcmp(ext, ".cp")
+ || !strcmp(ext, ".cxx")
+ || !strcmp(ext, ".cpp")
+ || !strcmp(ext, ".CPP")
+ || !strcmp(ext, ".c++")
+ || !strcmp(ext, ".C")) {
+ result.hasCPlusPlus = true;
+ }
+ else {
+ printf("unknown extension, file %s ignored\n", filename);
+ result = nil;
+ }
+ return result;
+
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%s: %s%s%s%s%s%s",
+ filename,
+ LOOKFOR,
+ hasGC ? " GC" : "",
+ hasRR ? " RR" : "",
+ hasCPlusPlus ? " C++" : "",
+ wantsC99 ? "C99" : "",
+ supposedToNotCompile ? " FAIL" : ""];
+}
+
+@end
+
+void printDetails(NSArray *failures, const char *whatAreThey) {
+ if ([failures count]) {
+ NSMutableString *output = [NSMutableString new];
+ printf("%s:\n", whatAreThey);
+ for (TestFileExe *line in failures) {
+ printf("%s", line.binaryName);
+ char *radar = line.generator.radar;
+ if (radar)
+ printf(" (due to %s?),", radar);
+ printf(" recompile via:\n%s\n\n", line.description.UTF8String);
+ }
+ printf("\n");
+ }
+}
+
+void help(const char *whoami) {
+ printf("Usage: %s [-fast] [-e] [-dyld librarypath] [gcc4.2dir] [-- | source1 ...]\n", whoami);
+ printf(" -fast don't recompile if binary younger than source\n");
+ printf(" -open only run tests that are thought to still be unresolved\n");
+ printf(" -clang use the clang and clang++ compilers\n");
+ printf(" -e compile all variations also with -Os, -O2, -O3\n");
+ printf(" -dyld p override DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to p when running tests\n");
+ printf(" <compilerpath> directory containing gcc-4.2 (or clang) that you wish to use to compile the tests\n");
+ printf(" -- assume stdin is a grep CON" "FIG across the test sources\n");
+ printf(" otherwise treat each remaining argument as a single test file source\n");
+ printf("%s will compile and run individual test files under a variety of compilers, c, obj-c, c++, and objc++\n", whoami);
+ printf(" .c files are compiled with all four compilers\n");
+ printf(" .m files are compiled with objc and objc++ compilers\n");
+ printf(" .C files are compiled with c++ and objc++ compilers\n");
+ printf(" .M files are compiled only with the objc++ compiler\n");
+ printf("(actually all forms of extensions recognized by the compilers are honored, .cc, .c++ etc.)\n");
+ printf("\nTest files should run to completion with no output and exit (return) 0 on success.\n");
+ printf("Further they should be able to be compiled and run with GC on or off and by the C++ compilers\n");
+ printf("A line containing the string CON" "FIG within the source enables restrictions to the above assumptions\n");
+ printf("and other options.\n");
+ printf("Following CON" "FIG the string\n");
+ printf(" C++ restricts the test to only be run by c++ and objc++ compilers\n");
+ printf(" GC restricts the test to only be compiled and run with GC on\n");
+ printf(" RR (retain/release) restricts the test to only be compiled and run with GC off\n");
+ printf("Additionally,\n");
+ printf(" -C99 restricts the C versions of the test to -fstd=c99 -fblocks\n");
+ printf(" -O adds the -O optimization level\n");
+ printf(" -O2 adds the -O2 optimization level\n");
+ printf(" -Os adds the -Os optimization level\n");
+ printf("Files that are known to exhibit unresolved problems can provide the term \"open\" and this can");
+ printf("in turn allow highlighting of fixes that have regressed as well as identify that fixes are now available.\n");
+ printf("Files that exhibit known bugs may provide\n");
+ printf(" rdar://whatever such that if they fail the rdar will get cited\n");
+ printf("Files that are expected to fail to compile should provide, as their last token sequence,\n");
+ printf(" error:\n");
+ printf(" or error: substring to match.\n");
+ printf("Files that are expected to produce a runtime error message should provide, as their last token sequence,\n");
+ printf(" warning: string to match\n");
+ printf("\n%s will compile and run all configurations of the test files and report a summary at the end. Good luck.\n", whoami);
+ printf(" Blaine Garst blaine@apple.com\n");
+}
+
+int main(int argc, char *argv[]) {
+ printf("running on %s-bit architecture\n", sizeof(long) == 4 ? "32" : "64");
+ char *compilerDir = "/usr/bin";
+ NSMutableArray *generators = [NSMutableArray new];
+ bool doFast = false;
+ bool doStdin = false;
+ bool onlyOpen = false;
+ char *libraryPath = getenv("DYLD_LIBRARY_PATH");
+ char *frameworkPath = getenv("DYLD_FRAMEWORK_PATH");
+ // process options
+ while (argc > 1) {
+ if (!strcmp(argv[1], "-fast")) {
+ doFast = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-dyld")) {
+ doFast = true;
+ --argc;
+ ++argv;
+ frameworkPath = argv[1];
+ libraryPath = argv[1];
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-open")) {
+ onlyOpen = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-clang")) {
+ DoClang = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-e")) {
+ Everything = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "--")) {
+ doStdin = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-")) {
+ help(argv[0]);
+ return 1;
+ }
+ else if (argc > 1 && isDirectory(argv[1])) {
+ compilerDir = argv[1];
+ ++argv;
+ --argc;
+ }
+ else
+ break;
+ }
+ // process remaining arguments, or stdin
+ if (argc == 1) {
+ if (doStdin)
+ generators = (NSMutableArray *)[TestFileExeGenerator generatorsFromFILE:stdin];
+ else {
+ help(argv[0]);
+ return 1;
+ }
+ }
+ else while (argc > 1) {
+ TestFileExeGenerator *generator = [TestFileExeGenerator generatorFromFilename:argv[1]];
+ if (generator) [generators addObject:generator];
+ ++argv;
+ --argc;
+ }
+ // see if we can generate all possibilities
+ NSMutableArray *failureToCompile = [NSMutableArray new];
+ NSMutableArray *failureToFailToCompile = [NSMutableArray new];
+ NSMutableArray *failureToRun = [NSMutableArray new];
+ NSMutableArray *successes = [NSMutableArray new];
+ for (TestFileExeGenerator *generator in generators) {
+ //NSLog(@"got %@", generator);
+ if (onlyOpen && !generator.open) {
+ //printf("skipping resolved test %s\n", generator.filename);
+ continue; // skip closed if onlyOpen
+ }
+ if (!onlyOpen && generator.open) {
+ //printf("skipping open test %s\n", generator.filename);
+ continue; // skip open if not asked for onlyOpen
+ }
+ generator.compilerPath = compilerDir;
+ NSArray *tests = [generator allLines];
+ for (TestFileExe *line in tests) {
+ line.frameworkPath = frameworkPath; // tell generators about it instead XXX
+ line.libraryPath = libraryPath; // tell generators about it instead XXX
+ if ([line shouldFail]) {
+ if (doFast) continue; // don't recompile & don't count as success
+ if ([line compileWithExpectedFailure]) {
+ [successes addObject:line];
+ }
+ else
+ [failureToFailToCompile addObject:line];
+ }
+ else if ([line compileUnlessExists:doFast]) {
+ if ([line run]) {
+ printf("%s ran successfully\n", line.binaryName);
+ [successes addObject:line];
+ }
+ else {
+ [failureToRun addObject:line];
+ }
+ }
+ else {
+ [failureToCompile addObject:line];
+ }
+ }
+ }
+ printf("\n--- results ---\n\n%lu successes\n%lu unexpected compile failures\n%lu failure to fail to compile errors\n%lu run failures\n",
+ [successes count], [failureToCompile count], [failureToFailToCompile count], [failureToRun count]);
+ printDetails(failureToCompile, "unexpected compile failures");
+ printDetails(failureToFailToCompile, "should have failed to compile but didn't failures");
+ printDetails(failureToRun, "run failures");
+
+ if (onlyOpen && [successes count]) {
+ NSMutableSet *radars = [NSMutableSet new];
+ printf("The following tests ran successfully suggesting that they are now resolved:\n");
+ for (TestFileExe *line in successes) {
+ printf("%s\n", line.binaryName);
+ if (line.radar) [radars addObject:line.generator];
+ }
+ if ([radars count]) {
+ printf("The following radars may be resolved:\n");
+ for (TestFileExeGenerator *line in radars) {
+ printf("%s\n", line.radar);
+ }
+ }
+ }
+
+ return [failureToCompile count] + [failureToRun count];
+}
+
+#include <sys/stat.h>
+
+static bool isDirectory(char *path) {
+ struct stat statb;
+ int retval = stat(path, &statb);
+ if (retval != 0) return false;
+ if (statb.st_mode & S_IFDIR) return true;
+ return false;
+}
+
+static bool isExecutable(char *path) {
+ struct stat statb;
+ int retval = stat(path, &statb);
+ if (retval != 0) return false;
+ if (!(statb.st_mode & S_IFREG)) return false;
+ if (statb.st_mode & S_IXUSR) return true;
+ return false;
+}
+
+static bool isYounger(char *source, char *binary) {
+ struct stat statb;
+ int retval = stat(binary, &statb);
+ if (retval != 0) return true; // if doesn't exit, lie
+
+ struct stat stata;
+ retval = stat(source, &stata);
+ if (retval != 0) return true; // we're hosed
+ // the greater the timeval the younger it is
+ if (stata.st_mtimespec.tv_sec > statb.st_mtimespec.tv_sec) return true;
+ if (stata.st_mtimespec.tv_nsec > statb.st_mtimespec.tv_nsec) return true;
+ return false;
+}
+
+static bool readErrorFile(char *buffer, const char *from) {
+ int fd = open(from, 0);
+ if (fd < 0) {
+ printf("didn't open %s, (might not have been created?)\n", buffer);
+ return false;
+ }
+ int count = read(fd, buffer, 512);
+ if (count < 1) {
+ printf("read error on %s\n", buffer);
+ return false;
+ }
+ buffer[count-1] = 0; // zap newline
+ return true;
+}
diff --git a/BlocksRuntime/tests/varargs-bad-assign.c b/BlocksRuntime/tests/varargs-bad-assign.c
new file mode 100644
index 000000000..b978668b9
--- /dev/null
+++ b/BlocksRuntime/tests/varargs-bad-assign.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// HACK ALERT: gcc and g++ give different errors, referencing the line number to ensure that it checks for the right error; MUST KEEP IN SYNC WITH THE TEST
+// CONFIG 27: error:
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+#import <stdarg.h>
+
+
+int main (int argc, const char * argv[]) {
+ int (^sumn)(int n, ...);
+ int six = 0;
+
+ sumn = ^(int a, int b, int n, ...){
+ int result = 0;
+ va_list numbers;
+ int i;
+
+ va_start(numbers, n);
+ for (i = 0 ; i < n ; i++) {
+ result += va_arg(numbers, int);
+ }
+ va_end(numbers);
+
+ return result;
+ };
+
+ six = sumn(3, 1, 2, 3);
+
+ if ( six != 6 ) {
+ printf("%s: Expected 6 but got %d\n", argv[0], six);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/varargs.c b/BlocksRuntime/tests/varargs.c
new file mode 100644
index 000000000..01affc76e
--- /dev/null
+++ b/BlocksRuntime/tests/varargs.c
@@ -0,0 +1,39 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+#import <stdarg.h>
+
+
+int main (int argc, const char * argv[]) {
+ int (^sumn)(int n, ...) = ^(int n, ...){
+ int result = 0;
+ va_list numbers;
+ int i;
+
+ va_start(numbers, n);
+ for (i = 0 ; i < n ; i++) {
+ result += va_arg(numbers, int);
+ }
+ va_end(numbers);
+
+ return result;
+ };
+ int six = sumn(3, 1, 2, 3);
+
+ if ( six != 6 ) {
+ printf("%s: Expected 6 but got %d\n", argv[0], six);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/BlocksRuntime/tests/variadic.c b/BlocksRuntime/tests/variadic.c
new file mode 100644
index 000000000..1d80657e9
--- /dev/null
+++ b/BlocksRuntime/tests/variadic.c
@@ -0,0 +1,66 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * variadic.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE Test that variadic arguments compile and work for Blocks
+// CONFIG
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+
+ long (^addthem)(const char *, ...) = ^long (const char *format, ...){
+ va_list argp;
+ const char *p;
+ int i;
+ char c;
+ double d;
+ long result = 0;
+ va_start(argp, format);
+ //printf("starting...\n");
+ for (p = format; *p; p++) switch (*p) {
+ case 'i':
+ i = va_arg(argp, int);
+ //printf("i: %d\n", i);
+ result += i;
+ break;
+ case 'd':
+ d = va_arg(argp, double);
+ //printf("d: %g\n", d);
+ result += (int)d;
+ break;
+ case 'c':
+ c = va_arg(argp, int);
+ //printf("c: '%c'\n", c);
+ result += c;
+ break;
+ }
+ //printf("...done\n\n");
+ return result;
+ };
+ long testresult = addthem("ii", 10, 20);
+ if (testresult != 30) {
+ printf("got wrong result: %ld\n", testresult);
+ return 1;
+ }
+ testresult = addthem("idc", 30, 40.0, 'a');
+ if (testresult != (70+'a')) {
+ printf("got different wrong result: %ld\n", testresult);
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
+
diff --git a/BlocksRuntime/tests/voidarg.c b/BlocksRuntime/tests/voidarg.c
new file mode 100644
index 000000000..a8f034b47
--- /dev/null
+++ b/BlocksRuntime/tests/voidarg.c
@@ -0,0 +1,27 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * voidarg.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE should complain about missing 'void' but both GCC and clang are supporting K&R instead
+// CONFIG open error:
+
+#include <stdio.h>
+
+int Global;
+
+void (^globalBlock)() = ^{ ++Global; }; // should be void (^gb)(void) = ...
+
+int main(int argc, char *argv[]) {
+ printf("%s: success", argv[0]);
+ return 0;
+}