diff options
Diffstat (limited to 'test/SemaCXX/nullability.cpp')
-rw-r--r-- | test/SemaCXX/nullability.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/test/SemaCXX/nullability.cpp b/test/SemaCXX/nullability.cpp new file mode 100644 index 0000000..f0aa13b --- /dev/null +++ b/test/SemaCXX/nullability.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify + +typedef decltype(nullptr) nullptr_t; + +class X { +}; + +// Nullability applies to all pointer types. +typedef int (X::* __nonnull member_function_type_1)(int); +typedef int X::* __nonnull member_data_type_1; +typedef nullptr_t __nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}} + +// Nullability can move into member pointers (this is suppressing a warning). +typedef __nonnull int (X::* member_function_type_2)(int); +typedef int (X::* __nonnull member_function_type_3)(int); +typedef __nonnull int X::* member_data_type_2; + +// Adding non-null via a template. +template<typename T> +struct AddNonNull { + typedef __nonnull T type; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'}} + // expected-error@-1{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}} +}; + +typedef AddNonNull<int *>::type nonnull_int_ptr_1; +typedef AddNonNull<int * __nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden +typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}} + +typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} + +// Non-null checking within a template. +template<typename T> +struct AddNonNull2 { + typedef __nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} + typedef __nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} + typedef __nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}} + typedef __nonnull typename AddNonNull<T>::type okay1; + + // Don't move past a dependent type even if we know that nullability + // cannot apply to that specific dependent type. + typedef __nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}} +}; + +// Check passing null to a __nonnull argument. +void (*accepts_nonnull_1)(__nonnull int *ptr); +void (*& accepts_nonnull_2)(__nonnull int *ptr) = accepts_nonnull_1; +void (X::* accepts_nonnull_3)(__nonnull int *ptr); +void accepts_nonnull_4(__nonnull int *ptr); +void (&accepts_nonnull_5)(__nonnull int *ptr) = accepts_nonnull_4; + +void test_accepts_nonnull_null_pointer_literal(X *x) { + accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} + accepts_nonnull_2(0); // expected-warning{{null passed to a callee that requires a non-null argument}} + (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} + accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} + accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} +} + +template<void FP(__nonnull int*)> +void test_accepts_nonnull_null_pointer_literal_template() { + FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}} +} + +template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} |