2016-07-26 05:58:19 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -fblocks -Woverriding-method-mismatch -Wno-nullability-declspec -Wnullable-to-nonnull-conversion %s -verify
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
|
2015-06-20 02:13:19 +08:00
|
|
|
__attribute__((objc_root_class))
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
@interface NSFoo
|
2015-06-25 06:02:08 +08:00
|
|
|
- (void)methodTakingIntPtr:(_Nonnull int *)ptr;
|
|
|
|
- (_Nonnull int *)methodReturningIntPtr;
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
@end
|
|
|
|
|
|
|
|
// Nullability applies to all pointer types.
|
2015-06-25 06:02:08 +08:00
|
|
|
typedef NSFoo * _Nonnull nonnull_NSFoo_ptr;
|
|
|
|
typedef id _Nonnull nonnull_id;
|
|
|
|
typedef SEL _Nonnull nonnull_SEL;
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
|
|
|
|
// Nullability can move into Objective-C pointer types.
|
2015-06-25 06:02:08 +08:00
|
|
|
typedef _Nonnull NSFoo * nonnull_NSFoo_ptr_2;
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
|
|
|
|
// Conflicts from nullability moving into Objective-C pointer type.
|
2015-06-25 06:02:08 +08:00
|
|
|
typedef _Nonnull NSFoo * _Nullable conflict_NSFoo_ptr_2; // expected-error{{'_Nonnull' cannot be applied to non-pointer type 'NSFoo'}}
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
void testBlocksPrinting(NSFoo * _Nullable (^bp)(int)) {
|
|
|
|
int *ip = bp; // expected-error{{'NSFoo * _Nullable (^)(int)'}}
|
Introduce type nullability specifiers for C/C++.
Introduces the type specifiers __nonnull, __nullable, and
__null_unspecified that describe the nullability of the pointer type
to which the specifier appertains. Nullability type specifiers improve
on the existing nonnull attributes in a few ways:
- They apply to types, so one can represent a pointer to a non-null
pointer, use them in function pointer types, etc.
- As type specifiers, they are syntactically more lightweight than
__attribute__s or [[attribute]]s.
- They can express both the notion of 'should never be null' and
also 'it makes sense for this to be null', and therefore can more
easily catch errors of omission where one forgot to annotate the
nullability of a particular pointer (this will come in a subsequent
patch).
Nullability type specifiers are maintained as type sugar, and
therefore have no effect on mangling, encoding, overloading,
etc. Nonetheless, they will be used for warnings about, e.g., passing
'null' to a method that does not accept it.
This is the C/C++ part of rdar://problem/18868820.
llvm-svn: 240146
2015-06-20 01:51:05 +08:00
|
|
|
}
|
2015-06-20 02:13:19 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
// Check returning nil from a _Nonnull-returning method.
|
2015-06-20 02:13:19 +08:00
|
|
|
@implementation NSFoo
|
2015-06-25 06:02:08 +08:00
|
|
|
- (void)methodTakingIntPtr:(_Nonnull int *)ptr { }
|
|
|
|
- (_Nonnull int *)methodReturningIntPtr {
|
2015-06-20 02:13:19 +08:00
|
|
|
return 0; // no warning
|
|
|
|
}
|
|
|
|
@end
|
2015-06-20 02:14:38 +08:00
|
|
|
|
|
|
|
// Context-sensitive keywords and property attributes for nullability.
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface NSBar
|
|
|
|
- (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo;
|
|
|
|
|
|
|
|
- (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}}
|
2015-06-25 06:02:08 +08:00
|
|
|
// expected-note@-1{{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'NSFoo **'}}
|
|
|
|
- (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
|
|
|
|
- (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
|
|
|
|
@property(nonnull,retain) NSFoo *property1;
|
|
|
|
@property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
|
2015-06-25 06:02:08 +08:00
|
|
|
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
|
|
|
|
@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
|
|
|
|
@property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
|
|
|
|
@property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}}
|
|
|
|
@property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface NSBar ()
|
|
|
|
@property(nonnull,retain) NSFoo *property2;
|
|
|
|
@property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
|
2015-06-25 06:02:08 +08:00
|
|
|
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
|
|
|
|
@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
|
|
|
|
@property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
@end
|
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, _Nonnull NSBar *bar) {
|
2015-06-20 02:14:38 +08:00
|
|
|
[foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
|
|
|
[bar methodWithFoo: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
|
|
|
bar.property1 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
|
|
|
bar.property2 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
|
|
|
[bar setProperty1: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
|
|
|
[bar setProperty2: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
|
2015-06-25 06:02:08 +08:00
|
|
|
int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check returning nil from a nonnull-returning method.
|
|
|
|
@implementation NSBar
|
|
|
|
- (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo {
|
|
|
|
return 0; // no warning
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSFoo **)invalidMethod1 {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSFoo *)conflictingMethod1 {
|
|
|
|
return 0; // no warning
|
|
|
|
}
|
|
|
|
- (NSFoo *)redundantMethod1 {
|
|
|
|
int *ip = 0;
|
2015-06-25 06:02:08 +08:00
|
|
|
return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface NSMerge
|
|
|
|
- (nonnull NSFoo *)methodA:(nonnull NSFoo*)foo;
|
|
|
|
- (nonnull NSFoo *)methodB:(nonnull NSFoo*)foo;
|
|
|
|
- (NSFoo *)methodC:(NSFoo*)foo;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSMerge
|
|
|
|
- (NSFoo *)methodA:(NSFoo*)foo {
|
2015-06-25 06:02:08 +08:00
|
|
|
int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}}
|
|
|
|
return ptr; // expected-warning{{result type 'NSFoo * _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \
|
|
|
|
// expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier 'nonnull'}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (nonnull NSFoo *)methodC:(nullable NSFoo*)foo {
|
|
|
|
int *ip = 0;
|
2015-06-25 06:02:08 +08:00
|
|
|
return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
// Checking merging of nullability when sending a message.
|
|
|
|
@interface NSMergeReceiver
|
|
|
|
- (id)returnsNone;
|
|
|
|
- (nonnull id)returnsNonNull;
|
|
|
|
- (nullable id)returnsNullable;
|
|
|
|
- (null_unspecified id)returnsNullUnspecified;
|
|
|
|
@end
|
|
|
|
|
|
|
|
void test_receiver_merge(NSMergeReceiver *none,
|
2015-06-25 06:02:08 +08:00
|
|
|
_Nonnull NSMergeReceiver *nonnull,
|
|
|
|
_Nullable NSMergeReceiver *nullable,
|
|
|
|
_Null_unspecified NSMergeReceiver *null_unspecified) {
|
2015-06-20 02:14:38 +08:00
|
|
|
int *ptr;
|
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
ptr = [nullable returnsNullable]; // expected-warning{{'id _Nullable'}}
|
|
|
|
ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id _Nullable'}}
|
|
|
|
ptr = [nullable returnsNonNull]; // expected-warning{{'id _Nullable'}}
|
|
|
|
ptr = [nullable returnsNone]; // expected-warning{{'id _Nullable'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
ptr = [null_unspecified returnsNullable]; // expected-warning{{'id _Nullable'}}
|
|
|
|
ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}}
|
|
|
|
ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id _Null_unspecified'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
ptr = [null_unspecified returnsNone]; // expected-warning{{'id'}}
|
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
ptr = [nonnull returnsNullable]; // expected-warning{{'id _Nullable'}}
|
|
|
|
ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}}
|
|
|
|
ptr = [nonnull returnsNonNull]; // expected-warning{{'id _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
ptr = [nonnull returnsNone]; // expected-warning{{'id'}}
|
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
ptr = [none returnsNullable]; // expected-warning{{'id _Nullable'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
ptr = [none returnsNullUnspecified]; // expected-warning{{'id'}}
|
|
|
|
ptr = [none returnsNonNull]; // expected-warning{{'id'}}
|
|
|
|
ptr = [none returnsNone]; // expected-warning{{'id'}}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// instancetype
|
|
|
|
@protocol Initializable
|
|
|
|
- (instancetype)initWithBlah:(id)blah;
|
|
|
|
@end
|
|
|
|
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface InitializableClass <Initializable>
|
|
|
|
- (nonnull instancetype)initWithBlah:(nonnull id)blah;
|
|
|
|
- (nullable instancetype)returnMe;
|
|
|
|
+ (nullable instancetype)returnInstanceOfMe;
|
2015-06-20 07:18:00 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
- (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
|
|
|
|
- (instancetype _Nullable)returnMe2;
|
|
|
|
+ (_Nonnull instancetype)returnInstanceOfMe2;
|
2015-06-20 02:14:38 +08:00
|
|
|
@end
|
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
void test_instancetype(InitializableClass * _Nonnull ic, id _Nonnull object) {
|
|
|
|
int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * _Nullable'}}
|
|
|
|
ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}}
|
|
|
|
ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}}
|
|
|
|
ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}}
|
2015-06-20 07:18:00 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
ip = [ic returnMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}}
|
|
|
|
ip = [InitializableClass returnInstanceOfMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nonnull'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
2015-06-20 02:14:46 +08:00
|
|
|
|
|
|
|
// Check null_resettable getters/setters.
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface NSResettable
|
|
|
|
@property(null_resettable,retain) NSResettable *resettable1; // expected-note{{passing argument to parameter 'resettable1' here}}
|
|
|
|
@property(null_resettable,retain,nonatomic) NSResettable *resettable2;
|
|
|
|
@property(null_resettable,retain,nonatomic) NSResettable *resettable3;
|
|
|
|
@property(null_resettable,retain,nonatomic) NSResettable *resettable4;
|
|
|
|
@property(null_resettable,retain,nonatomic) NSResettable *resettable5;
|
|
|
|
@property(null_resettable,retain,nonatomic) NSResettable *resettable6;
|
|
|
|
@end
|
|
|
|
|
|
|
|
void test_null_resettable(NSResettable *r, int *ip) {
|
2015-06-25 06:02:08 +08:00
|
|
|
[r setResettable1:ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'NSResettable * _Nullable'}}
|
|
|
|
r.resettable1 = ip; // expected-warning{{incompatible pointer types assigning to 'NSResettable * _Nullable' from 'int *'}}
|
2015-06-20 02:14:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@implementation NSResettable // expected-warning{{synthesized setter 'setResettable4:' for null_resettable property 'resettable4' does not handle nil}}
|
|
|
|
- (NSResettable *)resettable1 {
|
|
|
|
int *ip = 0;
|
2015-06-25 06:02:08 +08:00
|
|
|
return ip; // expected-warning{{result type 'NSResettable * _Nonnull'}}
|
2015-06-20 02:14:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setResettable1:(NSResettable *)param {
|
|
|
|
}
|
|
|
|
|
|
|
|
@synthesize resettable2; // no warning; not synthesized
|
|
|
|
@synthesize resettable3; // expected-warning{{synthesized setter 'setResettable3:' for null_resettable property 'resettable3' does not handle nil}}
|
|
|
|
|
|
|
|
- (void)setResettable2:(NSResettable *)param {
|
|
|
|
}
|
|
|
|
|
|
|
|
@dynamic resettable5;
|
|
|
|
|
|
|
|
- (NSResettable *)resettable6 {
|
|
|
|
return 0; // no warning
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
// rdar://problem/19814852
|
|
|
|
@interface MultiProp
|
|
|
|
@property (nullable, copy) id a, b, c;
|
|
|
|
@property (nullable, copy) MultiProp *d, *(^e)(int);
|
|
|
|
@end
|
|
|
|
|
|
|
|
void testMultiProp(MultiProp *foo) {
|
|
|
|
int *ip;
|
2015-06-25 06:02:08 +08:00
|
|
|
ip = foo.a; // expected-warning{{from 'id _Nullable'}}
|
|
|
|
ip = foo.d; // expected-warning{{from 'MultiProp * _Nullable'}}
|
|
|
|
ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ _Nullable)(int)'}}
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
2015-06-20 07:18:03 +08:00
|
|
|
|
|
|
|
void testBlockLiterals() {
|
|
|
|
(void)(^id(void) { return 0; });
|
2015-06-25 06:02:08 +08:00
|
|
|
(void)(^id _Nullable (void) { return 0; });
|
|
|
|
(void)(^ _Nullable id(void) { return 0; });
|
2015-06-20 07:18:03 +08:00
|
|
|
|
2015-06-25 06:02:08 +08:00
|
|
|
int *x = (^ _Nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id _Nullable'}}
|
2015-06-20 07:18:03 +08:00
|
|
|
}
|
2016-07-26 05:58:19 +08:00
|
|
|
|
|
|
|
// Check nullability of conditional expressions.
|
|
|
|
void conditional_expr(int c) {
|
|
|
|
NSFoo * _Nonnull p;
|
|
|
|
NSFoo * _Nonnull nonnullP;
|
|
|
|
NSFoo * _Nullable nullableP;
|
|
|
|
NSFoo * _Null_unspecified unspecifiedP;
|
|
|
|
NSFoo *noneP;
|
|
|
|
|
|
|
|
p = c ? nonnullP : nonnullP;
|
|
|
|
p = c ? nonnullP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? nonnullP : unspecifiedP;
|
|
|
|
p = c ? nonnullP : noneP;
|
|
|
|
p = c ? nullableP : nonnullP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? nullableP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? nullableP : unspecifiedP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? nullableP : noneP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? unspecifiedP : nonnullP;
|
|
|
|
p = c ? unspecifiedP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? unspecifiedP : unspecifiedP;
|
|
|
|
p = c ? unspecifiedP : noneP;
|
|
|
|
p = c ? noneP : nonnullP;
|
|
|
|
p = c ? noneP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
|
|
|
|
p = c ? noneP : unspecifiedP;
|
|
|
|
p = c ? noneP : noneP;
|
|
|
|
}
|
2016-11-11 07:28:17 +08:00
|
|
|
|
|
|
|
typedef int INTS[4];
|
|
|
|
@interface ArraysInMethods
|
|
|
|
- (void)simple:(int [_Nonnull 2])x;
|
|
|
|
- (void)nested:(void *_Nullable [_Nonnull 2])x;
|
|
|
|
- (void)nestedBad:(int [2][_Nonnull 2])x; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}}
|
|
|
|
|
|
|
|
- (void)withTypedef:(INTS _Nonnull)x;
|
|
|
|
- (void)withTypedefBad:(INTS _Nonnull[2])x; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
|
|
|
|
|
|
|
|
- (void)simpleSugar:(nonnull int [2])x;
|
|
|
|
- (void)nestedSugar:(nonnull void *_Nullable [2])x; // expected-error {{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'void * _Nullable [2]'}} expected-note {{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'void * _Nullable [2]'}}
|
|
|
|
- (void)sugarWithTypedef:(nonnull INTS)x;
|
|
|
|
@end
|
|
|
|
|
|
|
|
void test(ArraysInMethods *obj) {
|
|
|
|
[obj simple:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
|
|
|
|
[obj nested:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
|
|
|
|
[obj withTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
|
|
|
|
|
|
|
|
[obj simpleSugar:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
|
|
|
|
[obj sugarWithTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
|
|
|
|
}
|