1 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s
2 // test for block type safety.
5 @interface Sub : Super @end
7 void f2(void(^f)(Super *)) { // expected-note{{passing argument to parameter 'f' here}}
12 void f3(void(^f)(Sub *)) {
17 void r0(Super* (^f)()) {
21 void r1(Sub* (^f)()) { // expected-note{{passing argument to parameter 'f' here}}
28 void r2 (id<NSObject> (^f) (void)) {
33 f2(^(Sub *o) { }); // expected-error {{incompatible block pointer types passing}}
34 f3(^(Super *o) { }); // OK, block taking Super* may be called with a Sub*
36 r0(^Super* () { return 0; }); // OK
37 r0(^Sub* () { return 0; }); // OK, variable of type Super* gets return value of type Sub*
38 r0(^id () { return 0; });
40 r1(^Super* () { return 0; }); // expected-error {{incompatible block pointer types passing}}
41 r1(^Sub* () { return 0; }); // OK
42 r1(^id () { return 0; });
44 r2(^id<NSObject>() { return 0; });
51 void f0(void (^f)(A* x)) {
56 void f1(void (^f)(id x)) {
63 f0(^(id a) { }); // OK
65 f1(^(id<NSObject> a) { }); // OK
69 // Calls block() with every object in the array
70 -enumerateObjectsWithBlock:(void (^)(id obj))block;
77 @implementation MyThing
78 static NSArray* myThings; // array of MyThing*
80 -(void) printThing { }
82 // programmer wants to write this:
84 [myThings enumerateObjectsWithBlock: ^(MyThing *obj) {
89 // strict type safety requires this:
91 [myThings enumerateObjectsWithBlock: ^(id obj) {
92 MyThing *obj2 = (MyThing *)obj;
99 void f4(void (^f)(id<P> x)) { // expected-note{{passing argument to parameter 'f' here}}
101 f(b); // expected-warning {{passing 'NSArray<P2> *' to parameter of incompatible type 'id<P>'}}
105 f4(^(NSArray<P2>* a) { }); // expected-error {{incompatible block pointer types passing 'void (^)(NSArray<P2> *)' to parameter of type 'void (^)(id<P>)'}}
113 @interface Baz(FooConformance) <Foo>
116 @implementation Baz @end
119 id <Foo> (^b)() = ^{ // Doesn't work
127 @protocol NSCopying @end
129 @interface NSAllArray <NSCopying>
132 @interface NSAllArray (FooConformance) <Foo>
136 // Returned value is used outside of a block, so error on changing
137 // a return type to a more general than expected.
138 NSAllArray *(^block)(id);
139 id <Foo> (^genericBlock)(id);
140 genericBlock = block;
141 block = genericBlock; // expected-error {{incompatible block pointer types assigning to 'NSAllArray *(^)(id)' from 'id<Foo> (^)(id)'}}
143 // A parameter is used inside a block, so error on changing a parameter type
144 // to a more specific than an argument type it will be called with.
145 // rdar://problem/52788423
146 void (^blockWithParam)(NSAllArray *);
147 void (^genericBlockWithParam)(id<Foo>);
148 genericBlockWithParam = blockWithParam; // expected-error {{incompatible block pointer types assigning to 'void (^)(id<Foo>)' from 'void (^)(NSAllArray *)'}}
149 blockWithParam = genericBlockWithParam;
154 typedef int NSInteger;
156 typedef enum : NSInteger {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending} NSComparisonResult;
158 typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
160 @interface radar10798770
161 - (void)sortUsingComparator:(NSComparator)c;
166 [f sortUsingComparator:^(id a, id b) {
167 return NSOrderedSame;
177 id anId = aBlock; // OK
179 id<P1,P2> anQualId = aBlock; // expected-error {{initializing 'id<P1,P2>' with an expression of incompatible type 'void (^)()'}}
181 NSArray* anArray = aBlock; // expected-error {{initializing 'NSArray *' with an expression of incompatible type 'void (^)()'}}
186 aBlock = anQualId1; // expected-error {{assigning to 'void (^)()' from incompatible type 'id<P1,P2>'}}
189 aBlock = anArray1; // expected-error {{assigning to 'void (^)()' from incompatible type 'NSArray *'}}
194 id<NSObject> anQualId1 = aBlock; // Ok
195 id<NSObject, NSCopying> anQualId2 = aBlock; // Ok
196 id<NSObject, NSCopying, NSObject, NSCopying> anQualId3 = aBlock; // Ok
197 id <P1> anQualId4 = aBlock; // expected-error {{initializing 'id<P1>' with an expression of incompatible type 'void (^)()'}}
198 id<NSObject, P1, NSCopying> anQualId5 = aBlock; // expected-error {{initializing 'id<NSObject,P1,NSCopying>' with an expression of incompatible type 'void (^)()'}}
199 id<NSCopying> anQualId6 = aBlock; // Ok
204 NSObject *NSO = aBlock; // Ok
205 NSObject<NSObject> *NSO1 = aBlock; // Ok
206 NSObject<NSObject, NSCopying> *NSO2 = aBlock; // Ok
207 NSObject<NSObject, NSCopying, NSObject, NSCopying> *NSO3 = aBlock; // Ok
208 NSObject <P1> *NSO4 = aBlock; // expected-error {{initializing 'NSObject<P1> *' with an expression of incompatible type 'void (^)()'}}
209 NSObject<NSObject, P1, NSCopying> *NSO5 = aBlock; // expected-error {{initializing 'NSObject<NSObject,P1,NSCopying> *' with an expression of incompatible type 'void (^)()'}}
210 NSObject<NSCopying> *NSO6 = aBlock; // Ok
213 // rdar://problem/19420731
214 typedef NSObject<P1> NSObject_P1;
215 typedef NSObject_P1<P2> NSObject_P1_P2;
217 void Test4(void (^handler)(NSObject_P1_P2 *p)) {
218 Test4(^(NSObject<P2> *p) { });