[clang] 993060e - [StaticAnalyzer] Fix block pointer type nullability check

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Tue May 30 02:20:28 PDT 2023


Author: tripleCC
Date: 2023-05-30T11:20:05+02:00
New Revision: 993060e1d31d07e9c44e7164d24f9f495197ca87

URL: https://github.com/llvm/llvm-project/commit/993060e1d31d07e9c44e7164d24f9f495197ca87
DIFF: https://github.com/llvm/llvm-project/commit/993060e1d31d07e9c44e7164d24f9f495197ca87.diff

LOG: [StaticAnalyzer] Fix block pointer type nullability check

This patch fixes a false negative when the property type
is an objective-c block pointer.

Patch By tripleCC!

Differential Revision: https://reviews.llvm.org/D151651

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    clang/test/Analysis/nullability.mm

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index da8529f4ea813..11d5e77db0c73 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -306,6 +306,10 @@ static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
   return NullConstraint::Unknown;
 }
 
+static bool isValidPointerType(QualType T) {
+  return T->isAnyPointerType() || T->isBlockPointerType();
+}
+
 const SymbolicRegion *
 NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
   if (!NeedTracking)
@@ -621,7 +625,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
   if (!RetExpr)
     return;
 
-  if (!RetExpr->getType()->isAnyPointerType())
+  if (!isValidPointerType(RetExpr->getType()))
     return;
 
   ProgramStateRef State = C.getState();
@@ -754,7 +758,7 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
     if (!ArgSVal)
       continue;
 
-    if (!Param->getType()->isAnyPointerType() &&
+    if (!isValidPointerType(Param->getType()) &&
         !Param->getType()->isReferenceType())
       continue;
 
@@ -841,7 +845,7 @@ void NullabilityChecker::checkPostCall(const CallEvent &Call,
   if (!FuncType)
     return;
   QualType ReturnType = FuncType->getReturnType();
-  if (!ReturnType->isAnyPointerType())
+  if (!isValidPointerType(ReturnType))
     return;
   ProgramStateRef State = C.getState();
   if (State->get<InvariantViolated>())
@@ -935,7 +939,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
   if (!Decl)
     return;
   QualType RetType = Decl->getReturnType();
-  if (!RetType->isAnyPointerType())
+  if (!isValidPointerType(RetType))
     return;
 
   ProgramStateRef State = C.getState();
@@ -1089,9 +1093,9 @@ void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
                                        CheckerContext &C) const {
   QualType OriginType = CE->getSubExpr()->getType();
   QualType DestType = CE->getType();
-  if (!OriginType->isAnyPointerType())
+  if (!isValidPointerType(OriginType))
     return;
-  if (!DestType->isAnyPointerType())
+  if (!isValidPointerType(DestType))
     return;
 
   ProgramStateRef State = C.getState();
@@ -1215,7 +1219,7 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
     return;
 
   QualType LocType = TVR->getValueType();
-  if (!LocType->isAnyPointerType())
+  if (!isValidPointerType(LocType))
     return;
 
   ProgramStateRef State = C.getState();

diff  --git a/clang/test/Analysis/nullability.mm b/clang/test/Analysis/nullability.mm
index f9b3fc60c5a02..44c241e07ee50 100644
--- a/clang/test/Analysis/nullability.mm
+++ b/clang/test/Analysis/nullability.mm
@@ -46,10 +46,13 @@ - (int *_Nonnull)returnsNonnull;
 - (int *_Nullable)returnsNullable;
 - (int *)returnsUnspecified;
 - (void)takesNonnull:(int *_Nonnull)p;
+- (void)takesNonnullBlock:(void (^ _Nonnull)(void))block;
 - (void)takesNullable:(int *_Nullable)p;
 - (void)takesUnspecified:(int *)p;
 @property(readonly, strong) NSString *stuff;
 @property(readonly, nonnull) int *propReturnsNonnull;
+ at property(readonly, nonnull) void (^propReturnsNonnullBlock)(void);
+ at property(readonly, nullable) void (^propReturnsNullableBlock)(void);
 @property(readonly, nullable) int *propReturnsNullable;
 @property(readonly) int *propReturnsUnspecified;
 @end
@@ -65,6 +68,7 @@ - (void)takesUnspecified:(int *)p;
 void takesNullable(Dummy *_Nullable);
 void takesNonnull(Dummy *_Nonnull);
 void takesUnspecified(Dummy *);
+void takesNonnullBlock(void (^ _Nonnull)(void));
 
 Dummy *_Nullable returnsNullable();
 Dummy *_Nonnull returnsNonnull();
@@ -197,6 +201,7 @@ void testObjCPropertyReadNullability() {
   switch (getRandom()) {
   case 0:
     [o takesNonnull:o.propReturnsNonnull]; // no-warning
+    [o takesNonnullBlock:o.propReturnsNonnullBlock]; // no-warning
     break;
   case 1:
     [o takesNonnull:o.propReturnsUnspecified]; // no-warning
@@ -236,6 +241,9 @@ void testObjCPropertyReadNullability() {
     assert(o.propReturnsNullable);
     [o takesNonnull:o.propReturnsNullable]; // no-warning
     break;
+  case 8:
+    [o takesNonnullBlock:o.propReturnsNullableBlock]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
+    break;
   }
 }
 
@@ -308,6 +316,11 @@ void testIndirectNilPassToNonnull() {
   takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
 }
 
+void testBlockIndirectNilPassToNonnull() {
+  void (^p)(void) = nil;
+  takesNonnullBlock(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
+}
+
 void testConditionalNilPassToNonnull(Dummy *p) {
   if (!p) {
     takesNonnull(p);  // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}


        


More information about the cfe-commits mailing list