Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -279,6 +279,7 @@ def Nullability : DiagGroup<"nullability">; def NullabilityDeclSpec : DiagGroup<"nullability-declspec">; def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">; +def NullConstToNonnull : DiagGroup<"null-const-to-nonnull">; def NullabilityCompleteness : DiagGroup<"nullability-completeness">; def NullArithmetic : DiagGroup<"null-arithmetic">; def NullCharacter : DiagGroup<"null-character">; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -8538,6 +8538,10 @@ "type %1">, InGroup, DefaultIgnore; +def warn_null_const_to_nonnull : Warning< + "implicitly casting a null constant to non-nullable pointer type %0">, + InGroup, DefaultIgnore; + def err_nullability_cs_multilevel : Error< "nullability keyword %0 cannot be applied to multi-level pointer type %1">; def note_nullability_type_specifier : Note< Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -3614,6 +3614,11 @@ void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc); + /// Warn if we're implicitly casting from a null pointer constant to a + /// _Nonnull pointer type. + void diagnoseNullPtrToNonnullCast(QualType DstType, Expr *E, + SourceLocation Loc); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { return DelayedDiagnostics.push(pool); } Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -399,6 +399,7 @@ } } + diagnoseNullPtrToNonnullCast(Ty, E, E->getExprLoc()); return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK); } Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -8685,6 +8685,17 @@ return false; } +void Sema::diagnoseNullPtrToNonnullCast(QualType DstType, Expr *E, + SourceLocation Loc) { + if (!DstType->isAnyPointerType() || CurContext->isDependentContext()) + return; + + if (Optional Kind = DstType->getNullability(Context)) + if (*Kind == NullabilityKind::NonNull && + E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + Diag(Loc, diag::warn_null_const_to_nonnull) << DstType; +} + /// \brief Diagnose pointers that are always non-null. /// \param E the expression containing the pointer /// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -714,6 +714,7 @@ E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); + diagnoseNullPtrToNonnullCast(T, E, E->getExprLoc()); ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, nullptr, VK_RValue); Index: test/Sema/null_const_to_nonnull.c =================================================================== --- /dev/null +++ test/Sema/null_const_to_nonnull.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -Wnull-const-to-nonnull %s -verify + +void null_const_to_nonnull(int c) { + int * _Nonnull p0 = 0; // expected-warning{{implicitly casting a null constant to non-nullable pointer type 'int * _Nonnull'}} + int * _Nonnull p1; + int * _Nonnull p2 = c ? p1 : 0; // expected-warning{{implicitly casting a null constant to non-nullable pointer type 'int * _Nonnull'}} +} Index: test/SemaObjC/null_const_to_nonnull.m =================================================================== --- /dev/null +++ test/SemaObjC/null_const_to_nonnull.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -Wnull-const-to-nonnull %s -verify + +void null_const_to_nonnull(int c) { + id _Nonnull p0 = 0; // expected-warning{{implicitly casting a null constant to non-nullable pointer type 'id _Nonnull'}} + id _Nonnull p1; + id _Nonnull p2 = c ? p1 : 0; // expected-warning{{implicitly casting a null constant to non-nullable pointer type 'id _Nonnull'}} +}