[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
This commit is contained in:
Anna Zaks 2013-04-03 19:28:15 +00:00
Родитель c1bef5671e
Коммит cabc3fddae
2 изменённых файлов: 54 добавлений и 28 удалений

Просмотреть файл

@ -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();
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();
// 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);
}
// 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)) {

Просмотреть файл

@ -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}}
}