xref: /llvm-project/clang/test/Sema/block-return.c (revision ca148b21505e97f07787c13ec00ffc086d4658d0)
1 // RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks
2 // RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks -fexperimental-new-constant-interpreter
3 
4 extern int printf(const char *, ...);
5 
6 typedef void (^CL)(void);
7 
8 CL foo(void) {
9   short y;
10   short (^add1)(void) = ^{ return y+1; }; // expected-error {{incompatible block pointer types initializing 'short (^)(void)' with an expression of type 'int (^)(void)'}}
11 
12   CL X = ^{
13     if (2)
14       return;
15     return 1;  // expected-error {{return type 'int' must match previous return type 'void' when block literal has unspecified explicit return type}}
16   };
17 
18   int (^Y) (void)  = ^{
19     if (3)
20       return 1;
21     else
22       return; // expected-error {{return type 'void' must match previous return type 'int' when block literal has unspecified explicit return type}}
23   };
24 
25   char *(^Z)(void) = ^{
26     if (3)
27       return "";
28     else
29       return (char*)0;
30   };
31 
32   double (^A)(void) = ^ { // expected-error {{incompatible block pointer types initializing 'double (^)(void)' with an expression of type 'float (^)(void)'}}
33     if (1)
34       return (float)1.0;
35     else
36       if (2)
37         return (double)2.0; // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}}
38     return 1; // expected-error {{return type 'int' must match previous return type 'float' when block literal has unspecified explicit return type}}
39   };
40   char *(^B)(void) = ^{
41     if (3)
42       return "";
43     else
44       return 2; // expected-error {{return type 'int' must match previous return type 'char *' when block literal has unspecified explicit return type}}
45   };
46 
47   return ^{ return 1; }; // expected-error {{incompatible block pointer types returning 'int (^)(void)' from a function with result type 'CL' (aka 'void (^)(void)')}}
48 }
49 
50 typedef int (^CL2)(void);
51 
52 CL2 foo2(void) {
53   return ^{ return 1; };
54 }
55 
56 typedef unsigned int * uintptr_t;
57 typedef char Boolean;
58 typedef int CFBasicHash;
59 
60 #define INVOKE_CALLBACK2(P, A, B) (P)(A, B)
61 
62 typedef struct {
63     Boolean (^isEqual)(const CFBasicHash *, uintptr_t stack_value_or_key1, uintptr_t stack_value_or_key2, Boolean is_key);
64 } CFBasicHashCallbacks;
65 
66 int foo3(void) {
67     CFBasicHashCallbacks cb;
68 
69     Boolean (*value_equal)(uintptr_t, uintptr_t) = 0;
70 
71     cb.isEqual = ^(const CFBasicHash *table, uintptr_t stack_value_or_key1, uintptr_t stack_value_or_key2, Boolean is_key) {
72       return (Boolean)(uintptr_t)INVOKE_CALLBACK2(value_equal, (uintptr_t)stack_value_or_key1, (uintptr_t)stack_value_or_key2);
73     };
74 }
75 
76 static int funk(char *s) {
77   if (^{} == ((void*)0))
78     return 1;
79   else
80     return 0;
81 }
82 void next(void);
83 void foo4(void) {
84   int (^xx)(const char *s) = ^(char *s) { return 1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(const char *)' with an expression of type 'int (^)(char *)'}}
85   int (*yy)(const char *s) = funk; // expected-error {{incompatible function pointer types initializing 'int (*)(const char *)' with an expression of type 'int (char *)'}}
86 
87   int (^nested)(char *s) = ^(char *str) { void (^nest)(void) = ^(void) { printf("%s\n", str); }; next(); return 1; };
88 }
89 
90 typedef void (^bptr)(void);
91 
92 bptr foo5(int j) {
93   __block int i;
94   if (j)
95     return ^{ ^{ i=0; }(); };  // expected-error {{returning block that lives on the local stack}}
96   return ^{ i=0; };  // expected-error {{returning block that lives on the local stack}}
97   return (^{ i=0; });  // expected-error {{returning block that lives on the local stack}}
98   return (void*)(^{ i=0; });  // expected-error {{returning block that lives on the local stack}}
99 }
100 
101 int (*funcptr3[5])(long);
102 int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block cannot return array type}} expected-error {{incompatible pointer to integer conversion}}
103 int sz9 = sizeof(^int(*())()[3]{ }); // expected-error {{function cannot return array type}}
104                                      // expected-warning@-1 {{a function declaration without a prototype is deprecated in all versions of C}}
105 
106 void foo6(void) {
107   int (^b)(int) __attribute__((noreturn));
108   b = ^ (int i) __attribute__((noreturn)) { return 1; };  // expected-error {{block declared 'noreturn' should not return}}
109   b(1);
110   int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}}
111 }
112 
113 
114 void foo7(void)
115 {
116  const int (^BB) (void) = ^{ const int i = 1; return i; }; // OK - initializing 'const int (^)(void)' with an expression of type 'int (^)(void)'
117 
118  const int (^CC) (void)  = ^const int{ const int i = 1; return i; };
119 
120 
121   int i;
122   int (^FF) (void)  = ^{ return i; }; // OK
123   int (^EE) (void)  = ^{ return i+1; }; // OK
124 
125   __block int j;
126   int (^JJ) (void)  = ^{ return j; }; // OK
127   int (^KK) (void)  = ^{ return j+1; }; // OK
128 
129   __block const int k;
130   const int cint = 100;
131 
132   int (^MM) (void)  = ^{ return k; };
133   int (^NN) (void)  = ^{ return cint; };
134 }
135 
136 void (^blk)(void) = ^{
137     return (void)0; // expected-warning {{void block literal should not return void expression}}
138 };
139 
140 enum Test8 { T8_a, T8_b, T8_c };
141 void test8(void) {
142   extern void test8_helper(int (^)(int));
143   test8_helper(^(int flag) { if (flag) return T8_a; return T8_b; });
144 }
145 void test8b(void) {
146   extern void test8_helper2(char (^)(int)); // expected-note {{here}}
147   test8_helper2(^(int flag) { if (flag) return T8_a; return T8_b; }); // expected-error {{passing 'enum Test8 (^)(int)' to parameter of type 'char (^)(int)'}}
148 }
149