[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CodeGenObjC / arc-captured-block-var-layout.m
blob366f8882ad4ab2e22645eebe8895a8a121445bca
1 // RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout
2 // RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.layout %s
4 void x(id y) {}
5 void y(int a) {}
7 extern id opaque_id(void);
9 void f(void) {
10     __weak id wid;
11     __block int byref_int = 0;
12     char ch = 'a';
13     char ch1 = 'b';
14     char ch2 = 'c';
15     short sh = 2;
16     const id bar = (id) opaque_id();
17     id baz = 0;
18     __strong id strong_void_sta;
19     __block id byref_bab = (id)0;
20     __block id bl_var1;
21     int i; double dob;
23 // The patterns here are a sequence of bytes, each saying first how
24 // many sizeof(void*) chunks to skip (high nibble) and then how many
25 // to scan (low nibble).  A zero byte says that we've reached the end
26 // of the pattern.
28 // All of these patterns start with 01 3x because the block header on
29 // LP64 consists of an isa pointer (which we're supposed to scan for
30 // some reason) followed by three words (2 ints, a function pointer,
31 // and a descriptor pointer).
33 // Test 1
34 // Inline instruction for block variable layout: 0x0320 (3 strong 2 byref)
35 // CHECK-LP64: Inline block variable layout: 0x0320, BL_STRONG:3, BL_BYREF:2, BL_OPERATOR:0
36     void (^b)(void) = ^{
37         byref_int = sh + ch+ch1+ch2 ;
38         x(bar);
39         x(baz);
40         x((id)strong_void_sta);
41         x(byref_bab);
42     };    
43     b();
45 // Test 2
46 // Inline instruction for block variable layout: 0x0331 (3 strong 3 byref 1 weak)
47 // CHECK-LP64: Inline block variable layout: 0x0331, BL_STRONG:3, BL_BYREF:3, BL_WEAK:1, BL_OPERATOR:0
48     void (^c)(void) = ^{
49         byref_int = sh + ch+ch1+ch2 ;
50         x(bar);
51         x(baz);
52         x((id)strong_void_sta);
53         x(wid);
54         bl_var1 = 0;
55         x(byref_bab);
56     };    
59 @class NSString, NSNumber;
60 void g(void) {
61   NSString *foo;
62    NSNumber *bar;
63    unsigned int bletch;
64    __weak id weak_delegate;
65   unsigned int i;
66   NSString *y;
67   NSString *z;
68 // Inline instruction for block variable layout: 0x0401 (4 strong 0 byref 1 weak)
69 // CHECK-LP64: Inline block variable layout: 0x0401, BL_STRONG:4, BL_WEAK:1, BL_OPERATOR:0
70   void (^c)(void) = ^{
71    int j = i + bletch;
72    x(foo);
73    x(bar);
74    x(weak_delegate);
75    x(y);
76    x(z); 
77   };
78   c();
81 // Test 5 (unions/structs and their nesting):
82 void h(void) {
83   struct S5 {
84     int i1;
85     __unsafe_unretained id o1;
86     struct V {
87      int i2;
88      __unsafe_unretained id o2;
89     } v1;
90     int i3;
91     union UI {
92         void * i1;
93         __unsafe_unretained id o1;
94         int i3;
95         __unsafe_unretained id o3;
96     }ui;
97   };
99   union U {
100         void * i1;
101         __unsafe_unretained id o1;
102         int i3;
103         __unsafe_unretained id o3;
104   }ui;
106   struct S5 s2;
107   union U u2;
108   __block id block_id;
110 // CHECK-LP64: Block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0
111   void (^c)(void) = ^{
112     x(s2.ui.o1);
113     x(u2.o1);
114     block_id = 0;
115   };
116   c();
119 // Test for array of stuff.
120 void arr1(void) {
121   struct S {
122     __unsafe_unretained id unsafe_unretained_var[4];
123  } imported_s;
125 // CHECK-LP64: Block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0
126     void (^c)(void) = ^{
127         x(imported_s.unsafe_unretained_var[2]);
128     };    
130    c();
133 // Test2 for array of stuff.
134 void arr2(void) {
135   struct S {
136    int a;
137     __unsafe_unretained id unsafe_unretained_var[4];
138  } imported_s;
140 // CHECK-LP64: Block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0
141     void (^c)(void) = ^{
142         x(imported_s.unsafe_unretained_var[2]);
143     };    
145    c();
148 // Test3 for array of stuff.
149 void arr3(void) {
150   struct S {
151    int a;
152     __unsafe_unretained id unsafe_unretained_var[0];
153  } imported_s;
155 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
156     void (^c)(void) = ^{
157       int i = imported_s.a;
158     };    
160    c();
164 // Test4 for array of stuff.
165 @class B;
166 void arr4(void) {
167   struct S {
168     struct s0 {
169       __unsafe_unretained id s_f0;
170       __unsafe_unretained id s_f1;
171     } f0;
173     __unsafe_unretained id f1;
175     struct s1 {
176       int *f0;
177       __unsafe_unretained B *f1;
178     } f4[2][2];
179   } captured_s;
181 // CHECK-LP64: Block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0
182   void (^c)(void) = ^{
183       id i = captured_s.f0.s_f1;
184   };
186    c();
189 // Test1 bitfield in cpatured aggregate.
190 void bf1(void) {
191   struct S {
192     int flag : 25;
193     int flag1: 7;
194     int flag2 :1;
195     int flag3: 7;
196     int flag4: 24;
197   } s;
199 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
200   int (^c)(void) = ^{
201       return s.flag;
202   };
203   c();
206 // Test2 bitfield in cpatured aggregate.
207 void bf2(void) {
208   struct S {
209     int flag : 1;
210   } s;
212 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
213   int (^c)(void) = ^{
214       return s.flag;
215   };
216   c();
219 // Test3 bitfield in cpatured aggregate.
220 void bf3(void) {
222      struct {
223         unsigned short _reserved : 16;
225         unsigned char _draggedNodesAreDeletable: 1;
226         unsigned char _draggedOutsideOutlineView : 1;
227         unsigned char _adapterRespondsTo_addRootPaths : 1;
228         unsigned char _adapterRespondsTo_moveDataNodes : 1;
229         unsigned char _adapterRespondsTo_removeRootDataNode : 1;
230         unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
231         unsigned char _adapterRespondsTo_selectDataNode : 1;
232         unsigned char _adapterRespondsTo_textDidEndEditing : 1;
233         unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
234         unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
235         unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
236         unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
237         unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
238         unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
240         unsigned int _filler : 32;
241     } _flags;
243 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
244   unsigned char (^c)(void) = ^{
245       return _flags._draggedNodesAreDeletable;
246   };
248    c();
251 // Test4 unnamed bitfield
252 void bf4(void) {
254      struct {
255         unsigned short _reserved : 16;
257         unsigned char _draggedNodesAreDeletable: 1;
258         unsigned char _draggedOutsideOutlineView : 1;
259         unsigned char _adapterRespondsTo_addRootPaths : 1;
260         unsigned char _adapterRespondsTo_moveDataNodes : 1;
261         unsigned char _adapterRespondsTo_removeRootDataNode : 1;
262         unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
263         unsigned char _adapterRespondsTo_selectDataNode : 1;
264         unsigned char _adapterRespondsTo_textDidEndEditing : 1;
266         unsigned long long : 64;
268         unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
269         unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
270         unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
271         unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
272         unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
273         unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
275         unsigned int _filler : 32;
276     } _flags;
278 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
279   unsigned char (^c)(void) = ^{
280       return _flags._draggedNodesAreDeletable;
281   };
283    c();
288 // Test5 unnamed bitfield.
289 void bf5(void) {
290      struct {
291         unsigned char flag : 1;
292         unsigned int  : 32;
293         unsigned char flag1 : 1;
294     } _flags;
296 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
297   unsigned char (^c)(void) = ^{
298       return _flags.flag;
299   };
301    c();
305 // Test6 0 length bitfield.
306 void bf6(void) {
307      struct {
308         unsigned char flag : 1;
309         unsigned int  : 0;
310         unsigned char flag1 : 1;
311     } _flags;
313 // CHECK-LP64: Block variable layout: BL_OPERATOR:0
314   unsigned char (^c)(void) = ^{
315       return _flags.flag;
316   };
318    c();
321 // Test7 large number of captured variables.
322 void Test7(void) {
323     __weak id wid;
324     __weak id wid1, wid2, wid3, wid4;
325     __weak id wid5, wid6, wid7, wid8;
326     __weak id wid9, wid10, wid11, wid12;
327     __weak id wid13, wid14, wid15, wid16;
328     const id bar = (id) opaque_id();
329 // CHECK-LP64: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0
330     void (^b)(void) = ^{
331       x(bar);
332       x(wid1);
333       x(wid2);
334       x(wid3);
335       x(wid4);
336       x(wid5);
337       x(wid6);
338       x(wid7);
339       x(wid8);
340       x(wid9);
341       x(wid10);
342       x(wid11);
343       x(wid12);
344       x(wid13);
345       x(wid14);
346       x(wid15);
347       x(wid16);
348     };    
352 // Test 8 very large number of captured variables.
353 void Test8(void) {
354 __weak id wid;
355     __weak id wid1, wid2, wid3, wid4;
356     __weak id wid5, wid6, wid7, wid8;
357     __weak id wid9, wid10, wid11, wid12;
358     __weak id wid13, wid14, wid15, wid16;
359     __weak id w1, w2, w3, w4;
360     __weak id w5, w6, w7, w8;
361     __weak id w9, w10, w11, w12;
362     __weak id w13, w14, w15, w16;
363     const id bar = (id) opaque_id();
364 // CHECK-LP64: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0
365     void (^b)(void) = ^{
366       x(bar);
367       x(wid1);
368       x(wid2);
369       x(wid3);
370       x(wid4);
371       x(wid5);
372       x(wid6);
373       x(wid7);
374       x(wid8);
375       x(wid9);
376       x(wid10);
377       x(wid11);
378       x(wid12);
379       x(wid13);
380       x(wid14);
381       x(wid15);
382       x(wid16);
383       x(w1);
384       x(w2);
385       x(w3);
386       x(w4);
387       x(w5);
388       x(w6);
389       x(w7);
390       x(w8);
391       x(w9);
392       x(w10);
393       x(w11);
394       x(w12);
395       x(w13);
396       x(w14);
397       x(w15);
398       x(w16);
399       x(wid);
400     };