summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/lib/Sema/SemaType.cpp37
-rw-r--r--clang/test/FixIt/Inputs/nullability-objc.h48
-rw-r--r--clang/test/FixIt/nullability.mm2
-rw-r--r--clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h2
5 files changed, 77 insertions, 16 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cd06ae831aa..1b02c61cc6c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -229,6 +229,10 @@ struct FileNullability {
/// not have a corresponding nullability annotation.
SourceLocation PointerLoc;
+ /// The end location for the first pointer declarator in the file. Used for
+ /// placing fix-its.
+ SourceLocation PointerEndLoc;
+
/// Which kind of pointer declarator we saw.
uint8_t PointerKind;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index d5ec98c8cba..3c455043af3 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3500,7 +3500,8 @@ static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
static void emitNullabilityConsistencyWarning(Sema &S,
SimplePointerKind PointerKind,
- SourceLocation PointerLoc) {
+ SourceLocation PointerLoc,
+ SourceLocation PointerEndLoc) {
assert(PointerLoc.isValid());
if (PointerKind == SimplePointerKind::Array) {
@@ -3510,14 +3511,15 @@ static void emitNullabilityConsistencyWarning(Sema &S,
<< static_cast<unsigned>(PointerKind);
}
- if (PointerLoc.isMacroID())
+ auto FixItLoc = PointerEndLoc.isValid() ? PointerEndLoc : PointerLoc;
+ if (FixItLoc.isMacroID())
return;
auto addFixIt = [&](NullabilityKind Nullability) {
- auto Diag = S.Diag(PointerLoc, diag::note_nullability_fix_it);
+ auto Diag = S.Diag(FixItLoc, diag::note_nullability_fix_it);
Diag << static_cast<unsigned>(Nullability);
Diag << static_cast<unsigned>(PointerKind);
- fixItNullability(S, Diag, PointerLoc, Nullability);
+ fixItNullability(S, Diag, FixItLoc, Nullability);
};
addFixIt(NullabilityKind::Nullable);
addFixIt(NullabilityKind::NonNull);
@@ -3529,9 +3531,10 @@ static void emitNullabilityConsistencyWarning(Sema &S,
///
/// If the file has \e not seen other uses of nullability, this particular
/// pointer is saved for possible later diagnosis. See recordNullabilitySeen().
-static void checkNullabilityConsistency(Sema &S,
- SimplePointerKind pointerKind,
- SourceLocation pointerLoc) {
+static void
+checkNullabilityConsistency(Sema &S, SimplePointerKind pointerKind,
+ SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc = SourceLocation()) {
// Determine which file we're performing consistency checking for.
FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
if (file.isInvalid())
@@ -3552,6 +3555,7 @@ static void checkNullabilityConsistency(Sema &S,
if (fileNullability.PointerLoc.isInvalid() &&
!S.Context.getDiagnostics().isIgnored(diagKind, pointerLoc)) {
fileNullability.PointerLoc = pointerLoc;
+ fileNullability.PointerEndLoc = pointerEndLoc;
fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
}
@@ -3559,7 +3563,7 @@ static void checkNullabilityConsistency(Sema &S,
}
// Complain about missing nullability.
- emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc);
+ emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc, pointerEndLoc);
}
/// Marks that a nullability feature has been used in the file containing
@@ -3585,7 +3589,8 @@ static void recordNullabilitySeen(Sema &S, SourceLocation loc) {
return;
auto kind = static_cast<SimplePointerKind>(fileNullability.PointerKind);
- emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc);
+ emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc,
+ fileNullability.PointerEndLoc);
}
/// Returns true if any of the declarator chunks before \p endIndex include a
@@ -3895,6 +3900,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Returns true if _Nonnull was inferred.
auto inferPointerNullability = [&](SimplePointerKind pointerKind,
SourceLocation pointerLoc,
+ SourceLocation pointerEndLoc,
AttributeList *&attrs) -> AttributeList * {
// We've seen a pointer.
if (NumPointersRemaining > 0)
@@ -3950,7 +3956,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Fallthrough.
case CAMN_Yes:
- checkNullabilityConsistency(S, pointerKind, pointerLoc);
+ checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
}
return nullptr;
};
@@ -3973,6 +3979,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (auto *attr = inferPointerNullability(
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getDeclSpec().getLocEnd(),
D.getMutableDeclSpec().getAttributes().getListRef())) {
T = Context.getAttributedType(
AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
@@ -4008,8 +4015,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL;
// Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::BlockPointer,
- DeclType.Loc, DeclType.getAttrListRef());
+ inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
+ DeclType.EndLoc, DeclType.getAttrListRef());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
@@ -4031,7 +4038,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Handle pointer nullability
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
- DeclType.getAttrListRef());
+ DeclType.EndLoc, DeclType.getAttrListRef());
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
@@ -4530,8 +4537,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType ClsType;
// Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::MemberPointer,
- DeclType.Loc, DeclType.getAttrListRef());
+ inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
+ DeclType.EndLoc, DeclType.getAttrListRef());
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
diff --git a/clang/test/FixIt/Inputs/nullability-objc.h b/clang/test/FixIt/Inputs/nullability-objc.h
new file mode 100644
index 00000000000..e3e6baafd66
--- /dev/null
+++ b/clang/test/FixIt/Inputs/nullability-objc.h
@@ -0,0 +1,48 @@
+@class Item;
+@class Container<ObjectType>;
+@protocol Protocol;
+
+// rdar://problem/34260995
+// The first pointer in the file is handled in a different way so need
+// a separate test for this case even if the parameter type is the same as in
+// objcIdParameterWithProtocol.
+void objcIdParameterWithProtocolFirstInFile(id<Protocol> i); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:57-[[@LINE-3]]:57}:" _Nullable"
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:57-[[@LINE-4]]:57}:" _Nonnull"
+
+int * _Nonnull forceNullabilityWarningsObjC(void);
+
+void objcClassParameter(Item *i); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:31-[[@LINE-3]]:31}:" _Nullable "
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:31-[[@LINE-4]]:31}:" _Nonnull "
+
+void objcClassParameterWithProtocol(Item<Protocol> *i); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:53-[[@LINE-3]]:53}:" _Nullable "
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:53-[[@LINE-4]]:53}:" _Nonnull "
+
+// rdar://problem/34260995
+void objcIdParameterWithProtocol(id<Protocol> i); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:46-[[@LINE-3]]:46}:" _Nullable"
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:46-[[@LINE-4]]:46}:" _Nonnull"
+
+// Class parameters don't have nullability type specifier.
+void objcParameterizedClassParameter(Container<Item *> *c); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:57-[[@LINE-3]]:57}:" _Nullable "
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:57-[[@LINE-4]]:57}:" _Nonnull "
+
+// Class parameters don't have nullability type specifier.
+void objcParameterizedClassParameterWithProtocol(Container<id<Protocol>> *c); // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-3]]:75-[[@LINE-3]]:75}:" _Nullable "
+// CHECK: fix-it:"{{.*}}nullability-objc.h":{[[@LINE-4]]:75-[[@LINE-4]]:75}:" _Nonnull "
diff --git a/clang/test/FixIt/nullability.mm b/clang/test/FixIt/nullability.mm
index 815c8441924..a91ccc0f5f6 100644
--- a/clang/test/FixIt/nullability.mm
+++ b/clang/test/FixIt/nullability.mm
@@ -2,8 +2,10 @@
// 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
+// RUN: FileCheck %S/Inputs/nullability-objc.h < %t.txt
#include "nullability.h"
+#include "nullability-objc.h"
#pragma clang assume_nonnull begin
diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
index 72f22e2ce47..84a1369618a 100644
--- a/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -6,9 +6,9 @@ void g2(int (^block)(int, int)); // expected-warning{{block pointer is missing a
void g3(const
id // expected-warning{{missing a nullability type specifier}}
+ volatile
// 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}}
OpenPOWER on IntegriCloud