[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; return 0;
} }
static const Expr *peelOffOuterExpr(const Stmt *S, static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) { const ExplodedNode *N) {
if (const Expr *Ex = dyn_cast<Expr>(S)) { Ex = Ex->IgnoreParenCasts();
Ex = Ex->IgnoreParenCasts(); if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex)) return peelOffOuterExpr(EWC->getSubExpr(), N);
return EWC->getSubExpr(); if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex)) return peelOffOuterExpr(OVE->getSourceExpr(), N);
return OVE->getSourceExpr();
// Peel off the ternary operator. // Peel off the ternary operator.
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) { if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
const Expr *CondEx = CO->getCond(); const Expr *CondEx = CO->getCond();
// Find a node where the value of the condition is known. // Find a node where the value of the condition is known.
do { do {
ProgramStateRef State = N->getState(); ProgramStateRef State = N->getState();
SVal CondVal = State->getSVal(CondEx, N->getLocationContext()); SVal CondVal = State->getSVal(CondEx, N->getLocationContext());
ConditionTruthVal CondEvaluated = State->isNull(CondVal); ConditionTruthVal CondEvaluated = State->isNull(CondVal);
if (CondEvaluated.isConstrained()) { if (CondEvaluated.isConstrained()) {
if (CondEvaluated.isConstrainedTrue()) if (CondEvaluated.isConstrainedTrue())
return CO->getFalseExpr(); return peelOffOuterExpr(CO->getFalseExpr(), N);
else else
return CO->getTrueExpr(); return peelOffOuterExpr(CO->getTrueExpr(), N);
} }
N = N->getFirstPred(); N = N->getFirstPred();
} while (N); } while (N);
}
} }
return 0; return Ex;
} }
bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
@ -828,8 +825,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
if (!S || !N) if (!S || !N)
return false; return false;
if (const Expr *Ex = peelOffOuterExpr(S, N)) if (const Expr *Ex = dyn_cast<Expr>(S)) {
S = Ex; Ex = Ex->IgnoreParenCasts();
const Expr *PeeledEx = peelOffOuterExpr(Ex, N);
if (Ex != PeeledEx)
S = PeeledEx;
}
const Expr *Inner = 0; const Expr *Inner = 0;
if (const Expr *Ex = dyn_cast<Expr>(S)) { if (const Expr *Ex = dyn_cast<Expr>(S)) {

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

@ -240,4 +240,29 @@ int ternaryRetNull(char cond) {
#endif #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}}
}