ahatanak updated this revision to Diff 65446.
ahatanak added a comment.

Addressed review comment and made a couple of other changes.

- Move Sema::diagnoseNullPtrToNonnullCast to SemaChecking.cpp.
- In diagnoseNullPtrToNonnullCast, call "Type::isAnyPointerType" instead of 
"Type::isPointerType" so that the function can diagnose objective-c pointers in 
addition to c/c++ pointers.
- Instead of adding the new warning to the existing 
"NullableToNonNullConversion" group, which would cause clang to warn about nil 
returns from objective-c methods (which is undesirable according to r240153's 
commit log), create a new diagnostic group for "-Wnull-const_to-nonnull".


https://reviews.llvm.org/D22391

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/Sema.cpp
  lib/Sema/SemaChecking.cpp
  lib/Sema/SemaExpr.cpp
  test/Sema/null_const_to_nonnull.c
  test/SemaObjC/null_const_to_nonnull.m

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'}}
+}
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: 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: 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<NullabilityKind> 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/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: 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: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -8538,6 +8538,10 @@
   "type %1">,
   InGroup<NullableToNonNullConversion>, DefaultIgnore;
 
+def warn_null_const_to_nonnull : Warning<
+  "implicitly casting a null constant to non-nullable pointer type %0">,
+  InGroup<NullConstToNonnull>, 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/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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to