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