1 | // RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks |
2 | void donotwarn(); |
3 | |
4 | int (^IFP) (); |
5 | int (^II) (int); |
6 | int test1() { |
7 | int (^PFR) (int) = 0; // OK |
8 | PFR = II; // OK |
9 | |
10 | if (PFR == II) // OK |
11 | donotwarn(); |
12 | |
13 | if (PFR == IFP) // OK |
14 | donotwarn(); |
15 | |
16 | if (PFR == (int (^) (int))IFP) // OK |
17 | donotwarn(); |
18 | |
19 | if (PFR == 0) // OK |
20 | donotwarn(); |
21 | |
22 | if (PFR) // OK |
23 | donotwarn(); |
24 | |
25 | if (!PFR) // OK |
26 | donotwarn(); |
27 | |
28 | return PFR != IFP; // OK |
29 | } |
30 | |
31 | int test2(double (^S)()) { |
32 | double (^I)(int) = (void*) S; |
33 | (void*)I = (void *)S; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} |
34 | |
35 | void *pv = I; |
36 | |
37 | pv = S; |
38 | |
39 | I(1); |
40 | |
41 | return (void*)I == (void *)S; |
42 | } |
43 | |
44 | int^ x; // expected-error {{block pointer to non-function type is invalid}} |
45 | int^^ x1; // expected-error {{block pointer to non-function type is invalid}} expected-error {{block pointer to non-function type is invalid}} |
46 | |
47 | void test3() { |
48 | char *^ y; // expected-error {{block pointer to non-function type is invalid}} |
49 | } |
50 | |
51 | |
52 | |
53 | enum {NSBIRLazilyAllocated = 0}; |
54 | |
55 | int test4(int argc) { // rdar://6251437 |
56 | ^{ |
57 | switch (argc) { |
58 | case NSBIRLazilyAllocated: // is an integer constant expression. |
59 | default: |
60 | break; |
61 | } |
62 | }(); |
63 | return 0; |
64 | } |
65 | |
66 | |
67 | void bar(void*); |
68 | // rdar://6257721 - reference to static/global is byref by default. |
69 | static int test5g; |
70 | void test5() { |
71 | bar(^{ test5g = 1; }); |
72 | } |
73 | |
74 | // rdar://6405429 - __func__ in a block refers to the containing function name. |
75 | const char*test6() { |
76 | return ^{ |
77 | return __func__; |
78 | } (); |
79 | } |
80 | |
81 | // radr://6732116 - block comparisons |
82 | void (^test7a)(); |
83 | int test7(void (^p)()) { |
84 | return test7a == p; |
85 | } |
86 | |
87 | |
88 | void test8() { |
89 | somelabel: |
90 | ^{ goto somelabel; }(); // expected-error {{use of undeclared label 'somelabel'}} |
91 | } |
92 | |
93 | void test9() { |
94 | goto somelabel; // expected-error {{use of undeclared label 'somelabel'}} |
95 | ^{ somelabel: ; }(); |
96 | } |
97 | |
98 | void test10(int i) { |
99 | switch (i) { |
100 | case 41: ; |
101 | ^{ case 42: ; }(); // expected-error {{'case' statement not in switch statement}} |
102 | } |
103 | } |
104 | |
105 | void test11(int i) { |
106 | switch (i) { |
107 | case 41: ; |
108 | ^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}} |
109 | } |
110 | |
111 | for (; i < 100; ++i) |
112 | ^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}} |
113 | } |
114 | |
115 | void (^test12f)(void); |
116 | void test12() { |
117 | test12f = ^test12f; // expected-error {{type name requires a specifier or qualifier}} expected-error {{expected expression}} |
118 | } |
119 | |
120 | // rdar://6808730 |
121 | void *test13 = ^{ |
122 | int X = 32; |
123 | |
124 | void *P = ^{ |
125 | return X+4; // References outer block's "X", so outer block is constant. |
126 | }; |
127 | }; |
128 | |
129 | void test14() { |
130 | int X = 32; |
131 | static void *P = ^{ // expected-error {{initializer element is not a compile-time constant}} |
132 | |
133 | void *Q = ^{ |
134 | // References test14's "X": outer block is non-constant. |
135 | return X+4; |
136 | }; |
137 | }; |
138 | } |
139 | |
140 | enum { LESS }; |
141 | |
142 | void foo(long (^comp)()) { // expected-note{{passing argument to parameter 'comp' here}} |
143 | } |
144 | |
145 | void (^test15f)(void); |
146 | void test15() { |
147 | foo(^{ return LESS; }); // expected-error {{incompatible block pointer types passing 'int (^)(void)' to parameter of type 'long (^)()'}} |
148 | } |
149 | |
150 | __block int test16i; // expected-error {{__block attribute not allowed, only allowed on local variables}} |
151 | |
152 | void test16(__block int i) { // expected-error {{__block attribute not allowed, only allowed on local variables}} |
153 | int size = 5; |
154 | extern __block double extern_var; // expected-error {{__block attribute not allowed, only allowed on local variables}} |
155 | static __block char * pch; // expected-error {{__block attribute not allowed, only allowed on local variables}} |
156 | __block int a[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}} |
157 | __block int (*ap)[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}} |
158 | } |
159 | |
160 | void f(); |
161 | |
162 | void test17() { |
163 | void (^bp)(int); |
164 | void (*rp)(int); |
165 | void (^bp1)(); |
166 | void *vp = bp; |
167 | |
168 | f(1 ? bp : vp); |
169 | f(1 ? vp : bp); |
170 | f(1 ? bp : bp1); |
171 | (void)(bp > rp); // expected-error {{invalid operands}} |
172 | (void)(bp > 0); // expected-error {{invalid operands}} |
173 | (void)(bp > bp); // expected-error {{invalid operands}} |
174 | (void)(bp > vp); // expected-error {{invalid operands}} |
175 | f(1 ? bp : rp); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (*)(int)')}} |
176 | (void)(bp == 1); // expected-error {{invalid operands to binary expression}} |
177 | (void)(bp == 0); |
178 | (void)(1 == bp); // expected-error {{invalid operands to binary expression}} |
179 | (void)(0 == bp); |
180 | (void)(bp < 1); // expected-error {{invalid operands to binary expression}} |
181 | (void)(bp < 0); // expected-error {{invalid operands to binary expression}} |
182 | (void)(1 < bp); // expected-error {{invalid operands to binary expression}} |
183 | (void)(0 < bp); // expected-error {{invalid operands to binary expression}} |
184 | } |
185 | |
186 | void test18() { |
187 | void (^const blockA)(void) = ^{ }; // expected-note {{variable 'blockA' declared const here}} |
188 | blockA = ^{ }; // expected-error {{cannot assign to variable 'blockA' with const-qualified type 'void (^const)(void)}} |
189 | } |
190 | |
191 | // rdar://7072507 |
192 | int test19() { |
193 | goto L0; // expected-error {{cannot jump}} |
194 | |
195 | __block int x; // expected-note {{jump bypasses setup of __block variable}} |
196 | L0: |
197 | x = 0; |
198 | ^(){ ++x; }(); |
199 | return x; |
200 | } |
201 | |
202 | // radr://7438948 |
203 | void test20() { |
204 | int n = 7; |
205 | int vla[n]; // expected-note {{declared here}} |
206 | int (*vm)[n] = 0; // expected-note {{declared here}} |
207 | vla[1] = 4341; |
208 | ^{ |
209 | (void)vla[1]; // expected-error {{cannot refer to declaration with a variably modified type inside block}} |
210 | (void)(vm+1); // expected-error {{cannot refer to declaration with a variably modified type inside block}} |
211 | }(); |
212 | } |
213 | |
214 | // radr://7438948 |
215 | void test21() { |
216 | int a[7]; // expected-note {{declared here}} |
217 | __block int b[10]; // expected-note {{declared here}} |
218 | a[1] = 1; |
219 | ^{ |
220 | (void)a[1]; // expected-error {{cannot refer to declaration with an array type inside block}} |
221 | (void)b[1]; // expected-error {{cannot refer to declaration with an array type inside block}} |
222 | }(); |
223 | } |
224 | |
225 | // rdar ://8218839 |
226 | const char * (^func)(void) = ^{ return __func__; }; |
227 | const char * (^function)(void) = ^{ return __FUNCTION__; }; |
228 | const char * (^pretty)(void) = ^{ return __PRETTY_FUNCTION__; }; |
229 | |