summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Coughlin <dcoughlin@apple.com>2016-04-12 19:29:52 +0000
committerDevin Coughlin <dcoughlin@apple.com>2016-04-12 19:29:52 +0000
commit49bd58f1ebe28d97e4949e9c757bc5dfd8b2d72f (patch)
treec3879d19b604cf8e066643666d9d51fa9553f78f
parentfd3e1ad0ce073e67c21833e56b74105ce8339ce3 (diff)
downloadbcm5719-llvm-49bd58f1ebe28d97e4949e9c757bc5dfd8b2d72f.tar.gz
bcm5719-llvm-49bd58f1ebe28d97e4949e9c757bc5dfd8b2d72f.zip
[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
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp3
-rw-r--r--clang/test/Analysis/nullability.mm35
2 files changed, 37 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 35620d33acf..d8a224ea2f4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -562,7 +562,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
if (Filter.CheckNullReturnedFromNonnull &&
NullReturnedFromNonNull &&
RetExprTypeLevelNullability != Nullability::Nonnull &&
- !InSuppressedMethodFamily) {
+ !InSuppressedMethodFamily &&
+ C.getLocationContext()->inTopFrame()) {
static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
ExplodedNode *N = C.generateErrorNode(State, &Tag);
if (!N)
diff --git a/clang/test/Analysis/nullability.mm b/clang/test/Analysis/nullability.mm
index 0a3ae7a1968..1e01cdf4ca6 100644
--- a/clang/test/Analysis/nullability.mm
+++ b/clang/test/Analysis/nullability.mm
@@ -238,6 +238,41 @@ void testPreconditionViolationInInlinedFunction(Dummy *p) {
doNotWarnWhenPreconditionIsViolated(p);
}
+@interface TestInlinedPreconditionViolationClass : NSObject
+@end
+
+@implementation TestInlinedPreconditionViolationClass
+-(Dummy * _Nonnull) calleeWithParam:(Dummy * _Nonnull) p2 {
+ Dummy *x = 0;
+ if (!p2) // p2 binding becomes dead at this point.
+ return x; // no-warning
+ else
+ return p2;
+}
+
+-(Dummy *)callerWithParam:(Dummy * _Nonnull) p1 {
+ return [self calleeWithParam:p1];
+}
+
+@end
+
+int * _Nonnull InlinedPreconditionViolationInFunctionCallee(int * _Nonnull p2) {
+ int *x = 0;
+ if (!p2) // p2 binding becomes dead at this point.
+ return x; // no-warning
+ else
+ return p2;
+}
+
+int * _Nonnull InlinedReturnNullOverSuppressionCallee(int * _Nonnull p2) {
+ int *result = 0;
+ return result; // no-warning; but this is an over suppression
+}
+
+int *InlinedReturnNullOverSuppressionCaller(int * _Nonnull p1) {
+ return InlinedReturnNullOverSuppressionCallee(p1);
+}
+
void inlinedNullable(Dummy *_Nullable p) {
if (p) return;
}
OpenPOWER on IntegriCloud