aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-04-03 19:28:15 +0000
committerAnna Zaks <ganna@apple.com>2013-04-03 19:28:15 +0000
commitcabc3fddae63f5eb3bd44bdecce7a3fbd69421a9 (patch)
tree3b0177710b389bd37e92dc7935e6e0b0cc89ffa9
parentc1bef5671e682de5a573c7c6b66871b36de0ec61 (diff)
[analyzer] make peelOffOuterExpr in BugReporterVisitors recursively peel off select Exprs
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178685 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp61
-rw-r--r--test/Analysis/inlining/false-positive-suppression.c25
2 files changed, 56 insertions, 30 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 7f71b8e81e..60a7e65254 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -789,36 +789,33 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
return 0;
}
-static const Expr *peelOffOuterExpr(const Stmt *S,
+static const Expr *peelOffOuterExpr(const Expr *Ex,
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)) {
- const Expr *CondEx = CO->getCond();
-
- // Find a node where the value of the condition is known.
- do {
- ProgramStateRef State = N->getState();
- SVal CondVal = State->getSVal(CondEx, N->getLocationContext());
- ConditionTruthVal CondEvaluated = State->isNull(CondVal);
- if (CondEvaluated.isConstrained()) {
- if (CondEvaluated.isConstrainedTrue())
- return CO->getFalseExpr();
- else
- return CO->getTrueExpr();
- }
- N = N->getFirstPred();
- } while (N);
-
- }
+ Ex = Ex->IgnoreParenCasts();
+ if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
+ return peelOffOuterExpr(EWC->getSubExpr(), N);
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
+ return peelOffOuterExpr(OVE->getSourceExpr(), N);
+
+ // Peel off the ternary operator.
+ if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
+ const Expr *CondEx = CO->getCond();
+
+ // Find a node where the value of the condition is known.
+ do {
+ ProgramStateRef State = N->getState();
+ SVal CondVal = State->getSVal(CondEx, N->getLocationContext());
+ ConditionTruthVal CondEvaluated = State->isNull(CondVal);
+ if (CondEvaluated.isConstrained()) {
+ if (CondEvaluated.isConstrainedTrue())
+ return peelOffOuterExpr(CO->getFalseExpr(), N);
+ else
+ return peelOffOuterExpr(CO->getTrueExpr(), N);
+ }
+ N = N->getFirstPred();
+ } while (N);
}
- return 0;
+ return Ex;
}
bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
@@ -828,8 +825,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
if (!S || !N)
return false;
- if (const Expr *Ex = peelOffOuterExpr(S, N))
- S = Ex;
+ if (const Expr *Ex = dyn_cast<Expr>(S)) {
+ Ex = Ex->IgnoreParenCasts();
+ const Expr *PeeledEx = peelOffOuterExpr(Ex, N);
+ if (Ex != PeeledEx)
+ S = PeeledEx;
+ }
const Expr *Inner = 0;
if (const Expr *Ex = dyn_cast<Expr>(S)) {
diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c
index e12612d8c4..248d854dbc 100644
--- a/test/Analysis/inlining/false-positive-suppression.c
+++ b/test/Analysis/inlining/false-positive-suppression.c
@@ -240,4 +240,29 @@ int ternaryRetNull(char cond) {
#endif
}
+// Test suppression of nested conditional operators.
+int testConditionalOperatorSuppress(int x) {
+ return *(x ? getNull() : getPtr());
+#ifndef SUPPRESSED
+ // expected-warning@-2 {{Dereference of null pointer}}
+#endif
+}
+int testNestedConditionalOperatorSuppress(int x) {
+ return *(x ? (x ? getNull() : getPtr()) : getPtr());
+#ifndef SUPPRESSED
+ // expected-warning@-2 {{Dereference of null pointer}}
+#endif
+}
+int testConditionalOperator(int x) {
+ return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
+}
+int testNestedConditionalOperator(int x) {
+ return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
+}
+
+// False Positve - we are unable to suppress this case because the condition is
+// float.
+int testConditionalOperatorSuppressFloatCond(float x) {
+ return *(x ? getNull() : getPtr()); // expected-warning {{Dereference of null pointer}}
+}