@@ -73,3 +73,130 @@ void foo10() {
73
73
NSLog (@" %@ " , myBlock);
74
74
}
75
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 when
79
+ // inferring block return types, so that they can be mixed-and-matched with
80
+ // other expressions of enum type.
81
+ enum CStyleEnum {
82
+ CSE_Value = 1
83
+ };
84
+ enum CStyleEnum getCSE ();
85
+ typedef enum CStyleEnum (^cse_block_t )();
86
+
87
+ void 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
+
126
+ enum FixedTypeEnum : unsigned {
127
+ FTE_Value = 1U
128
+ };
129
+ enum FixedTypeEnum getFTE ();
130
+ typedef enum FixedTypeEnum (^fte_block_t )();
131
+
132
+ void 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
+
173
+ enum {
174
+ AnonymousValue = 1
175
+ };
176
+
177
+ enum : short {
178
+ FixedAnonymousValue = 1
179
+ };
180
+
181
+ typedef enum {
182
+ TDE_Value
183
+ } TypeDefEnum;
184
+
185
+ typedef enum : short {
186
+ TDFTE_Value
187
+ } TypeDefFixedTypeEnum;
188
+
189
+
190
+ typedef int (^int_block_t )();
191
+ typedef short (^short_block_t )();
192
+ void 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
+ }
0 commit comments