llvm-project/clang/test/SemaObjCXX/nullability-pragmas.mm

58 lines
2.9 KiB
Plaintext
Raw Normal View History

// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs %s -verify
#include "nullability-pragmas-1.h"
#include "nullability-pragmas-2.h"
Substitute type arguments into uses of Objective-C interface members. When messaging a method that was defined in an Objective-C class (or category or extension thereof) that has type parameters, substitute the type arguments for those type parameters. Similarly, substitute into property accesses, instance variables, and other references. This includes general infrastructure for substituting the type arguments associated with an ObjCObject(Pointer)Type into a type referenced within a particular context, handling all of the substitutions required to deal with (e.g.) inheritance involving parameterized classes. In cases where no type arguments are available (e.g., because we're messaging via some unspecialized type, id, etc.), we substitute in the type bounds for the type parameters instead. Example: @interface NSSet<T : id<NSCopying>> : NSObject <NSCopying> - (T)firstObject; @end void f(NSSet<NSString *> *stringSet, NSSet *anySet) { [stringSet firstObject]; // produces NSString* [anySet firstObject]; // produces id<NSCopying> (the bound) } When substituting for the type parameters given an unspecialized context (i.e., no specific type arguments were given), substituting the type bounds unconditionally produces type signatures that are too strong compared to the pre-generics signatures. Instead, use the following rule: - In covariant positions, such as method return types, replace type parameters with “id” or “Class” (the latter only when the type parameter bound is “Class” or qualified class, e.g, “Class<NSCopying>”) - In other positions (e.g., parameter types), replace type parameters with their type bounds. - When a specialized Objective-C object or object pointer type contains a type parameter in its type arguments (e.g., NSArray<T>*, but not NSArray<NSString *> *), replace the entire object/object pointer type with its unspecialized version (e.g., NSArray *). llvm-svn: 241543
2015-07-07 11:57:53 +08:00
#include "nullability-pragmas-generics-1.h"
#if !__has_feature(assume_nonnull)
# error assume_nonnull feature is not set
#endif
#if !__has_extension(assume_nonnull)
# error assume_nonnull extension is not set
#endif
void test_pragmas_1(A * _Nonnull a, AA * _Nonnull aa) {
f1(0); // okay: no nullability annotations
f2(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f3(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f4(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f5(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f6(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f7(0); // okay
f8(0); // okay
f9(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f10(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f11(0); // okay
f12(0); // okay
[a method1:0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
f17(a); // expected-error{{no matching function for call to 'f17'}}
[a method3: a]; // expected-error{{cannot initialize a parameter of type 'NSError * _Nullable * _Nullable' with an lvalue of type 'A * _Nonnull'}}
[a method4: a]; // expected-error{{cannot initialize a parameter of type 'NSErrorPtr _Nullable * _Nullable' (aka 'NSError **') with an lvalue of type 'A * _Nonnull'}}
float *ptr;
ptr = f13(); // expected-error{{assigning to 'float *' from incompatible type 'int_ptr _Nonnull' (aka 'int *')}}
ptr = f14(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = [a method1:a]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = a.aProp; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = global_int_ptr; // expected-error{{assigning to 'float *' from incompatible type 'int * _Nonnull'}}
ptr = f15(); // expected-error{{assigning to 'float *' from incompatible type 'int * _Null_unspecified'}}
ptr = f16(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
ptr = [a method2]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
ptr = aa->ivar1; // expected-error{{from incompatible type 'id'}}
ptr = aa->ivar2; // expected-error{{from incompatible type 'id _Nonnull'}}
}
Substitute type arguments into uses of Objective-C interface members. When messaging a method that was defined in an Objective-C class (or category or extension thereof) that has type parameters, substitute the type arguments for those type parameters. Similarly, substitute into property accesses, instance variables, and other references. This includes general infrastructure for substituting the type arguments associated with an ObjCObject(Pointer)Type into a type referenced within a particular context, handling all of the substitutions required to deal with (e.g.) inheritance involving parameterized classes. In cases where no type arguments are available (e.g., because we're messaging via some unspecialized type, id, etc.), we substitute in the type bounds for the type parameters instead. Example: @interface NSSet<T : id<NSCopying>> : NSObject <NSCopying> - (T)firstObject; @end void f(NSSet<NSString *> *stringSet, NSSet *anySet) { [stringSet firstObject]; // produces NSString* [anySet firstObject]; // produces id<NSCopying> (the bound) } When substituting for the type parameters given an unspecialized context (i.e., no specific type arguments were given), substituting the type bounds unconditionally produces type signatures that are too strong compared to the pre-generics signatures. Instead, use the following rule: - In covariant positions, such as method return types, replace type parameters with “id” or “Class” (the latter only when the type parameter bound is “Class” or qualified class, e.g, “Class<NSCopying>”) - In other positions (e.g., parameter types), replace type parameters with their type bounds. - When a specialized Objective-C object or object pointer type contains a type parameter in its type arguments (e.g., NSArray<T>*, but not NSArray<NSString *> *), replace the entire object/object pointer type with its unspecialized version (e.g., NSArray *). llvm-svn: 241543
2015-07-07 11:57:53 +08:00
void test_pragmas_generics(void) {
float *fp;
NSGeneric<C *> *genC;
fp = [genC tee]; // expected-error{{from incompatible type 'C *'}}
fp = [genC maybeTee]; // expected-error{{from incompatible type 'C * _Nullable'}}
Generic_with_C genC2;
fp = genC2; // expected-error{{from incompatible type 'Generic_with_C' (aka 'NSGeneric<C *> *')}}
}