xref: /llvm-project/clang/test/SemaObjC/blocks.m (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -fblocks -Wno-strict-prototypes %s
2
3#define bool _Bool
4@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)) {
23    return bar4(objectCreationBlock);
24}
25
26void bar5(id(^)(void)); // expected-note 3{{passing argument to parameter here}}
27void foo5(id (^objectCreationBlock)(bool)) {
28    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)'}}
33}
34
35void bar6(id(^)(int));
36void foo6(id (^objectCreationBlock)()) {
37    return bar6(objectCreationBlock);
38}
39
40void foo7(id (^x)(int)) {
41  if (x) { }
42}
43
44@interface itf
45@end
46
47void foo8() {
48  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'}}
52}
53
54
55int foo9() {
56  typedef void (^DVTOperationGroupScheduler)();
57  id _suboperationSchedulers;
58
59  for (DVTOperationGroupScheduler scheduler in _suboperationSchedulers) {
60            ;
61        }
62
63}
64
65@class NSString;
66
67extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
68
69void foo10() {
70    void(^myBlock)(void) = ^{
71    };
72    NSLog(@"%@", myBlock);
73}
74
75
76// In C, enum constants have the type of the underlying integer type, not the
77// enumeration they are part of. We pretend the constants have enum type if
78// all the returns seem to be playing along.
79enum CStyleEnum {
80  CSE_Value = 1,
81  CSE_Value2 = 2
82};
83enum CStyleEnum getCSE();
84typedef enum CStyleEnum (^cse_block_t)();
85
86void testCStyleEnumInference(bool arg) {
87  cse_block_t a;
88  enum CStyleEnum value;
89
90  // No warnings here.
91  a = ^{ return getCSE(); };
92  a = ^{ return value; };
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 warning here.
99  a = ^{
100    return CSE_Value;
101  };
102
103  // No warnings here.
104  a = ^{ if (arg) return CSE_Value; else return getCSE();  };
105  a = ^{ if (arg) return getCSE();  else return CSE_Value; };
106  a = ^{ if (arg) return value;     else return CSE_Value; };
107
108  // These two blocks actually return 'int'
109  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
110    if (arg)
111      return 1;
112    else
113      return CSE_Value;
114  };
115
116  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
117    if (arg)
118      return CSE_Value;
119    else
120      return 1;
121  };
122
123  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
124    if (arg)
125      return 1;
126    else
127      return value; // expected-error {{return type 'enum CStyleEnum' must match previous return type 'int'}}
128  };
129
130  extern void check_enum(void);
131  a = ^{
132    return (arg ? (CSE_Value) : (check_enum(), (!arg ? CSE_Value2 : getCSE())));
133  };
134  a = ^{
135    return (arg ? (CSE_Value) : ({check_enum(); CSE_Value2; }));
136  };
137}
138
139
140enum FixedTypeEnum : unsigned {
141  FTE_Value = 1U
142};
143enum FixedTypeEnum getFTE();
144typedef enum FixedTypeEnum (^fte_block_t)();
145
146void testFixedTypeEnumInference(bool arg) {
147  fte_block_t a;
148
149  // No warnings here.
150  a = ^{ return getFTE(); };
151
152  // Since we fixed the underlying type of the enum, this is considered a
153  // compatible block type.
154  a = ^{
155    return 1U;
156  };
157  a = ^{
158    return FTE_Value;
159  };
160
161  // No warnings here.
162  a = ^{ if (arg) return FTE_Value; else return FTE_Value; };
163  a = ^{ if (arg) return getFTE();  else return getFTE();  };
164  a = ^{ if (arg) return FTE_Value; else return getFTE();  };
165  a = ^{ if (arg) return getFTE();  else return FTE_Value; };
166
167  // These two blocks actually return 'unsigned'.
168  a = ^{
169    if (arg)
170      return 1U;
171    else
172      return FTE_Value;
173  };
174
175  a = ^{
176    if (arg)
177      return FTE_Value;
178    else
179      return 1U;
180  };
181}
182
183
184enum {
185  AnonymousValue = 1
186};
187
188enum : short {
189  FixedAnonymousValue = 1
190};
191
192typedef enum {
193  TDE_Value
194} TypeDefEnum;
195TypeDefEnum getTDE();
196
197typedef enum : short {
198  TDFTE_Value
199} TypeDefFixedTypeEnum;
200TypeDefFixedTypeEnum getTDFTE();
201
202typedef int (^int_block_t)();
203typedef short (^short_block_t)();
204void testAnonymousEnumTypes(int arg) {
205  int_block_t IB;
206  IB = ^{ return AnonymousValue; };
207  IB = ^{ if (arg) return TDE_Value; else return getTDE(); };
208  IB = ^{ if (arg) return getTDE(); else return TDE_Value; };
209
210  // Since we fixed the underlying type of the enum, these are considered
211  // compatible block types anyway.
212  short_block_t SB;
213  SB = ^{ return FixedAnonymousValue; };
214  SB = ^{ if (arg) return TDFTE_Value; else return getTDFTE(); };
215  SB = ^{ if (arg) return getTDFTE(); else return TDFTE_Value; };
216}
217
218static inline void inlinefunc() {
219  ^{}();
220}
221void inlinefunccaller() { inlinefunc(); }
222