зеркало из https://github.com/microsoft/clang-1.git
[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:
Родитель
c1bef5671e
Коммит
cabc3fddae
|
@ -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}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче