1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion 2 3 #if __has_feature(nullability) 4 #else 5 # error nullability feature should be defined 6 #endif 7 8 typedef decltype(nullptr) nullptr_t; 9 10 class X { 11 }; 12 13 // Nullability applies to all pointer types. 14 typedef int (X::* _Nonnull member_function_type_1)(int); 15 typedef int X::* _Nonnull member_data_type_1; 16 typedef nullptr_t _Nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}} 17 18 // Nullability can move into member pointers (this is suppressing a warning). 19 typedef _Nonnull int (X::* member_function_type_2)(int); 20 typedef int (X::* _Nonnull member_function_type_3)(int); 21 typedef _Nonnull int X::* member_data_type_2; 22 23 // Adding non-null via a template. 24 template<typename T> 25 struct AddNonNull { 26 typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}} 27 // expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}} 28 }; 29 30 typedef AddNonNull<int *>::type nonnull_int_ptr_1; 31 typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden 32 typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}} 33 34 typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} 35 36 // Non-null checking within a template. 37 template<typename T> 38 struct AddNonNull2 { 39 typedef _Nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 40 typedef _Nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 41 typedef _Nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 42 typedef _Nonnull typename AddNonNull<T>::type okay1; 43 44 // Don't move past a dependent type even if we know that nullability 45 // cannot apply to that specific dependent type. 46 typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 47 }; 48 49 // Check passing null to a _Nonnull argument. 50 void (*accepts_nonnull_1)(_Nonnull int *ptr); 51 void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1; 52 void (X::* accepts_nonnull_3)(_Nonnull int *ptr); 53 void accepts_nonnull_4(_Nonnull int *ptr); 54 void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4; 55 test_accepts_nonnull_null_pointer_literal(X * x)56void test_accepts_nonnull_null_pointer_literal(X *x) { 57 accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 58 accepts_nonnull_2(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 59 (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 60 accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 61 accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 62 } 63 64 template<void FP(_Nonnull int*)> test_accepts_nonnull_null_pointer_literal_template()65void test_accepts_nonnull_null_pointer_literal_template() { 66 FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 67 } 68 69 template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} 70 71 void TakeNonnull(void *_Nonnull); 72 // Check different forms of assignment to a nonull type from a nullable one. AssignAndInitNonNull()73void AssignAndInitNonNull() { 74 void *_Nullable nullable; 75 void *_Nonnull p(nullable); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 76 void *_Nonnull p2{nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 77 void *_Nonnull p3 = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 78 void *_Nonnull p4 = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 79 void *_Nonnull nonnull; 80 nonnull = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 81 nonnull = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 82 83 TakeNonnull(nullable); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} 84 TakeNonnull(nonnull); // OK 85 } 86 87 void *_Nullable ReturnNullable(); 88 AssignAndInitNonNullFromFn()89void AssignAndInitNonNullFromFn() { 90 void *_Nonnull p(ReturnNullable()); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 91 void *_Nonnull p2{ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 92 void *_Nonnull p3 = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 93 void *_Nonnull p4 = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 94 void *_Nonnull nonnull; 95 nonnull = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 96 nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 97 98 TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} 99 } 100