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