xref: /llvm-project/clang/test/SemaCXX/nullability.cpp (revision 7f78f99fe5af82361d37adcbd2daa4d04afba13d)
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