• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion
2  
3  #if __has_feature(nullability)
4  #else
5  #  error nullability feature should be defined
6  #endif
7  
8  typedef decltype(nullptr) nullptr_t;
9  
10  class X {
11  };
12  
13  // Nullability applies to all pointer types.
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'}}
17  
18  // Nullability can move into member pointers (this is suppressing a warning).
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;
22  
23  // Adding non-null via a template.
24  template<typename T>
25  struct AddNonNull {
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'}}
28  };
29  
30  typedef AddNonNull<int *>::type nonnull_int_ptr_1;
31  typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden
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 {
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;
43  
44    // Don't move past a dependent type even if we know that nullability
45    // cannot apply to that specific dependent type.
46    typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}}
47  };
48  
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;
55  
test_accepts_nonnull_null_pointer_literal(X * x)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  
64  template<void FP(_Nonnull int*)>
test_accepts_nonnull_null_pointer_literal_template()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}}
70  
71  void TakeNonnull(void *_Nonnull);
72  // Check different forms of assignment to a nonull type from a nullable one.
AssignAndInitNonNull()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  
AssignAndInitNonNullFromFn()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  }
100