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
9struct 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;
21void x(id y) {}
22void y(int a) {}
23
24extern id opaque_id();
25
26void 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
71void (^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):
94void 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
133void CFRelease(id);
134void 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
152void test_empty_block() {
153// 01 00
154// CHECK: block variable layout for block: 0x01, 0x30, 0x00
155 void (^wrapperBlock)() = ^() {
156    };
157 wrapperBlock();
158}
159