Skip to content

Commit 993060e

Browse files
tripleCCsteakhal
authored andcommitted
[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
1 parent 9c561e8 commit 993060e

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
306306
return NullConstraint::Unknown;
307307
}
308308

309+
static bool isValidPointerType(QualType T) {
310+
return T->isAnyPointerType() || T->isBlockPointerType();
311+
}
312+
309313
const SymbolicRegion *
310314
NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
311315
if (!NeedTracking)
@@ -621,7 +625,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
621625
if (!RetExpr)
622626
return;
623627

624-
if (!RetExpr->getType()->isAnyPointerType())
628+
if (!isValidPointerType(RetExpr->getType()))
625629
return;
626630

627631
ProgramStateRef State = C.getState();
@@ -754,7 +758,7 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
754758
if (!ArgSVal)
755759
continue;
756760

757-
if (!Param->getType()->isAnyPointerType() &&
761+
if (!isValidPointerType(Param->getType()) &&
758762
!Param->getType()->isReferenceType())
759763
continue;
760764

@@ -841,7 +845,7 @@ void NullabilityChecker::checkPostCall(const CallEvent &Call,
841845
if (!FuncType)
842846
return;
843847
QualType ReturnType = FuncType->getReturnType();
844-
if (!ReturnType->isAnyPointerType())
848+
if (!isValidPointerType(ReturnType))
845849
return;
846850
ProgramStateRef State = C.getState();
847851
if (State->get<InvariantViolated>())
@@ -935,7 +939,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
935939
if (!Decl)
936940
return;
937941
QualType RetType = Decl->getReturnType();
938-
if (!RetType->isAnyPointerType())
942+
if (!isValidPointerType(RetType))
939943
return;
940944

941945
ProgramStateRef State = C.getState();
@@ -1089,9 +1093,9 @@ void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
10891093
CheckerContext &C) const {
10901094
QualType OriginType = CE->getSubExpr()->getType();
10911095
QualType DestType = CE->getType();
1092-
if (!OriginType->isAnyPointerType())
1096+
if (!isValidPointerType(OriginType))
10931097
return;
1094-
if (!DestType->isAnyPointerType())
1098+
if (!isValidPointerType(DestType))
10951099
return;
10961100

10971101
ProgramStateRef State = C.getState();
@@ -1215,7 +1219,7 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
12151219
return;
12161220

12171221
QualType LocType = TVR->getValueType();
1218-
if (!LocType->isAnyPointerType())
1222+
if (!isValidPointerType(LocType))
12191223
return;
12201224

12211225
ProgramStateRef State = C.getState();

clang/test/Analysis/nullability.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,13 @@ - (int *_Nonnull)returnsNonnull;
4646
- (int *_Nullable)returnsNullable;
4747
- (int *)returnsUnspecified;
4848
- (void)takesNonnull:(int *_Nonnull)p;
49+
- (void)takesNonnullBlock:(void (^ _Nonnull)(void))block;
4950
- (void)takesNullable:(int *_Nullable)p;
5051
- (void)takesUnspecified:(int *)p;
5152
@property(readonly, strong) NSString *stuff;
5253
@property(readonly, nonnull) int *propReturnsNonnull;
54+
@property(readonly, nonnull) void (^propReturnsNonnullBlock)(void);
55+
@property(readonly, nullable) void (^propReturnsNullableBlock)(void);
5356
@property(readonly, nullable) int *propReturnsNullable;
5457
@property(readonly) int *propReturnsUnspecified;
5558
@end
@@ -65,6 +68,7 @@ - (void)takesUnspecified:(int *)p;
6568
void takesNullable(Dummy *_Nullable);
6669
void takesNonnull(Dummy *_Nonnull);
6770
void takesUnspecified(Dummy *);
71+
void takesNonnullBlock(void (^ _Nonnull)(void));
6872

6973
Dummy *_Nullable returnsNullable();
7074
Dummy *_Nonnull returnsNonnull();
@@ -197,6 +201,7 @@ void testObjCPropertyReadNullability() {
197201
switch (getRandom()) {
198202
case 0:
199203
[o takesNonnull:o.propReturnsNonnull]; // no-warning
204+
[o takesNonnullBlock:o.propReturnsNonnullBlock]; // no-warning
200205
break;
201206
case 1:
202207
[o takesNonnull:o.propReturnsUnspecified]; // no-warning
@@ -236,6 +241,9 @@ void testObjCPropertyReadNullability() {
236241
assert(o.propReturnsNullable);
237242
[o takesNonnull:o.propReturnsNullable]; // no-warning
238243
break;
244+
case 8:
245+
[o takesNonnullBlock:o.propReturnsNullableBlock]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
246+
break;
239247
}
240248
}
241249

@@ -308,6 +316,11 @@ void testIndirectNilPassToNonnull() {
308316
takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
309317
}
310318

319+
void testBlockIndirectNilPassToNonnull() {
320+
void (^p)(void) = nil;
321+
takesNonnullBlock(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
322+
}
323+
311324
void testConditionalNilPassToNonnull(Dummy *p) {
312325
if (!p) {
313326
takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}

0 commit comments

Comments
 (0)