1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion -I%S/Inputs 2 3 #if __has_feature(nullability) 4 #else 5 # error nullability feature should be defined 6 #endif 7 #if __has_feature(nullability_on_classes) 8 #else 9 # error smart-pointer feature should be defined 10 #endif 11 12 #include "nullability-completeness.h" 13 14 typedef decltype(nullptr) nullptr_t; 15 16 class X { 17 }; 18 19 // Nullability applies to all pointer types. 20 typedef int (X::* _Nonnull member_function_type_1)(int); 21 typedef int X::* _Nonnull member_data_type_1; 22 typedef nullptr_t _Nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t' (aka 'std::nullptr_t')}} 23 24 // Nullability can move into member pointers (this is suppressing a warning). 25 typedef _Nonnull int (X::* member_function_type_2)(int); 26 typedef int (X::* _Nonnull member_function_type_3)(int); 27 typedef _Nonnull int X::* member_data_type_2; 28 29 // Adding non-null via a template. 30 template<typename T> 31 struct AddNonNull { 32 typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}} 33 // expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'std::nullptr_t'}} 34 // expected-error@-2{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'NotPtr'}} 35 }; 36 37 typedef AddNonNull<int *>::type nonnull_int_ptr_1; 38 typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden 39 typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}} 40 41 typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} 42 43 // Nullability on C++ class types (smart pointers). 44 struct NotPtr{}; 45 typedef AddNonNull<NotPtr>::type nonnull_non_pointer_2; // expected-note{{in instantiation}} 46 struct _Nullable SmartPtr{ 47 SmartPtr(); 48 SmartPtr(nullptr_t); 49 SmartPtr(const SmartPtr&); 50 SmartPtr(SmartPtr&&); 51 SmartPtr &operator=(const SmartPtr&); 52 SmartPtr &operator=(SmartPtr&&); 53 }; 54 typedef AddNonNull<SmartPtr>::type nonnull_smart_pointer_1; 55 template<class> struct _Nullable SmartPtrTemplate{}; 56 typedef AddNonNull<SmartPtrTemplate<int>>::type nonnull_smart_pointer_2; 57 namespace std { inline namespace __1 { 58 template <class> class unique_ptr {}; 59 template <class> class function; 60 template <class Ret, class... Args> class function<Ret(Args...)> {}; 61 } } 62 typedef AddNonNull<std::unique_ptr<int>>::type nonnull_smart_pointer_3; 63 typedef AddNonNull<std::function<int()>>::type nonnull_smart_pointer_4; 64 65 class Derived : public SmartPtr {}; 66 Derived _Nullable x; // expected-error {{'_Nullable' cannot be applied}} 67 class DerivedPrivate : private SmartPtr {}; 68 DerivedPrivate _Nullable y; // expected-error {{'_Nullable' cannot be applied}} 69 70 // Non-null checking within a template. 71 template<typename T> 72 struct AddNonNull2 { 73 typedef _Nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 74 typedef _Nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 75 typedef _Nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} 76 typedef _Nonnull typename AddNonNull<T>::type okay1; 77 78 // Don't move past a dependent type even if we know that nullability 79 // cannot apply to that specific dependent type. 80 typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} 81 }; 82 83 // Check passing null to a _Nonnull argument. 84 void (*accepts_nonnull_1)(_Nonnull int *ptr); 85 void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1; 86 void (X::* accepts_nonnull_3)(_Nonnull int *ptr); 87 void accepts_nonnull_4(_Nonnull int *ptr); 88 void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4; 89 void accepts_nonnull_6(SmartPtr _Nonnull); 90 91 void test_accepts_nonnull_null_pointer_literal(X *x) { 92 accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 93 accepts_nonnull_2(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 94 (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 95 accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 96 accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 97 98 accepts_nonnull_6(nullptr); // expected-warning{{null passed to a callee that requires a non-null argument}} 99 } 100 101 template<void FP(_Nonnull int*)> 102 void test_accepts_nonnull_null_pointer_literal_template() { 103 FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}} 104 } 105 106 template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} 107 108 void TakeNonnull(void *_Nonnull); 109 void TakeSmartNonnull(SmartPtr _Nonnull); 110 // Check different forms of assignment to a nonull type from a nullable one. 111 void AssignAndInitNonNull() { 112 void *_Nullable nullable; 113 void *_Nonnull p(nullable); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 114 void *_Nonnull p2{nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 115 void *_Nonnull p3 = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 116 void *_Nonnull p4 = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 117 void *_Nonnull nonnull; 118 nonnull = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 119 nonnull = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 120 TakeNonnull(nullable); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} 121 TakeNonnull(nonnull); // OK 122 nonnull = (void *_Nonnull)nullable; // explicit cast OK 123 124 SmartPtr _Nullable s_nullable; 125 SmartPtr _Nonnull s(s_nullable); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 126 SmartPtr _Nonnull s2{s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 127 SmartPtr _Nonnull s3 = {s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 128 SmartPtr _Nonnull s4 = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 129 SmartPtr _Nonnull s_nonnull; 130 s_nonnull = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 131 s_nonnull = {s_nullable}; // no warning here - might be nice? 132 TakeSmartNonnull(s_nullable); //expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull}} 133 TakeSmartNonnull(s_nonnull); // OK 134 s_nonnull = (SmartPtr _Nonnull)s_nullable; // explicit cast OK 135 s_nonnull = static_cast<SmartPtr _Nonnull>(s_nullable); // explicit cast OK 136 } 137 138 void *_Nullable ReturnNullable(); 139 SmartPtr _Nullable ReturnSmartNullable(); 140 141 void AssignAndInitNonNullFromFn() { 142 void *_Nonnull p(ReturnNullable()); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 143 void *_Nonnull p2{ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 144 void *_Nonnull p3 = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 145 void *_Nonnull p4 = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 146 void *_Nonnull nonnull; 147 nonnull = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 148 nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} 149 TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} 150 151 SmartPtr _Nonnull s(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 152 SmartPtr _Nonnull s2{ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 153 SmartPtr _Nonnull s3 = {ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 154 SmartPtr _Nonnull s4 = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 155 SmartPtr _Nonnull s_nonnull; 156 s_nonnull = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 157 s_nonnull = {ReturnSmartNullable()}; 158 TakeSmartNonnull(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} 159 } 160 161 void ConditionalExpr(bool c) { 162 struct Base {}; 163 struct Derived : Base {}; 164 165 Base * _Nonnull p; 166 Base * _Nonnull nonnullB; 167 Base * _Nullable nullableB; 168 Derived * _Nonnull nonnullD; 169 Derived * _Nullable nullableD; 170 171 p = c ? nonnullB : nonnullD; 172 p = c ? nonnullB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 173 p = c ? nullableB : nonnullD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 174 p = c ? nullableB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 175 p = c ? nonnullD : nonnullB; 176 p = c ? nonnullD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 177 p = c ? nullableD : nonnullB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 178 p = c ? nullableD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} 179 } 180 181 void arraysInLambdas() { 182 typedef int INTS[4]; 183 auto simple = [](int [_Nonnull 2]) {}; 184 simple(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} 185 auto nested = [](void *_Nullable [_Nonnull 2]) {}; 186 nested(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} 187 auto nestedBad = [](int [2][_Nonnull 2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int[2]'}} 188 189 auto withTypedef = [](INTS _Nonnull) {}; 190 withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} 191 auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} 192 } 193 194 void testNullabilityCompletenessWithTemplate() { 195 Template<int*> tip; 196 } 197 198 namespace GH60344 { 199 class a; 200 template <typename b> using c = b _Nullable; // expected-error {{'_Nullable' cannot be applied to non-pointer type 'a'}} 201 c<a>; // expected-note {{in instantiation of template type alias 'c' requested here}} 202 } 203