1 | // RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout |
2 | // RUN: FileCheck --input-file=%t-64.layout %s |
3 | // rdar://12184410 |
4 | // rdar://12752901 |
5 | |
6 | // See commentary in test/CodeGenObjC/block-var-layout.m, from which |
7 | // this is largely cloned. |
8 | |
9 | struct S { |
10 | int i1; |
11 | id o1; |
12 | struct V { |
13 | int i2; |
14 | id o2; |
15 | } v1; |
16 | int i3; |
17 | id o3; |
18 | }; |
19 | |
20 | __weak id wid; |
21 | void x(id y) {} |
22 | void y(int a) {} |
23 | |
24 | extern id opaque_id(); |
25 | |
26 | void f() { |
27 | __block int byref_int = 0; |
28 | char ch = 'a'; |
29 | char ch1 = 'b'; |
30 | char ch2 = 'c'; |
31 | short sh = 2; |
32 | const id bar = (id) opaque_id(); |
33 | id baz = 0; |
34 | __strong void *strong_void_sta; |
35 | __block id byref_bab = (id)0; |
36 | __block void *bl_var1; |
37 | int i; double dob; |
38 | |
39 | // Test 1 |
40 | // byref int, short, char, char, char, id, id, strong void*, byref id |
41 | // 01 35 10 00 |
42 | // CHECK: block variable layout for block: 0x01, 0x35, 0x10, 0x00 |
43 | void (^b)() = ^{ |
44 | byref_int = sh + ch+ch1+ch2 ; |
45 | x(bar); |
46 | x(baz); |
47 | x((id)strong_void_sta); |
48 | x(byref_bab); |
49 | }; |
50 | b(); |
51 | |
52 | // Test 2 |
53 | // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id |
54 | // 01 36 10 00 |
55 | // CHECK: 0x01, 0x36, 0x10, 0x00 |
56 | void (^c)() = ^{ |
57 | byref_int = sh + ch+ch1+ch2 ; |
58 | x(bar); |
59 | x(baz); |
60 | x((id)strong_void_sta); |
61 | x(wid); |
62 | bl_var1 = 0; |
63 | x(byref_bab); |
64 | }; |
65 | c(); |
66 | |
67 | // Test 3 |
68 | // byref int, short, char, char, char, id, id, byref void*, int, double, byref id |
69 | // 01 34 11 30 00 |
70 | // CHECK: block variable layout for block: 0x01, 0x35, 0x30, 0x00 |
71 | void (^d)() = ^{ |
72 | byref_int = sh + ch+ch1+ch2 ; |
73 | x(bar); |
74 | x(baz); |
75 | x(wid); |
76 | bl_var1 = 0; |
77 | y(i + dob); |
78 | x(byref_bab); |
79 | }; |
80 | d(); |
81 | |
82 | // Test4 |
83 | // struct S (int, id, int, id, int, id) |
84 | // 01 41 11 11 00 |
85 | // CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00 |
86 | struct S s2; |
87 | void (^e)() = ^{ |
88 | x(s2.o1); |
89 | }; |
90 | e(); |
91 | } |
92 | |
93 | // Test 5 (unions/structs and their nesting): |
94 | void Test5() { |
95 | struct S5 { |
96 | int i1; |
97 | id o1; |
98 | struct V { |
99 | int i2; |
100 | id o2; |
101 | } v1; |
102 | int i3; |
103 | union UI { |
104 | void * i1; |
105 | id o1; |
106 | int i3; |
107 | id o3; |
108 | }ui; |
109 | }; |
110 | |
111 | union U { |
112 | void * i1; |
113 | id o1; |
114 | int i3; |
115 | id o3; |
116 | }ui; |
117 | |
118 | struct S5 s2; |
119 | union U u2; |
120 | |
121 | // struct s2 (int, id, int, id, int, id?), union u2 (id?) |
122 | // 01 41 11 12 00 |
123 | // CHECK: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00 |
124 | void (^c)() = ^{ |
125 | x(s2.ui.o1); |
126 | x(u2.o1); |
127 | }; |
128 | c(); |
129 | |
130 | } |
131 | |
132 | // rdar: //8417746 |
133 | void CFRelease(id); |
134 | void notifyBlock(id dependentBlock) { |
135 | id singleObservationToken; |
136 | id token; |
137 | void (^b)(); |
138 | |
139 | // id, id, void(^)() |
140 | // 01 33 00 |
141 | // CHECK: block variable layout for block: 0x01, 0x33, 0x00 |
142 | void (^wrapperBlock)() = ^() { |
143 | CFRelease(singleObservationToken); |
144 | CFRelease(singleObservationToken); |
145 | CFRelease(token); |
146 | CFRelease(singleObservationToken); |
147 | b(); |
148 | }; |
149 | wrapperBlock(); |
150 | } |
151 | |
152 | void test_empty_block() { |
153 | // 01 00 |
154 | // CHECK: block variable layout for block: 0x01, 0x30, 0x00 |
155 | void (^wrapperBlock)() = ^() { |
156 | }; |
157 | wrapperBlock(); |
158 | } |
159 | |