block-blocks-test-8.C [plain text]
#include <objc/Object.h>
#import <Foundation/Foundation.h>
void * _NSConcreteStackBlock;
int CalledRetain = 0;
extern "C" id objc_msgSend(id target, SEL cmd, ...) {
printf("[%p %s] called\n", target, sel_getName(cmd));
if (!strcmp(sel_getName(cmd), "retain")) {
CalledRetain = 1;
}
return target;
}
@interface DumbObject : NSObject {
}
@end
id newDumbObject() {
DumbObject *result = (DumbObject *)calloc(sizeof(DumbObject), 1);
result->isa = objc_getClass("DumbObject");
return result;
}
@implementation DumbObject
+ new {
return newDumbObject();
}
+ (void) initialize { }
- forward:(SEL)msg :(long *)params {
printf("forward:: with %s called\n", sel_getName(msg));
return self;
}
@end
enum {
BLOCK_NEEDS_FREE = (1 << 24),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_NO_COPY = (1 << 26), BLOCK_IS_GC = (1 << 27),
};
struct Block_basic {
void *isa; int Block_flags;
int reserved;
void (*Block_invoke)(void *);
struct Block_descriptor_1 {
unsigned long int reserved; unsigned long int Block_size;
void (*Block_copy)(void *dst, void *src);
void (*Block_dispose)(void *src);
} *descriptor;
};
struct Block_byref {
void* isa;
struct Block_byref *forwarding;
int flags; int size;
void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
void (*byref_destroy)(struct Block_byref *);
};
int ByrefAssignCopy = 0;
void _Block_byref_assign_copy(void *destp, void *source) {
struct Block_byref *src = (struct Block_byref *)source;
ByrefAssignCopy = 1;
if ((src->flags & BLOCK_HAS_COPY_DISPOSE) == 0) {
printf("byref data block does not have bit saying that copy/dispose helper routines are present\n");
return;
}
printf("calling out to byref copy helper at %p\n", src->byref_keep);
int junk[100];
src->byref_keep((struct Block_byref *)junk, src);
}
void _Block_byref_release(void *source) {
struct Block_byref *src = (struct Block_byref *)source;
src->byref_destroy(src);
}
int main(int argc, char *argv[]) {
id __block dumbo = newDumbObject(); void (^dummy)(void) = ^{
[dumbo self];
};
struct Block_basic *aBlock = (struct Block_basic *)(void *)dummy;
if ((aBlock->Block_flags & BLOCK_HAS_COPY_DISPOSE) == 0) {
printf("Block should have a NON_POD copy/destroy helpers and flags to say so, but doesn't\n");
return 1;
}
char result[200];
printf("calling out to copy support helper at %p\n", aBlock->descriptor->Block_copy);
(*aBlock->descriptor->Block_copy)(result, aBlock);
if (! ByrefAssignCopy) {
printf("_Block_copy_assign not called\n");
return 1;
}
if (! CalledRetain) {
printf("byref block support helper did not call retain\n");
return 1;
}
(*aBlock->descriptor->Block_dispose)(aBlock);
return 0;
}