forked from OSchip/llvm-project
parent
a1c0f8b5c8
commit
be67b4aa20
compiler-rt/BlocksRuntime/tests
block-static.cblockimport.cbyrefaccess.cbyrefcopy.cbyrefcopycopy.cbyrefcopyinner.cbyrefcopyint.cbyrefcopystack.cbyrefsanity.cbyrefstruct.cc99.ccast.cconstassign.ccopy-block-literal-rdar6439600.ccopyconstructor.Ccopynull.cdispatch_async.cdispatch_call_Block_with_release.cfail.cflagsisa.cglobalexpression.cgoto.chasdescriptor.cjosh.Ck-and-r.clarge-struct.clocalisglobal.cmacro.cmakefilemodglobal.cnestedimport.cnullblockisa.cobjectRRGC.cobjectassign.corbars.crdar6396238.crdar6405500.crdar6414583.crecursive-block.crecursive-test.crecursiveassign.creference.Crettypepromotion.creturnfunctionptr.cshorthandexpression.csizeof.csmall-struct.cstructmember.ctestfilerunner.htestfilerunner.mvarargs-bad-assign.cvarargs.cvariadic.cvoidarg.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;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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(©, 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 ( © == &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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue