1// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -fblocks %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// 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
76
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 if
79// all the returns seem to be playing along.
80enum CStyleEnum {
81  CSE_Value = 1,
82  CSE_Value2 = 2
83};
84enum CStyleEnum getCSE();
85typedef enum CStyleEnum (^cse_block_t)();
86
87void testCStyleEnumInference(bool arg) {
88  cse_block_t a;
89  enum CStyleEnum value;
90
91  // No warnings here.
92  a = ^{ return getCSE(); };
93  a = ^{ return value; };
94
95  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
96    return 1;
97  };
98
99  // No warning here.
100  a = ^{
101    return CSE_Value;
102  };
103
104  // No warnings here.
105  a = ^{ if (arg) return CSE_Value; else return getCSE();  };
106  a = ^{ if (arg) return getCSE();  else return CSE_Value; };
107  a = ^{ if (arg) return value;     else return CSE_Value; };
108
109  // These two blocks actually return 'int'
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;
115  };
116
117  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
118    if (arg)
119      return CSE_Value;
120    else
121      return 1;
122  };
123
124  a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
125    if (arg)
126      return 1;
127    else
128      return value; // expected-error {{return type 'enum CStyleEnum' must match previous return type 'int'}}
129  };
130
131  // rdar://13200889
132  extern void check_enum(void);
133  a = ^{
134    return (arg ? (CSE_Value) : (check_enum(), (!arg ? CSE_Value2 : getCSE())));
135  };
136  a = ^{
137    return (arg ? (CSE_Value) : ({check_enum(); CSE_Value2; }));
138  };
139}
140
141
142enum FixedTypeEnum : unsigned {
143  FTE_Value = 1U
144};
145enum FixedTypeEnum getFTE();
146typedef enum FixedTypeEnum (^fte_block_t)();
147
148void testFixedTypeEnumInference(bool arg) {
149  fte_block_t a;
150
151  // No warnings here.
152  a = ^{ return getFTE(); };
153
154  // Since we fixed the underlying type of the enum, this is considered a
155  // compatible block type.
156  a = ^{
157    return 1U;
158  };
159  a = ^{
160    return FTE_Value;
161  };
162
163  // No warnings here.
164  a = ^{ if (arg) return FTE_Value; else return FTE_Value; };
165  a = ^{ if (arg) return getFTE();  else return getFTE();  };
166  a = ^{ if (arg) return FTE_Value; else return getFTE();  };
167  a = ^{ if (arg) return getFTE();  else return FTE_Value; };
168
169  // These two blocks actually return 'unsigned'.
170  a = ^{
171    if (arg)
172      return 1U;
173    else
174      return FTE_Value;
175  };
176
177  a = ^{
178    if (arg)
179      return FTE_Value;
180    else
181      return 1U;
182  };
183}
184
185
186enum {
187  AnonymousValue = 1
188};
189
190enum : short {
191  FixedAnonymousValue = 1
192};
193
194typedef enum {
195  TDE_Value
196} TypeDefEnum;
197TypeDefEnum getTDE();
198
199typedef enum : short {
200  TDFTE_Value
201} TypeDefFixedTypeEnum;
202TypeDefFixedTypeEnum getTDFTE();
203
204typedef int (^int_block_t)();
205typedef short (^short_block_t)();
206void testAnonymousEnumTypes(int arg) {
207  int_block_t IB;
208  IB = ^{ return AnonymousValue; };
209  IB = ^{ if (arg) return TDE_Value; else return getTDE(); };
210  IB = ^{ if (arg) return getTDE(); else return TDE_Value; };
211
212  // Since we fixed the underlying type of the enum, these are considered
213  // compatible block types anyway.
214  short_block_t SB;
215  SB = ^{ return FixedAnonymousValue; };
216  SB = ^{ if (arg) return TDFTE_Value; else return getTDFTE(); };
217  SB = ^{ if (arg) return getTDFTE(); else return TDFTE_Value; };
218}
219
220static inline void inlinefunc() {
221  ^{}();
222}
223void inlinefunccaller() { inlinefunc(); }
224