1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify 2 3 typedef decltype(nullptr) nullptr_t; 4 5 class X { 6 }; 7 8 // Nullability applies to all pointer types. 9 typedef int (X::* __nonnull member_function_type_1)(int); 10 typedef int X::* __nonnull member_data_type_1; 11 typedef nullptr_t __nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}} 12 13 // Nullability can move into member pointers (this is suppressing a warning). 14 typedef __nonnull int (X::* member_function_type_2)(int); 15 typedef int (X::* __nonnull member_function_type_3)(int); 16 typedef __nonnull int X::* member_data_type_2; 17 18 // Adding non-null via a template. 19 template<typename T> 20 struct AddNonNull { 21 typedef __nonnull T type; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'}} 22 // expected-error@-1{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}} 23 }; 24 25 typedef AddNonNull<int *>::type nonnull_int_ptr_1; 26 typedef AddNonNull<int * __nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden 27 typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}} 28 29 typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} 30 31 // Non-null checking within a template. 32 template<typename T> 33 struct AddNonNull2 { 34 typedef __nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 35 typedef __nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 36 typedef __nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 37 typedef __nonnull typename AddNonNull<T>::type okay1; 38 39 // Don't move past a dependent type even if we know that nullability 40 // cannot apply to that specific dependent type. 41 typedef __nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 42 }; 43 44 // Check passing null to a __nonnull argument. 45 void (*accepts_nonnull_1)(__nonnull int *ptr); 46 void (*& accepts_nonnull_2)(__nonnull int *ptr) = accepts_nonnull_1; 47 void (X::* accepts_nonnull_3)(__nonnull int *ptr); 48 void accepts_nonnull_4(__nonnull int *ptr); 49 void (&accepts_nonnull_5)(__nonnull int *ptr) = accepts_nonnull_4; 50 51 void test_accepts_nonnull_null_pointer_literal(X *x) { 52 accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 53 accepts_nonnull_2(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 54 (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 55 accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 56 accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 57 } 58 59 template<void FP(__nonnull int*)> 60 void test_accepts_nonnull_null_pointer_literal_template() { 61 FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 62 } 63 64 template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} 65