1 // RUN: %clang_cc1 -fsyntax-only -fblocks -Woverriding-method-mismatch -Wno-nullability-declspec %s -verify 2 3 __attribute__((objc_root_class)) 4 @interface NSFoo 5 - (void)methodTakingIntPtr:(_Nonnull int *)ptr; 6 - (_Nonnull int *)methodReturningIntPtr; 7 @end 8 9 // Nullability applies to all pointer types. 10 typedef NSFoo * _Nonnull nonnull_NSFoo_ptr; 11 typedef id _Nonnull nonnull_id; 12 typedef SEL _Nonnull nonnull_SEL; 13 14 // Nullability can move into Objective-C pointer types. 15 typedef _Nonnull NSFoo * nonnull_NSFoo_ptr_2; 16 17 // Conflicts from nullability moving into Objective-C pointer type. 18 typedef _Nonnull NSFoo * _Nullable conflict_NSFoo_ptr_2; // expected-error{{'_Nonnull' cannot be applied to non-pointer type 'NSFoo'}} 19 20 void testBlocksPrinting(NSFoo * _Nullable (^bp)(int)) { 21 int *ip = bp; // expected-error{{'NSFoo * _Nullable (^)(int)'}} 22 } 23 24 // Check returning nil from a _Nonnull-returning method. 25 @implementation NSFoo 26 - (void)methodTakingIntPtr:(_Nonnull int *)ptr { } 27 - (_Nonnull int *)methodReturningIntPtr { 28 return 0; // no warning 29 } 30 @end 31 32 // Context-sensitive keywords and property attributes for nullability. 33 __attribute__((objc_root_class)) 34 @interface NSBar 35 - (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo; 36 37 - (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}} 38 // expected-note@-1{{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'NSFoo **'}} 39 - (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}} 40 - (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '_Nonnull'}} 41 42 @property(nonnull,retain) NSFoo *property1; 43 @property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}} 44 // expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}} 45 @property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}} 46 @property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '_Nonnull'}} 47 48 @property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}} 49 @property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}} 50 @end 51 52 @interface NSBar () 53 @property(nonnull,retain) NSFoo *property2; 54 @property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}} 55 // expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}} 56 @property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}} 57 @property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '_Nonnull'}} 58 @end 59 60 void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, _Nonnull NSBar *bar) { 61 [foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} 62 [bar methodWithFoo: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} 63 bar.property1 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} 64 bar.property2 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} 65 [bar setProperty1: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} 66 [bar setProperty2: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} 67 int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}} 68 } 69 70 // Check returning nil from a nonnull-returning method. 71 @implementation NSBar 72 - (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo { 73 return 0; // no warning 74 } 75 76 - (NSFoo **)invalidMethod1 { 77 return 0; 78 } 79 80 - (NSFoo *)conflictingMethod1 { 81 return 0; // no warning 82 } 83 - (NSFoo *)redundantMethod1 { 84 int *ip = 0; 85 return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} 86 } 87 @end 88 89 __attribute__((objc_root_class)) 90 @interface NSMerge 91 - (nonnull NSFoo *)methodA:(nonnull NSFoo*)foo; 92 - (nonnull NSFoo *)methodB:(nonnull NSFoo*)foo; 93 - (NSFoo *)methodC:(NSFoo*)foo; 94 @end 95 96 @implementation NSMerge 97 - (NSFoo *)methodA:(NSFoo*)foo { 98 int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}} 99 return ptr; // expected-warning{{result type 'NSFoo * _Nonnull'}} 100 } 101 102 - (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \ 103 // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier 'nonnull'}} 104 return 0; 105 } 106 107 - (nonnull NSFoo *)methodC:(nullable NSFoo*)foo { 108 int *ip = 0; 109 return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}} 110 } 111 @end 112 113 // Checking merging of nullability when sending a message. 114 @interface NSMergeReceiver 115 - (id)returnsNone; 116 - (nonnull id)returnsNonNull; 117 - (nullable id)returnsNullable; 118 - (null_unspecified id)returnsNullUnspecified; 119 @end 120 121 void test_receiver_merge(NSMergeReceiver *none, 122 _Nonnull NSMergeReceiver *nonnull, 123 _Nullable NSMergeReceiver *nullable, 124 _Null_unspecified NSMergeReceiver *null_unspecified) { 125 int *ptr; 126 127 ptr = [nullable returnsNullable]; // expected-warning{{'id _Nullable'}} 128 ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id _Nullable'}} 129 ptr = [nullable returnsNonNull]; // expected-warning{{'id _Nullable'}} 130 ptr = [nullable returnsNone]; // expected-warning{{'id _Nullable'}} 131 132 ptr = [null_unspecified returnsNullable]; // expected-warning{{'id _Nullable'}} 133 ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}} 134 ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id _Null_unspecified'}} 135 ptr = [null_unspecified returnsNone]; // expected-warning{{'id'}} 136 137 ptr = [nonnull returnsNullable]; // expected-warning{{'id _Nullable'}} 138 ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}} 139 ptr = [nonnull returnsNonNull]; // expected-warning{{'id _Nonnull'}} 140 ptr = [nonnull returnsNone]; // expected-warning{{'id'}} 141 142 ptr = [none returnsNullable]; // expected-warning{{'id _Nullable'}} 143 ptr = [none returnsNullUnspecified]; // expected-warning{{'id'}} 144 ptr = [none returnsNonNull]; // expected-warning{{'id'}} 145 ptr = [none returnsNone]; // expected-warning{{'id'}} 146 147 } 148 149 // instancetype 150 @protocol Initializable 151 - (instancetype)initWithBlah:(id)blah; 152 @end 153 154 __attribute__((objc_root_class)) 155 @interface InitializableClass <Initializable> 156 - (nonnull instancetype)initWithBlah:(nonnull id)blah; 157 - (nullable instancetype)returnMe; 158 + (nullable instancetype)returnInstanceOfMe; 159 160 - (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}} 161 - (instancetype _Nullable)returnMe2; 162 + (_Nonnull instancetype)returnInstanceOfMe2; 163 @end 164 165 void test_instancetype(InitializableClass * _Nonnull ic, id _Nonnull object) { 166 int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * _Nullable'}} 167 ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}} 168 ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}} 169 ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}} 170 171 ip = [ic returnMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}} 172 ip = [InitializableClass returnInstanceOfMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nonnull'}} 173 } 174 175 // Check null_resettable getters/setters. 176 __attribute__((objc_root_class)) 177 @interface NSResettable 178 @property(null_resettable,retain) NSResettable *resettable1; // expected-note{{passing argument to parameter 'resettable1' here}} 179 @property(null_resettable,retain,nonatomic) NSResettable *resettable2; 180 @property(null_resettable,retain,nonatomic) NSResettable *resettable3; 181 @property(null_resettable,retain,nonatomic) NSResettable *resettable4; 182 @property(null_resettable,retain,nonatomic) NSResettable *resettable5; 183 @property(null_resettable,retain,nonatomic) NSResettable *resettable6; 184 @end 185 186 void test_null_resettable(NSResettable *r, int *ip) { 187 [r setResettable1:ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'NSResettable * _Nullable'}} 188 r.resettable1 = ip; // expected-warning{{incompatible pointer types assigning to 'NSResettable * _Nullable' from 'int *'}} 189 } 190 191 @implementation NSResettable // expected-warning{{synthesized setter 'setResettable4:' for null_resettable property 'resettable4' does not handle nil}} 192 - (NSResettable *)resettable1 { 193 int *ip = 0; 194 return ip; // expected-warning{{result type 'NSResettable * _Nonnull'}} 195 } 196 197 - (void)setResettable1:(NSResettable *)param { 198 } 199 200 @synthesize resettable2; // no warning; not synthesized 201 @synthesize resettable3; // expected-warning{{synthesized setter 'setResettable3:' for null_resettable property 'resettable3' does not handle nil}} 202 203 - (void)setResettable2:(NSResettable *)param { 204 } 205 206 @dynamic resettable5; 207 208 - (NSResettable *)resettable6 { 209 return 0; // no warning 210 } 211 @end 212 213 // rdar://problem/19814852 214 @interface MultiProp 215 @property (nullable, copy) id a, b, c; 216 @property (nullable, copy) MultiProp *d, *(^e)(int); 217 @end 218 219 void testMultiProp(MultiProp *foo) { 220 int *ip; 221 ip = foo.a; // expected-warning{{from 'id _Nullable'}} 222 ip = foo.d; // expected-warning{{from 'MultiProp * _Nullable'}} 223 ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ _Nullable)(int)'}} 224 } 225 226 void testBlockLiterals() { 227 (void)(^id(void) { return 0; }); 228 (void)(^id _Nullable (void) { return 0; }); 229 (void)(^ _Nullable id(void) { return 0; }); 230 231 int *x = (^ _Nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id _Nullable'}} 232 } 233