add unit tests

llvm-svn: 110278
This commit is contained in:
Blaine Garst 2010-08-04 23:34:21 +00:00
parent a1c0f8b5c8
commit be67b4aa20
54 changed files with 3199 additions and 0 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,57 @@
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
// CONFIG
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
typedef struct {
unsigned long ps[30];
int qs[30];
} BobTheStruct;
int main (int argc, const char * argv[]) {
__block BobTheStruct fiddly;
BobTheStruct copy;
void (^incrementFiddly)() = ^{
int i;
for(i=0; i<30; i++) {
fiddly.ps[i]++;
fiddly.qs[i]++;
}
};
memset(&fiddly, 0xA5, sizeof(fiddly));
memset(&copy, 0x2A, sizeof(copy));
int i;
for(i=0; i<30; i++) {
fiddly.ps[i] = i * i * i;
fiddly.qs[i] = -i * i * i;
}
copy = fiddly;
incrementFiddly();
if ( &copy == &fiddly ) {
printf("%s: struct wasn't copied.", argv[0]);
exit(1);
}
for(i=0; i<30; i++) {
//printf("[%d]: fiddly.ps: %lu, copy.ps: %lu, fiddly.qs: %d, copy.qs: %d\n", i, fiddly.ps[i], copy.ps[i], fiddly.qs[i], copy.qs[i]);
if ( (fiddly.ps[i] != copy.ps[i] + 1) || (fiddly.qs[i] != copy.qs[i] + 1) ) {
printf("%s: struct contents were not incremented.", argv[0]);
exit(1);
}
}
printf("%s: success\n", argv[0]);
return 0;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
});
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}