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 | |
8 | #include "nullability-completeness.h" |
9 | |
10 | typedef decltype(nullptr) nullptr_t; |
11 | |
12 | class X { |
13 | }; |
14 | |
15 | // Nullability applies to all pointer types. |
16 | typedef int (X::* _Nonnull member_function_type_1)(int); |
17 | typedef int X::* _Nonnull member_data_type_1; |
18 | typedef nullptr_t _Nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}} |
19 | |
20 | // Nullability can move into member pointers (this is suppressing a warning). |
21 | typedef _Nonnull int (X::* member_function_type_2)(int); |
22 | typedef int (X::* _Nonnull member_function_type_3)(int); |
23 | typedef _Nonnull int X::* member_data_type_2; |
24 | |
25 | // Adding non-null via a template. |
26 | template<typename T> |
27 | struct AddNonNull { |
28 | typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}} |
29 | // expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}} |
30 | }; |
31 | |
32 | typedef AddNonNull<int *>::type nonnull_int_ptr_1; |
33 | typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden |
34 | typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}} |
35 | |
36 | typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} |
37 | |
38 | // Non-null checking within a template. |
39 | template<typename T> |
40 | struct AddNonNull2 { |
41 | typedef _Nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} |
42 | typedef _Nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} |
43 | typedef _Nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} |
44 | typedef _Nonnull typename AddNonNull<T>::type okay1; |
45 | |
46 | // Don't move past a dependent type even if we know that nullability |
47 | // cannot apply to that specific dependent type. |
48 | typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} |
49 | }; |
50 | |
51 | // Check passing null to a _Nonnull argument. |
52 | void (*accepts_nonnull_1)(_Nonnull int *ptr); |
53 | void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1; |
54 | void (X::* accepts_nonnull_3)(_Nonnull int *ptr); |
55 | void accepts_nonnull_4(_Nonnull int *ptr); |
56 | void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4; |
57 | |
58 | void test_accepts_nonnull_null_pointer_literal(X *x) { |
59 | accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
60 | accepts_nonnull_2(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
61 | (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
62 | accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
63 | accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
64 | } |
65 | |
66 | template<void FP(_Nonnull int*)> |
67 | void test_accepts_nonnull_null_pointer_literal_template() { |
68 | FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}} |
69 | } |
70 | |
71 | template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} |
72 | |
73 | void TakeNonnull(void *_Nonnull); |
74 | // Check different forms of assignment to a nonull type from a nullable one. |
75 | void AssignAndInitNonNull() { |
76 | void *_Nullable nullable; |
77 | void *_Nonnull p(nullable); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
78 | void *_Nonnull p2{nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
79 | void *_Nonnull p3 = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
80 | void *_Nonnull p4 = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
81 | void *_Nonnull nonnull; |
82 | nonnull = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
83 | nonnull = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
84 | |
85 | TakeNonnull(nullable); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} |
86 | TakeNonnull(nonnull); // OK |
87 | } |
88 | |
89 | void *_Nullable ReturnNullable(); |
90 | |
91 | void AssignAndInitNonNullFromFn() { |
92 | void *_Nonnull p(ReturnNullable()); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
93 | void *_Nonnull p2{ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
94 | void *_Nonnull p3 = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
95 | void *_Nonnull p4 = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
96 | void *_Nonnull nonnull; |
97 | nonnull = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
98 | nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} |
99 | |
100 | TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} |
101 | } |
102 | |
103 | void ConditionalExpr(bool c) { |
104 | struct Base {}; |
105 | struct Derived : Base {}; |
106 | |
107 | Base * _Nonnull p; |
108 | Base * _Nonnull nonnullB; |
109 | Base * _Nullable nullableB; |
110 | Derived * _Nonnull nonnullD; |
111 | Derived * _Nullable nullableD; |
112 | |
113 | p = c ? nonnullB : nonnullD; |
114 | p = c ? nonnullB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
115 | p = c ? nullableB : nonnullD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
116 | p = c ? nullableB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
117 | p = c ? nonnullD : nonnullB; |
118 | p = c ? nonnullD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
119 | p = c ? nullableD : nonnullB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
120 | p = c ? nullableD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
121 | } |
122 | |
123 | void arraysInLambdas() { |
124 | typedef int INTS[4]; |
125 | auto simple = [](int [_Nonnull 2]) {}; |
126 | simple(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} |
127 | auto nested = [](void *_Nullable [_Nonnull 2]) {}; |
128 | nested(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} |
129 | auto nestedBad = [](int [2][_Nonnull 2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}} |
130 | |
131 | auto withTypedef = [](INTS _Nonnull) {}; |
132 | withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} |
133 | auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}} |
134 | } |
135 | |
136 | void testNullabilityCompletenessWithTemplate() { |
137 | Template<int*> tip; |
138 | } |
139 | |