Home | History | Annotate | Download | only in SemaCXX
      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 
     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*)>
     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.
     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 }
    100