[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,14 +789,13 @@ 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 EWC->getSubExpr(); return peelOffOuterExpr(EWC->getSubExpr(), N);
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex)) if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return OVE->getSourceExpr(); return peelOffOuterExpr(OVE->getSourceExpr(), N);
// 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)) {
@ -809,16 +808,14 @@ static const Expr *peelOffOuterExpr(const Stmt *S,
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 Ex;
return 0;
} }
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}}
}