aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-03-26 23:58:49 +0000
committerAnna Zaks <ganna@apple.com>2013-03-26 23:58:49 +0000
commit1533833e21ae5b3f5f39b168b3fbac109ee77008 (patch)
tree3d856870ee5a9bd1c228670ede34c98ff71142b1 /lib/StaticAnalyzer
parent2fcadbeecbbc0b48dc92b9ce778e5c7a53292505 (diff)
[analyzer] Make sure IDC works for ‘NSContainer value/key is nil’ checks.
Register the nil tracking visitors with the region and refactor trackNullOrUndefValue a bit. Also adds the cast and paren stripping before checking if the value is an OpaqueValueExpr or ExprWithCleanups. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178093 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp36
2 files changed, 23 insertions, 14 deletions
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index fb43964a89..533a324e75 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -139,6 +139,7 @@ void NilArgChecker::WarnIfNilArg(CheckerContext &C,
BugReport *R = new BugReport(*BT, os.str(), N);
R->addRange(msg.getArgSourceRange(Arg));
+ bugreporter::trackNullOrUndefValue(N, msg.getArgExpr(Arg), *R);
C.emitReport(R);
}
}
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 737285823f..4539d85cca 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -781,31 +781,39 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
return 0;
}
-bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
- const Stmt *S,
- BugReport &report, bool IsArg) {
- if (!S || !N)
- return false;
-
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
- S = EWC->getSubExpr();
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S))
- S = OVE->getSourceExpr();
-
- // Peel off the ternary operator.
+static const Expr *peelOffOuterExpr(const Stmt *S,
+ const ExplodedNode *N) {
if (const Expr *Ex = dyn_cast<Expr>(S)) {
Ex = Ex->IgnoreParenCasts();
+ if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
+ return EWC->getSubExpr();
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
+ return OVE->getSourceExpr();
+
+ // Peel off the ternary operator.
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
ProgramStateRef State = N->getState();
SVal CondVal = State->getSVal(CO->getCond(), N->getLocationContext());
if (State->isNull(CondVal).isConstrainedTrue()) {
- S = CO->getTrueExpr();
+ return CO->getTrueExpr();
} else {
assert(State->isNull(CondVal).isConstrainedFalse());
- S = CO->getFalseExpr();
+ return CO->getFalseExpr();
}
}
}
+ return 0;
+}
+
+bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
+ const Stmt *S,
+ BugReport &report, bool IsArg) {
+ if (!S || !N)
+ return false;
+
+ if (const Expr *Ex = peelOffOuterExpr(S, N)) {
+ S = Ex;
+ }
const Expr *Inner = 0;
if (const Expr *Ex = dyn_cast<Expr>(S)) {