2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks
|
2008-09-06 06:11:13 +08:00
|
|
|
void donotwarn();
|
|
|
|
|
|
|
|
int (^IFP) ();
|
|
|
|
int (^II) (int);
|
|
|
|
int test1() {
|
2009-09-09 23:08:12 +08:00
|
|
|
int (^PFR) (int) = 0; // OK
|
|
|
|
PFR = II; // OK
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PFR == II) // OK
|
2009-04-01 09:17:39 +08:00
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PFR == IFP) // OK
|
2009-04-01 09:17:39 +08:00
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-04-01 09:17:39 +08:00
|
|
|
if (PFR == (int (^) (int))IFP) // OK
|
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PFR == 0) // OK
|
2009-04-01 09:17:39 +08:00
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PFR) // OK
|
2009-04-01 09:17:39 +08:00
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!PFR) // OK
|
2009-04-01 09:17:39 +08:00
|
|
|
donotwarn();
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
return PFR != IFP; // OK
|
2008-09-06 06:11:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int test2(double (^S)()) {
|
2009-04-01 09:17:39 +08:00
|
|
|
double (^I)(int) = (void*) S;
|
2009-09-09 23:08:12 +08:00
|
|
|
(void*)I = (void *)S; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}}
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-04-01 09:17:39 +08:00
|
|
|
void *pv = I;
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
pv = S;
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-04-01 09:17:39 +08:00
|
|
|
I(1);
|
|
|
|
|
|
|
|
return (void*)I == (void *)S;
|
2008-09-06 06:11:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int^ x; // expected-error {{block pointer to non-function type is invalid}}
|
2009-02-08 15:59:54 +08:00
|
|
|
int^^ x1; // expected-error {{block pointer to non-function type is invalid}} expected-error {{block pointer to non-function type is invalid}}
|
2008-09-06 06:11:13 +08:00
|
|
|
|
2009-07-22 08:43:08 +08:00
|
|
|
void test3() {
|
2009-04-01 09:17:39 +08:00
|
|
|
char *^ y; // expected-error {{block pointer to non-function type is invalid}}
|
2008-09-06 06:11:13 +08:00
|
|
|
}
|
|
|
|
|
2008-09-28 13:30:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
enum {NSBIRLazilyAllocated = 0};
|
|
|
|
|
|
|
|
int test4(int argc) { // rdar://6251437
|
|
|
|
^{
|
|
|
|
switch (argc) {
|
|
|
|
case NSBIRLazilyAllocated: // is an integer constant expression.
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}();
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-20 13:16:36 +08:00
|
|
|
|
|
|
|
|
2010-01-10 04:43:19 +08:00
|
|
|
void bar(void*);
|
2008-10-20 13:16:36 +08:00
|
|
|
// rdar://6257721 - reference to static/global is byref by default.
|
|
|
|
static int test5g;
|
|
|
|
void test5() {
|
|
|
|
bar(^{ test5g = 1; });
|
|
|
|
}
|
|
|
|
|
2008-12-05 07:50:19 +08:00
|
|
|
// rdar://6405429 - __func__ in a block refers to the containing function name.
|
|
|
|
const char*test6() {
|
2009-04-01 09:17:39 +08:00
|
|
|
return ^{
|
|
|
|
return __func__;
|
|
|
|
} ();
|
2008-12-05 07:50:19 +08:00
|
|
|
}
|
|
|
|
|
2009-04-01 09:17:39 +08:00
|
|
|
// radr://6732116 - block comparisons
|
2009-04-19 03:32:54 +08:00
|
|
|
void (^test7a)();
|
|
|
|
int test7(void (^p)()) {
|
|
|
|
return test7a == p;
|
2009-04-01 09:17:39 +08:00
|
|
|
}
|
2009-04-19 03:32:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
void test8() {
|
|
|
|
somelabel:
|
2010-01-20 07:08:01 +08:00
|
|
|
^{ goto somelabel; }(); // expected-error {{use of undeclared label 'somelabel'}}
|
2009-04-19 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void test9() {
|
|
|
|
goto somelabel; // expected-error {{use of undeclared label 'somelabel'}}
|
|
|
|
^{ somelabel: ; }();
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:10:59 +08:00
|
|
|
void test10(int i) {
|
|
|
|
switch (i) {
|
|
|
|
case 41: ;
|
|
|
|
^{ case 42: ; }(); // expected-error {{'case' statement not in switch statement}}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test11(int i) {
|
|
|
|
switch (i) {
|
|
|
|
case 41: ;
|
|
|
|
^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; i < 100; ++i)
|
|
|
|
^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}}
|
|
|
|
}
|
|
|
|
|
2009-04-22 06:38:46 +08:00
|
|
|
void (^test12f)(void);
|
|
|
|
void test12() {
|
2009-09-09 23:08:12 +08:00
|
|
|
test12f = ^test12f; // expected-error {{type name requires a specifier or qualifier}} expected-error {{expected expression}}
|
2009-04-22 06:38:46 +08:00
|
|
|
}
|
|
|
|
|
2009-04-22 06:26:47 +08:00
|
|
|
// rdar://6808730
|
|
|
|
void *test13 = ^{
|
|
|
|
int X = 32;
|
|
|
|
|
|
|
|
void *P = ^{
|
|
|
|
return X+4; // References outer block's "X", so outer block is constant.
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
void test14() {
|
|
|
|
int X = 32;
|
|
|
|
static void *P = ^{ // expected-error {{initializer element is not a compile-time constant}}
|
|
|
|
|
|
|
|
void *Q = ^{
|
2013-12-05 12:47:09 +08:00
|
|
|
// References test14's "X": outer block is non-constant.
|
2009-04-22 06:26:47 +08:00
|
|
|
return X+4;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
2009-04-22 06:51:42 +08:00
|
|
|
|
2009-04-22 07:03:34 +08:00
|
|
|
enum { LESS };
|
|
|
|
|
2010-04-22 08:20:18 +08:00
|
|
|
void foo(long (^comp)()) { // expected-note{{passing argument to parameter 'comp' here}}
|
2009-04-22 07:03:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void (^test15f)(void);
|
|
|
|
void test15() {
|
2010-04-09 08:35:39 +08:00
|
|
|
foo(^{ return LESS; }); // expected-error {{incompatible block pointer types passing 'int (^)(void)' to parameter of type 'long (^)()'}}
|
2009-04-22 06:51:42 +08:00
|
|
|
}
|
2009-04-30 08:19:40 +08:00
|
|
|
|
|
|
|
__block int test16i; // expected-error {{__block attribute not allowed, only allowed on local variables}}
|
|
|
|
|
|
|
|
void test16(__block int i) { // expected-error {{__block attribute not allowed, only allowed on local variables}}
|
2009-05-02 07:41:47 +08:00
|
|
|
int size = 5;
|
2009-04-30 08:19:40 +08:00
|
|
|
extern __block double extern_var; // expected-error {{__block attribute not allowed, only allowed on local variables}}
|
|
|
|
static __block char * pch; // expected-error {{__block attribute not allowed, only allowed on local variables}}
|
2009-05-02 07:41:47 +08:00
|
|
|
__block int a[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}}
|
|
|
|
__block int (*ap)[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}}
|
2009-04-30 08:19:40 +08:00
|
|
|
}
|
2009-05-07 11:14:14 +08:00
|
|
|
|
2010-01-10 04:43:19 +08:00
|
|
|
void f();
|
|
|
|
|
2009-05-07 11:14:14 +08:00
|
|
|
void test17() {
|
|
|
|
void (^bp)(int);
|
|
|
|
void (*rp)(int);
|
|
|
|
void (^bp1)();
|
|
|
|
void *vp = bp;
|
|
|
|
|
|
|
|
f(1 ? bp : vp);
|
|
|
|
f(1 ? vp : bp);
|
2009-06-08 12:24:21 +08:00
|
|
|
f(1 ? bp : bp1);
|
2009-05-07 11:14:14 +08:00
|
|
|
(void)(bp > rp); // expected-error {{invalid operands}}
|
|
|
|
(void)(bp > 0); // expected-error {{invalid operands}}
|
|
|
|
(void)(bp > bp); // expected-error {{invalid operands}}
|
|
|
|
(void)(bp > vp); // expected-error {{invalid operands}}
|
|
|
|
f(1 ? bp : rp); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (*)(int)')}}
|
2009-05-08 02:43:07 +08:00
|
|
|
(void)(bp == 1); // expected-error {{invalid operands to binary expression}}
|
|
|
|
(void)(bp == 0);
|
|
|
|
(void)(1 == bp); // expected-error {{invalid operands to binary expression}}
|
|
|
|
(void)(0 == bp);
|
|
|
|
(void)(bp < 1); // expected-error {{invalid operands to binary expression}}
|
|
|
|
(void)(bp < 0); // expected-error {{invalid operands to binary expression}}
|
|
|
|
(void)(1 < bp); // expected-error {{invalid operands to binary expression}}
|
|
|
|
(void)(0 < bp); // expected-error {{invalid operands to binary expression}}
|
2009-05-07 11:14:14 +08:00
|
|
|
}
|
2009-05-08 05:56:17 +08:00
|
|
|
|
|
|
|
void test18() {
|
2015-04-11 09:53:13 +08:00
|
|
|
void (^const blockA)(void) = ^{ }; // expected-note {{variable 'blockA' declared const here}}
|
|
|
|
blockA = ^{ }; // expected-error {{cannot assign to variable 'blockA' with const-qualified type 'void (^const)(void)}}
|
2009-05-08 05:56:17 +08:00
|
|
|
}
|
2009-07-20 04:17:11 +08:00
|
|
|
|
|
|
|
// rdar://7072507
|
|
|
|
int test19() {
|
2014-09-06 08:24:58 +08:00
|
|
|
goto L0; // expected-error {{cannot jump}}
|
2009-07-20 04:17:11 +08:00
|
|
|
|
|
|
|
__block int x; // expected-note {{jump bypasses setup of __block variable}}
|
|
|
|
L0:
|
|
|
|
x = 0;
|
|
|
|
^(){ ++x; }();
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2010-01-05 10:56:35 +08:00
|
|
|
// radr://7438948
|
|
|
|
void test20() {
|
|
|
|
int n = 7;
|
2010-04-23 10:20:12 +08:00
|
|
|
int vla[n]; // expected-note {{declared here}}
|
|
|
|
int (*vm)[n] = 0; // expected-note {{declared here}}
|
2010-01-05 10:56:35 +08:00
|
|
|
vla[1] = 4341;
|
|
|
|
^{
|
|
|
|
(void)vla[1]; // expected-error {{cannot refer to declaration with a variably modified type inside block}}
|
|
|
|
(void)(vm+1); // expected-error {{cannot refer to declaration with a variably modified type inside block}}
|
|
|
|
}();
|
|
|
|
}
|
2010-01-05 11:10:36 +08:00
|
|
|
|
2010-01-05 11:16:33 +08:00
|
|
|
// radr://7438948
|
2010-01-05 11:10:36 +08:00
|
|
|
void test21() {
|
2010-04-23 10:20:12 +08:00
|
|
|
int a[7]; // expected-note {{declared here}}
|
|
|
|
__block int b[10]; // expected-note {{declared here}}
|
2010-01-05 11:10:36 +08:00
|
|
|
a[1] = 1;
|
|
|
|
^{
|
|
|
|
(void)a[1]; // expected-error {{cannot refer to declaration with an array type inside block}}
|
2010-03-17 07:39:51 +08:00
|
|
|
(void)b[1]; // expected-error {{cannot refer to declaration with an array type inside block}}
|
2010-01-05 11:10:36 +08:00
|
|
|
}();
|
|
|
|
}
|
2010-07-24 05:53:24 +08:00
|
|
|
|
|
|
|
// rdar ://8218839
|
|
|
|
const char * (^func)(void) = ^{ return __func__; };
|
|
|
|
const char * (^function)(void) = ^{ return __FUNCTION__; };
|
|
|
|
const char * (^pretty)(void) = ^{ return __PRETTY_FUNCTION__; };
|