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