George Burgess IV | 8d141e0 | 2015-12-14 22:00:49 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 2 | |
Douglas Gregor | 4c27d10 | 2015-06-29 18:11:42 +0000 | [diff] [blame] | 3 | #if __has_feature(nullability) |
| 4 | #else |
| 5 | # error nullability feature should be defined |
| 6 | #endif |
| 7 | |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 8 | typedef decltype(nullptr) nullptr_t; |
| 9 | |
| 10 | class X { |
| 11 | }; |
| 12 | |
| 13 | // Nullability applies to all pointer types. |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 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'}} |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 17 | |
| 18 | // Nullability can move into member pointers (this is suppressing a warning). |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 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; |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 22 | |
| 23 | // Adding non-null via a template. |
| 24 | template<typename T> |
| 25 | struct AddNonNull { |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 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'}} |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 28 | }; |
| 29 | |
| 30 | typedef AddNonNull<int *>::type nonnull_int_ptr_1; |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 31 | typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 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 { |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 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; |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 43 | |
| 44 | // Don't move past a dependent type even if we know that nullability |
| 45 | // cannot apply to that specific dependent type. |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 46 | typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} |
Douglas Gregor | 261a89b | 2015-06-19 17:51:05 +0000 | [diff] [blame] | 47 | }; |
Douglas Gregor | b4866e8 | 2015-06-19 18:13:19 +0000 | [diff] [blame] | 48 | |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 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; |
Douglas Gregor | b4866e8 | 2015-06-19 18:13:19 +0000 | [diff] [blame] | 55 | |
| 56 | void 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 | |
Douglas Gregor | aea7afd | 2015-06-24 22:02:08 +0000 | [diff] [blame] | 64 | template<void FP(_Nonnull int*)> |
Douglas Gregor | b4866e8 | 2015-06-19 18:13:19 +0000 | [diff] [blame] | 65 | void 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}} |
George Burgess IV | 8d141e0 | 2015-12-14 22:00:49 +0000 | [diff] [blame] | 70 | |
| 71 | void TakeNonnull(void *_Nonnull); |
| 72 | // Check different forms of assignment to a nonull type from a nullable one. |
| 73 | void 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 | |
| 89 | void 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 | } |
Akira Hatanaka | 73118fd | 2016-07-20 01:48:11 +0000 | [diff] [blame^] | 100 | |
| 101 | void ConditionalExpr(bool c) { |
| 102 | struct Base {}; |
| 103 | struct Derived : Base {}; |
| 104 | |
| 105 | Base * _Nonnull p; |
| 106 | Base * _Nonnull nonnullB; |
| 107 | Base * _Nullable nullableB; |
| 108 | Derived * _Nonnull nonnullD; |
| 109 | Derived * _Nullable nullableD; |
| 110 | |
| 111 | p = c ? nonnullB : nonnullD; |
| 112 | p = c ? nonnullB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 113 | p = c ? nullableB : nonnullD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 114 | p = c ? nullableB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 115 | p = c ? nonnullD : nonnullB; |
| 116 | p = c ? nonnullD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 117 | p = c ? nullableD : nonnullB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 118 | p = c ? nullableD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} |
| 119 | } |