From 06dd406e27b4d43e202b1a8a9782896f80cb0370 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 19 Dec 2016 20:58:20 +0000 Subject: [PATCH] Add fix-it notes to the nullability consistency warning. This is especially important for arrays, since no one knows the proper syntax for putting qualifiers in arrays. nullability.h:3:26: warning: array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) void arrayParameter(int x[]); ^ nullability.h:3:26: note: insert '_Nullable' if the array parameter may be null void arrayParameter(int x[]); ^ _Nullable nullability.h:3:26: note: insert '_Nonnull' if the array parameter should never be null void arrayParameter(int x[]); ^ _Nonnull rdar://problem/29524992 llvm-svn: 290132 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++ clang/lib/Sema/SemaType.cpp | 80 +++++++++++++++------- clang/test/FixIt/Inputs/nullability.h | 19 +++++ clang/test/FixIt/nullability.mm | 40 ++++++----- .../SemaObjCXX/Inputs/nullability-consistency-1.h | 10 +++ .../SemaObjCXX/Inputs/nullability-consistency-2.h | 10 +++ .../SemaObjCXX/Inputs/nullability-consistency-3.h | 2 + .../SemaObjCXX/Inputs/nullability-consistency-4.h | 2 + .../SemaObjCXX/Inputs/nullability-consistency-5.h | 2 + .../SemaObjCXX/Inputs/nullability-consistency-6.h | 5 +- .../SemaObjCXX/Inputs/nullability-consistency-7.h | 4 ++ .../SemaObjCXX/Inputs/nullability-consistency-8.h | 10 ++- .../Inputs/nullability-consistency-arrays.h | 52 +++++++++++--- .../nullability-consistency-system.h | 2 + .../test/SemaObjCXX/Inputs/nullability-pragmas-1.h | 36 +++++++++- 15 files changed, 220 insertions(+), 58 deletions(-) create mode 100644 clang/test/FixIt/Inputs/nullability.h diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 73f7f4d..2e64f10 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8770,6 +8770,10 @@ def warn_nullability_missing_array : Warning< "array parameter is missing a nullability type specifier (_Nonnull, " "_Nullable, or _Null_unspecified)">, InGroup; +def note_nullability_fix_it : Note< + "insert '%select{_Nonnull|_Nullable|_Null_unspecified}0' if the " + "%select{pointer|block pointer|member pointer|array parameter}1 " + "%select{should never be null|may be null|should not declare nullability}0">; def warn_nullability_inferred_on_nested_type : Warning< "inferring '_Nonnull' for pointer type within %select{array|reference}0 is " diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 0466835..eabed44 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3441,6 +3441,57 @@ static FileID getNullabilityCompletenessCheckFileID(Sema &S, return file; } +/// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc, +/// taking into account whitespace before and after. +static FixItHint fixItNullability(Sema &S, SourceLocation PointerLoc, + NullabilityKind Nullability) { + assert(PointerLoc.isValid()); + + SmallString<32> InsertionTextBuf{" "}; + InsertionTextBuf += getNullabilitySpelling(Nullability); + InsertionTextBuf += " "; + StringRef InsertionText = InsertionTextBuf.str(); + + SourceLocation FixItLoc = S.getLocForEndOfToken(PointerLoc); + if (const char *NextChar = S.SourceMgr.getCharacterData(FixItLoc)) { + if (isWhitespace(*NextChar)) { + InsertionText = InsertionText.drop_back(); + } else if (NextChar[-1] == '[') { + if (NextChar[0] == ']') + InsertionText = InsertionText.drop_back().drop_front(); + else + InsertionText = InsertionText.drop_front(); + } else if (!isIdentifierBody(NextChar[0], /*allow dollar*/true) && + !isIdentifierBody(NextChar[-1], /*allow dollar*/true)) { + InsertionText = InsertionText.drop_back().drop_front(); + } + } + + return FixItHint::CreateInsertion(FixItLoc, InsertionText); +} + +static void emitNullabilityConsistencyWarning(Sema &S, + SimplePointerKind PointerKind, + SourceLocation PointerLoc) { + assert(PointerLoc.isValid()); + + if (PointerKind == SimplePointerKind::Array) { + S.Diag(PointerLoc, diag::warn_nullability_missing_array); + } else { + S.Diag(PointerLoc, diag::warn_nullability_missing) + << static_cast(PointerKind); + } + + auto addFixIt = [&](NullabilityKind Nullability) { + S.Diag(PointerLoc, diag::note_nullability_fix_it) + << static_cast(Nullability) + << static_cast(PointerKind) + << fixItNullability(S, PointerLoc, Nullability); + }; + addFixIt(NullabilityKind::Nullable); + addFixIt(NullabilityKind::NonNull); +} + /// Complains about missing nullability if the file containing \p pointerLoc /// has other uses of nullability (either the keywords or the \c assume_nonnull /// pragma). @@ -3477,12 +3528,7 @@ static void checkNullabilityConsistency(Sema &S, } // Complain about missing nullability. - if (pointerKind == SimplePointerKind::Array) { - S.Diag(pointerLoc, diag::warn_nullability_missing_array); - } else { - S.Diag(pointerLoc, diag::warn_nullability_missing) - << static_cast(pointerKind); - } + emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc); } /// Marks that a nullability feature has been used in the file containing @@ -3507,13 +3553,8 @@ static void recordNullabilitySeen(Sema &S, SourceLocation loc) { if (fileNullability.PointerLoc.isInvalid()) return; - if (fileNullability.PointerKind == - static_cast(SimplePointerKind::Array)) { - S.Diag(fileNullability.PointerLoc, diag::warn_nullability_missing_array); - } else { - S.Diag(fileNullability.PointerLoc, diag::warn_nullability_missing) - << static_cast(fileNullability.PointerKind); - } + auto kind = static_cast(fileNullability.PointerKind); + emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc); } /// Returns true if any of the declarator chunks before \p endIndex include a @@ -3847,20 +3888,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (pointerLoc.isValid() && complainAboutInferringWithinChunk != PointerWrappingDeclaratorKind::None) { - SourceLocation fixItLoc = S.getLocForEndOfToken(pointerLoc); - StringRef insertionText = " _Nonnull "; - if (const char *nextChar = S.SourceMgr.getCharacterData(fixItLoc)) { - if (isWhitespace(*nextChar)) { - insertionText = insertionText.drop_back(); - } else if (!isIdentifierBody(nextChar[0], /*allow dollar*/true) && - !isIdentifierBody(nextChar[-1], /*allow dollar*/true)) { - insertionText = insertionText.drop_back().drop_front(); - } - } - S.Diag(pointerLoc, diag::warn_nullability_inferred_on_nested_type) << static_cast(complainAboutInferringWithinChunk) - << FixItHint::CreateInsertion(fixItLoc, insertionText); + << fixItNullability(S, pointerLoc, NullabilityKind::NonNull); } if (inferNullabilityInnerOnly) diff --git a/clang/test/FixIt/Inputs/nullability.h b/clang/test/FixIt/Inputs/nullability.h new file mode 100644 index 0000000..5dd5dfa --- /dev/null +++ b/clang/test/FixIt/Inputs/nullability.h @@ -0,0 +1,19 @@ +int * _Nonnull forceNullabilityWarnings(void); + +void arrayParameter(int x[]); // expected-warning {{array parameter is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable'}} +// expected-note@-2 {{insert '_Nonnull'}} +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:27-[[@LINE-3]]:27}:"_Nullable" +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:27-[[@LINE-4]]:27}:"_Nonnull" + +void arrayParameterWithSize(int x[5]); // expected-warning {{array parameter is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable'}} +// expected-note@-2 {{insert '_Nonnull'}} +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:35-[[@LINE-3]]:35}:"_Nullable " +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:35-[[@LINE-4]]:35}:"_Nonnull " + +void arrayParameterWithStar(int x[*]); // expected-warning {{array parameter is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable'}} +// expected-note@-2 {{insert '_Nonnull'}} +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:35-[[@LINE-3]]:35}:"_Nullable " +// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:35-[[@LINE-4]]:35}:"_Nonnull " diff --git a/clang/test/FixIt/nullability.mm b/clang/test/FixIt/nullability.mm index 2449066..eb900bb 100644 --- a/clang/test/FixIt/nullability.mm +++ b/clang/test/FixIt/nullability.mm @@ -1,59 +1,63 @@ -// RUN: %clang_cc1 -fsyntax-only -fblocks -std=gnu++11 -verify %s -// RUN: not %clang_cc1 -fdiagnostics-parseable-fixits -fblocks -std=gnu++11 %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -fblocks -std=gnu++11 -I %S/Inputs -verify %s +// RUN: not %clang_cc1 -fdiagnostics-parseable-fixits -fblocks -std=gnu++11 -I %S/Inputs %s >%t.txt 2>&1 +// RUN: FileCheck %s < %t.txt +// RUN: FileCheck %S/Inputs/nullability.h < %t.txt + +#include "nullability.h" #pragma clang assume_nonnull begin extern void *array[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull " +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull " extern void* array2[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" _Nonnull" extern void *nestedArray[2][3]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull " +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull " typedef const void *CFTypeRef; extern CFTypeRef typedefArray[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull" extern void *&ref; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" extern void * &ref2; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" extern void *&&ref3; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" extern void * &&ref4; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" extern void *(&arrayRef)[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull" extern void * (&arrayRef2)[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull" extern CFTypeRef &typedefRef; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull" extern CFTypeRef& typedefRef2; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull " +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull " void arrayNameless(void *[]); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"_Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"_Nonnull" void arrayNameless2(void * []); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:27-[[@LINE-1]]:27}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:27-[[@LINE-1]]:27}:" _Nonnull" void arrayNamelessTypedef(CFTypeRef[]); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:36-[[@LINE-1]]:36}:" _Nonnull " +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:36-[[@LINE-1]]:36}:" _Nonnull " void arrayNamelessTypedef2(CFTypeRef []); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}} -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:37}:" _Nonnull" +// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:37-[[@LINE-1]]:37}:" _Nonnull" extern int (*pointerToArray)[2]; // no-warning diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-1.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-1.h index a99f091..f04b569 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-1.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-1.h @@ -1,22 +1,32 @@ void f1(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} void f2(int * _Nonnull); #include "nullability-consistency-2.h" void f3(int *ptr) { // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} int *other = ptr; // shouldn't warn } class X { void mf(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} int X:: *memptr; // expected-warning{{member pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the member pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the member pointer should never be null}} }; template struct Typedefs { typedef T *Base; // no-warning typedef Base *type; // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} }; Typedefs xx; diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h index 520314635..72f22e2 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h @@ -1,11 +1,17 @@ void g1(int * _Nonnull); void g2(int (^block)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the block pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the block pointer should never be null}} void g3(const id // expected-warning{{missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} volatile * // expected-warning{{missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} ); @interface SomeClass @@ -14,8 +20,12 @@ void g3(const - (nullable SomeClass *)method1; - (void)method2:(nonnull SomeClass *)param; @property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} @end @interface SomeClass () @property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} @end diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-3.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-3.h index 520d1a4..e188151 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-3.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-3.h @@ -1 +1,3 @@ void double_declarator1(int *_Nonnull *); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-4.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-4.h index ac227a0..935c093 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-4.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-4.h @@ -1 +1,3 @@ void double_declarator1(int * * _Nonnull); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-5.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-5.h index 1c74ab8..30666c2 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-5.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-5.h @@ -7,6 +7,8 @@ void suppress1(SUPPRESS_NULLABILITY_WARNING(int *) ptr); // no warning void shouldwarn5(int *ptr); //expected-warning{{missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} void trigger5(int * _Nonnull); diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h index d1764a8..e9b2f9b 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-6.h @@ -1,8 +1,11 @@ int *ptr; // expected-warning {{missing a nullability type specifier}} - +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} #pragma clang assume_nonnull begin extern void **blah; // expected-warning 2{{missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} __attribute__((objc_root_class)) @interface ClassWithWeakProperties diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-7.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-7.h index ddbdfad..ed61666 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-7.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-7.h @@ -33,7 +33,11 @@ __attribute__((unavailable("just don't"))) @interface C : A - (instancetype)init; // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} - (instancetype)initWithA:( A*)a __attribute__((objc_designated_initializer)); // expected-warning 2{{pointer is missing a nullability type specifier}} +// expected-note@-1 2{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2{{insert '_Nonnull' if the pointer should never be null}} @end #endif diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-8.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-8.h index 2425a70..1f71315 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-8.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-8.h @@ -8,10 +8,14 @@ __attribute__((objc_root_class)) void func2(mynonnull i); void func3(int *); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) typedef void *CFTypeRef; -void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}} +void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void cf2(CFTypeRef * _Nullable p CF_RETURNS_NOT_RETAINED); void cf3(CFTypeRef * _Nonnull p CF_RETURNS_NOT_RETAINED); @@ -23,5 +27,7 @@ void cf6(CFTypeRef * _Nullable CF_RETURNS_NOT_RETAINED p); void cf7(CF_RETURNS_NOT_RETAINED CFTypeRef * _Nonnull p); typedef CFTypeRef _Nullable *CFTypeRefPtr; -void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}} +void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void cfp2(CFTypeRefPtr _Nonnull p CF_RETURNS_NOT_RETAINED); diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h index 900930c..d0d5125 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h @@ -2,12 +2,16 @@ void firstThingInTheFileThatNeedsNullabilityIsAnArray(int ints[]); #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif int *secondThingInTheFileThatNeedsNullabilityIsAPointer; #if !ARRAYS_CHECKED // expected-warning@-2 {{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-note@-3 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-4 {{insert '_Nonnull' if the pointer should never be null}} #endif int *_Nonnull triggerConsistencyWarnings; @@ -15,21 +19,35 @@ int *_Nonnull triggerConsistencyWarnings; void test( int ints[], #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif void *ptrs[], // expected-warning {{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-4 {{array parameter is missing a nullability type specifier}} +// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}} #endif void **nestedPtrs[]); // expected-warning 2 {{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-4 {{array parameter is missing a nullability type specifier}} +// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}} #endif void testArraysOK( int ints[_Nonnull], void *ptrs[_Nonnull], // expected-warning {{pointer is missing a nullability type specifier}} +// expected-note@-1 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}} void **nestedPtrs[_Nonnull]); // expected-warning 2 {{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} void testAllOK( int ints[_Nonnull], void * _Nullable ptrs[_Nonnull], @@ -57,7 +75,9 @@ void testVAListWithNullability( void nestedArrays(int x[5][1]) {} #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif void nestedArraysOK(int x[_Nonnull 5][1]) {} @@ -72,13 +92,17 @@ typedef int INTS[4]; void typedefTest( INTS x, #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif INTS _Nonnull x2, _Nonnull INTS x3, INTS y[2], #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif INTS y2[_Nonnull 2]); @@ -87,15 +111,23 @@ void typedefTest( void testAssumeNonnull( int ints[], #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif void *ptrs[], #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-2 {{array parameter is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}} #endif void **nestedPtrs[]); // expected-warning 2 {{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} #if ARRAYS_CHECKED -// expected-warning@-2 {{array parameter is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}} +// expected-warning@-4 {{array parameter is missing a nullability type specifier}} +// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}} +// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}} #endif void testAssumeNonnullAllOK( diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h index 9161af1..43e29e0 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h @@ -3,6 +3,8 @@ void system1(int *ptr); #if WARN_IN_SYSTEM_HEADERS // expected-warning@-2{{pointer is missing a nullability type specifier}} +// expected-note@-3 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-4 {{insert '_Nonnull' if the pointer should never be null}} #endif void system2(int * _Nonnull); diff --git a/clang/test/SemaObjCXX/Inputs/nullability-pragmas-1.h b/clang/test/SemaObjCXX/Inputs/nullability-pragmas-1.h index 4ac813d..91753ca 100644 --- a/clang/test/SemaObjCXX/Inputs/nullability-pragmas-1.h +++ b/clang/test/SemaObjCXX/Inputs/nullability-pragmas-1.h @@ -9,6 +9,8 @@ __attribute__((objc_root_class)) struct X { }; void f1(int *x); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} typedef struct __attribute__((objc_bridge(NSError))) __CFError *CFErrorRef; typedef NSError *NSErrorPtr; @@ -39,15 +41,29 @@ int * _Null_unspecified f15(void); A * _Null_unspecified f16(void); void f17(CFErrorRef *error); // expected-note{{no known conversion from 'A * _Nonnull' to 'CFErrorRef _Nullable * _Nullable' (aka '__CFError **') for 1st argument}} void f18(A **); // expected-warning 2{{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} void f19(CFErrorRefPtr error); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void g1(int (^)(int, int)); void g2(int (^ *bp)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}} -// expected-warning@-1{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the block pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the block pointer should never be null}} +// expected-warning@-3{{pointer is missing a nullability type specifier}} +// expected-note@-4{{insert '_Nullable' if the pointer may be null}} +// expected-note@-5{{insert '_Nonnull' if the pointer should never be null}} void g3(block_ptr *bp); // expected-warning{{block pointer is missing a nullability type specifier}} -// expected-warning@-1{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the block pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the block pointer should never be null}} +// expected-warning@-3{{pointer is missing a nullability type specifier}} +// expected-note@-4{{insert '_Nullable' if the pointer may be null}} +// expected-note@-5{{insert '_Nonnull' if the pointer should never be null}} void g4(int (*fp)(int, int)); void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} @interface A(Pragmas1) + (instancetype)aWithA:(A *)a; @@ -57,9 +73,13 @@ void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nulla - (void)method4:(NSErrorPtr *)error; // expected-note{{passing argument to parameter 'error' here}} - (void)method5:(NSErrorPtrPtr)error; // expected-warning@-1{{pointer is missing a nullability type specifier}} +// expected-note@-2{{insert '_Nullable' if the pointer may be null}} +// expected-note@-3{{insert '_Nonnull' if the pointer should never be null}} @property A *aProp; @property NSError **anError; // expected-warning 2{{pointer is missing a nullability type specifier}} +// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}} +// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}} @end int *global_int_ptr; @@ -68,6 +88,8 @@ int *global_int_ptr; typedef int *int_ptr_2; typedef int * // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} *int_ptr_ptr; static inline void f30(void) { @@ -90,12 +112,22 @@ static inline void f30(void) { #pragma clang assume_nonnull end void f20(A *a); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void f21(int_ptr x); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void f22(A_ptr y); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} void f23(int_ptr _Nullable x); void f24(A_ptr _Nullable y); void f25(int_ptr_2 x); // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} @interface A(OutsidePragmas1) + (instancetype)aWithInt:(int)value; // expected-warning{{pointer is missing a nullability type specifier}} +// expected-note@-1{{insert '_Nullable' if the pointer may be null}} +// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}} @end -- 2.7.4