Skip to content

Commit 49bd58f

Browse files
committed
[analyzer] Nullability: Suppress return diagnostics in inlined functions.
The nullability checker can sometimes miss detecting nullability precondition violations in inlined functions because the binding for the parameter that violated the precondition becomes dead before the return: int * _Nonnull callee(int * _Nonnull p2) { if (!p2) // p2 becomes dead here, so binding removed. return 0; // warning here because value stored in p2 is symbolic. else return p2; } int *caller(int * _Nonnull p1) { return callee(p1); } The fix, which is quite blunt, is to not warn about null returns in inlined methods/functions. This won’t lose much coverage for ObjC because the analyzer always analyzes each ObjC method at the top level in addition to inlined. It *will* lose coverage for C — but there aren’t that many codebases with C nullability annotations. rdar://problem/25615050 llvm-svn: 266109
1 parent fd3e1ad commit 49bd58f

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
562562
if (Filter.CheckNullReturnedFromNonnull &&
563563
NullReturnedFromNonNull &&
564564
RetExprTypeLevelNullability != Nullability::Nonnull &&
565-
!InSuppressedMethodFamily) {
565+
!InSuppressedMethodFamily &&
566+
C.getLocationContext()->inTopFrame()) {
566567
static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
567568
ExplodedNode *N = C.generateErrorNode(State, &Tag);
568569
if (!N)

clang/test/Analysis/nullability.mm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,41 @@ void testPreconditionViolationInInlinedFunction(Dummy *p) {
238238
doNotWarnWhenPreconditionIsViolated(p);
239239
}
240240

241+
@interface TestInlinedPreconditionViolationClass : NSObject
242+
@end
243+
244+
@implementation TestInlinedPreconditionViolationClass
245+
-(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
246+
Dummy *x = 0;
247+
if (!p2) // p2 binding becomes dead at this point.
248+
return x; // no-warning
249+
else
250+
return p2;
251+
}
252+
253+
-(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
254+
return [self calleeWithParam:p1];
255+
}
256+
257+
@end
258+
259+
int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
260+
int *x = 0;
261+
if (!p2) // p2 binding becomes dead at this point.
262+
return x; // no-warning
263+
else
264+
return p2;
265+
}
266+
267+
int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
268+
int *result = 0;
269+
return result; // no-warning; but this is an over suppression
270+
}
271+
272+
int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {
273+
return InlinedReturnNullOverSuppressionCallee(p1);
274+
}
275+
241276
void inlinedNullable(Dummy *_Nullable p) {
242277
if (p) return;
243278
}

0 commit comments

Comments
 (0)