blob: a6a6a3b36843cbdb0d4cb510808869dc2f625e2e [file] [log] [blame]
Daniel Dunbara5728872009-12-15 20:14:24 +00001// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
Douglas Gregor30c42402011-09-27 22:38:19 +00002
3#define bool _Bool
Steve Naroffc0febd52008-12-10 17:49:55 +00004@protocol NSObject;
5
6void bar(id(^)(void));
7void foo(id <NSObject>(^objectCreationBlock)(void)) {
8 return bar(objectCreationBlock);
9}
10
11void bar2(id(*)(void));
12void foo2(id <NSObject>(*objectCreationBlock)(void)) {
13 return bar2(objectCreationBlock);
14}
15
16void bar3(id(*)());
17void foo3(id (*objectCreationBlock)(int)) {
18 return bar3(objectCreationBlock);
19}
20
21void bar4(id(^)());
22void foo4(id (^objectCreationBlock)(int)) {
Mike Stumpaab0f7a2009-04-01 01:17:39 +000023 return bar4(objectCreationBlock);
Steve Naroffc0febd52008-12-10 17:49:55 +000024}
Douglas Gregor2a7e58d2008-12-23 00:53:59 +000025
Douglas Gregor8987b232011-09-27 23:30:47 +000026void bar5(id(^)(void)); // expected-note 3{{passing argument to parameter here}}
Douglas Gregor30c42402011-09-27 22:38:19 +000027void foo5(id (^objectCreationBlock)(bool)) {
Douglas Gregor8987b232011-09-27 23:30:47 +000028 bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(bool)' to parameter of type 'id (^)(void)'}}
29#undef bool
30 bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}}
31#define bool int
32 bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}}
Mike Stumpaab0f7a2009-04-01 01:17:39 +000033}
34
35void bar6(id(^)(int));
36void foo6(id (^objectCreationBlock)()) {
Eli Friedman687abff2009-06-08 04:24:21 +000037 return bar6(objectCreationBlock);
Mike Stumpaab0f7a2009-04-01 01:17:39 +000038}
39
Chris Lattnerbb749822009-04-11 19:17:25 +000040void foo7(id (^x)(int)) {
Douglas Gregor2a7e58d2008-12-23 00:53:59 +000041 if (x) { }
42}
Chris Lattnerbb749822009-04-11 19:17:25 +000043
44@interface itf
45@end
46
47void foo8() {
Richard Trieu2fe9b7f2011-12-15 00:38:15 +000048 void *P = ^(itf x) {}; // expected-error {{interface type 'itf' cannot be passed by value; did you forget * in 'itf'}}
49 P = ^itf(int x) {}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
50 P = ^itf() {}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
51 P = ^itf{}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
Chris Lattnerbb749822009-04-11 19:17:25 +000052}
Fariborz Jahaniana5e42a82009-08-14 21:53:27 +000053
54
55int foo9() {
56 typedef void (^DVTOperationGroupScheduler)();
57 id _suboperationSchedulers;
58
59 for (DVTOperationGroupScheduler scheduler in _suboperationSchedulers) {
60 ;
61 }
62
63}
Fariborz Jahanian2263f822010-03-09 18:34:52 +000064
65// rdar 7725203
66@class NSString;
67
68extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
69
70void foo10() {
71 void(^myBlock)(void) = ^{
72 };
73 NSLog(@"%@", myBlock);
74}
75
Jordan Rose81a56412012-06-21 05:54:55 +000076
77// In C, enum constants have the type of the underlying integer type, not the
78// enumeration they are part of. We pretend the constants have enum type when
79// inferring block return types, so that they can be mixed-and-matched with
80// other expressions of enum type.
81enum CStyleEnum {
82 CSE_Value = 1
83};
84enum CStyleEnum getCSE();
85typedef enum CStyleEnum (^cse_block_t)();
86
87void testCStyleEnumInference(bool arg) {
88 cse_block_t a;
89
90 // No warnings here.
91 a = ^{ return CSE_Value; };
92 a = ^{ return getCSE(); };
93
94 a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
95 return 1;
96 };
97
98 // No warnings here.
99 a = ^{ if (arg) return CSE_Value; else return CSE_Value; };
100 a = ^{ if (arg) return getCSE(); else return getCSE(); };
101 a = ^{ if (arg) return CSE_Value; else return getCSE(); };
102 a = ^{ if (arg) return getCSE(); else return CSE_Value; };
103
104 // Technically these two blocks should return 'int'.
105 // The first case is easy to handle -- just don't cast the enum constant
106 // to the enum type. However, the second guess would require going back
107 // and REMOVING the cast from the first return statement, which isn't really
108 // feasible (there may be more than one previous return statement with enum
109 // type). For symmetry, we just treat them the same way.
110 a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
111 if (arg)
112 return 1;
113 else
114 return CSE_Value; // expected-error {{return type 'enum CStyleEnum' must match previous return type 'int'}}
115 };
116
117 a = ^{
118 if (arg)
119 return CSE_Value;
120 else
121 return 1; // expected-error {{return type 'int' must match previous return type 'enum CStyleEnum'}}
122 };
123}
124
125
126enum FixedTypeEnum : unsigned {
127 FTE_Value = 1U
128};
129enum FixedTypeEnum getFTE();
130typedef enum FixedTypeEnum (^fte_block_t)();
131
132void testFixedTypeEnumInference(bool arg) {
133 fte_block_t a;
134
135 // No warnings here.
136 a = ^{ return FTE_Value; };
137 a = ^{ return getFTE(); };
138
139 // Since we fixed the underlying type of the enum, this is considered a
140 // compatible block type.
141 a = ^{
142 return 1U;
143 };
144
145 // No warnings here.
146 a = ^{ if (arg) return FTE_Value; else return FTE_Value; };
147 a = ^{ if (arg) return getFTE(); else return getFTE(); };
148 a = ^{ if (arg) return FTE_Value; else return getFTE(); };
149 a = ^{ if (arg) return getFTE(); else return FTE_Value; };
150
151 // Technically these two blocks should return 'unsigned'.
152 // The first case is easy to handle -- just don't cast the enum constant
153 // to the enum type. However, the second guess would require going back
154 // and REMOVING the cast from the first return statement, which isn't really
155 // feasible (there may be more than one previous return statement with enum
156 // type). For symmetry, we just treat them the same way.
157 a = ^{
158 if (arg)
159 return 1U;
160 else
161 return FTE_Value; // expected-error{{return type 'enum FixedTypeEnum' must match previous return type 'unsigned int'}}
162 };
163
164 a = ^{
165 if (arg)
166 return FTE_Value;
167 else
168 return 1U; // expected-error{{return type 'unsigned int' must match previous return type 'enum FixedTypeEnum'}}
169 };
170}
171
172
173enum {
174 AnonymousValue = 1
175};
176
177enum : short {
178 FixedAnonymousValue = 1
179};
180
181typedef enum {
182 TDE_Value
183} TypeDefEnum;
184
185typedef enum : short {
186 TDFTE_Value
187} TypeDefFixedTypeEnum;
188
189
190typedef int (^int_block_t)();
191typedef short (^short_block_t)();
192void testAnonymousEnumTypes() {
193 int_block_t IB;
194 IB = ^{ return AnonymousValue; };
195 IB = ^{ return TDE_Value; }; // expected-error {{incompatible block pointer types assigning to 'int_block_t' (aka 'int (^)()') from 'TypeDefEnum (^)(void)'}}
196 IB = ^{ return CSE_Value; }; // expected-error {{incompatible block pointer types assigning to 'int_block_t' (aka 'int (^)()') from 'enum CStyleEnum (^)(void)'}}
197
198 short_block_t SB;
199 SB = ^{ return FixedAnonymousValue; };
200 // This is not an error anyway since the enum has a fixed underlying type.
201 SB = ^{ return TDFTE_Value; };
202}