1#include "../objc/runtime.h"
2#include "../objc/blocks_runtime.h"
3#include <assert.h>
4#include <stdio.h>
5#include <stdlib.h>
6
7struct big
8{
9	int a, b, c, d, e;
10};
11
12#ifdef __has_attribute
13#if __has_attribute(objc_root_class)
14__attribute__((objc_root_class))
15#endif
16#endif
17@interface Foo @end
18@implementation Foo @end
19@interface Foo (Dynamic)
20+(int)count: (int)i;
21+(struct big)sret;
22@end
23
24
25int main(void)
26{
27	__block Class cls = objc_getClass("Foo");
28	__block int b = 0;
29	void* blk = ^(id self, int a) {
30		assert(self == cls);
31		b += a;
32		return b; };
33	blk = Block_copy(blk);
34	IMP imp = imp_implementationWithBlock(blk);
35	char *type = block_copyIMPTypeEncoding_np(blk);
36	assert(NULL != type);
37	class_addMethod((objc_getMetaClass("Foo")), @selector(count:), imp, type);
38	assert(2 == ((int(*)(id,SEL,int))imp)(cls, @selector(count:), 2));
39	free(type);
40	assert(4 == [Foo count: 2]);
41	assert(6 == [Foo count: 2]);
42	assert(imp_getBlock(imp) == (blk));
43	IMP imp2 = imp_implementationWithBlock(blk);
44	assert(imp != imp2);
45	imp_removeBlock(imp);
46	assert(imp_getBlock(imp) != (blk));
47
48	blk = ^(id self) {
49		assert(self == cls);
50		struct big b = {1, 2, 3, 4, 5};
51		return b;
52	};
53	imp = imp_implementationWithBlock(blk);
54	assert(imp && "Can't make sret IMP");
55	type = block_copyIMPTypeEncoding_np(blk);
56	assert(NULL != type);
57	class_addMethod((objc_getMetaClass("Foo")), @selector(sret), imp, type);
58	free(type);
59	struct big s = [Foo sret];
60	assert(s.a == 1);
61	assert(s.b == 2);
62	assert(s.c == 3);
63	assert(s.d == 4);
64	assert(s.e == 5);
65	return 0;
66}
67