summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-10-25 23:38:07 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-10-25 23:38:07 +0000
commit3c2ed8f3386eebae956267998c2d9aaec9105181 (patch)
tree267893d5d34bec7e9ddb5247e277c6988ccb64a2 /clang/lib/StaticAnalyzer/Checkers
parentf0923f16f88519a8eed863c93bbf5086e4420a3a (diff)
downloadbcm5719-llvm-3c2ed8f3386eebae956267998c2d9aaec9105181.tar.gz
bcm5719-llvm-3c2ed8f3386eebae956267998c2d9aaec9105181.zip
[analyzer] Correct modelling of OSDynamicCast: eagerly state split
Previously, OSDynamicCast was modeled as an identity. This is not correct: the output of OSDynamicCast may be zero even if the input was not zero (if the class is not of desired type), and thus the modeling led to false positives. Instead, we are doing eager state split: in one branch, the returned value is identical to the input parameter, and in the other branch, the returned value is zero. This patch required a substantial refactoring of canEval infrastructure, as now it can return different function summaries, and not just true/false. rdar://45497400 Differential Revision: https://reviews.llvm.org/D53624 llvm-svn: 345338
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index 9826e1ce62c..7db1465fa1b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -774,14 +774,17 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const LocationContext *LCtx = C.getLocationContext();
+ using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
+ Optional<BehaviorSummary> BSmr =
+ SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
+
// See if it's one of the specific functions we know how to eval.
- if (!SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation))
+ if (!BSmr)
return false;
// Bind the return value.
- // For now, all the functions which we can evaluate and which take
- // at least one argument are identities.
- if (CE->getNumArgs() >= 1) {
+ if (BSmr == BehaviorSummary::Identity ||
+ BSmr == BehaviorSummary::IdentityOrZero) {
SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
// If the receiver is unknown or the function has
@@ -793,7 +796,24 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
RetVal =
SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
}
- state = state->BindExpr(CE, LCtx, RetVal, false);
+ state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
+
+ if (BSmr == BehaviorSummary::IdentityOrZero) {
+ // Add a branch where the output is zero.
+ ProgramStateRef NullOutputState = C.getState();
+
+ // Assume that output is zero on the other branch.
+ NullOutputState = NullOutputState->BindExpr(
+ CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
+
+ C.addTransition(NullOutputState);
+
+ // And on the original branch assume that both input and
+ // output are non-zero.
+ if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
+ state = state->assume(*L, /*Assumption=*/true);
+
+ }
}
C.addTransition(state);
OpenPOWER on IntegriCloud