[analyzer] Make branch for condition callback use CheckerContext
Now, all the path sensitive checkers use CheckerContext! llvm-svn: 142944
This commit is contained in:
parent
3eae33412d
commit
f380534a1a
|
@ -214,10 +214,9 @@ public:
|
|||
|
||||
class BranchCondition {
|
||||
template <typename CHECKER>
|
||||
static void _checkBranchCondition(void *checker, const Stmt *condition,
|
||||
NodeBuilder &B, ExplodedNode *Pred,
|
||||
ExprEngine &Eng) {
|
||||
((const CHECKER *)checker)->checkBranchCondition(condition, B, Pred, Eng);
|
||||
static void _checkBranchCondition(void *checker, const Stmt *Condition,
|
||||
CheckerContext & C) {
|
||||
((const CHECKER *)checker)->checkBranchCondition(Condition, C);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -236,7 +236,7 @@ public:
|
|||
|
||||
/// \brief Run checkers for branch condition.
|
||||
void runCheckersForBranchCondition(const Stmt *condition,
|
||||
NodeBuilder &B, ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst, ExplodedNode *Pred,
|
||||
ExprEngine &Eng);
|
||||
|
||||
/// \brief Run checkers for live symbols.
|
||||
|
@ -339,8 +339,7 @@ public:
|
|||
typedef CheckerFn<void (CheckerContext &)>
|
||||
CheckEndPathFunc;
|
||||
|
||||
typedef CheckerFn<void (const Stmt *, NodeBuilder &, ExplodedNode *Pred,
|
||||
ExprEngine &)>
|
||||
typedef CheckerFn<void (const Stmt *, CheckerContext &)>
|
||||
CheckBranchConditionFunc;
|
||||
|
||||
typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
|
||||
|
|
|
@ -49,27 +49,18 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
|
|||
};
|
||||
|
||||
public:
|
||||
void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder,
|
||||
ExplodedNode *Pred, ExprEngine &Eng) const;
|
||||
void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
|
||||
NodeBuilder &Builder,
|
||||
ExplodedNode *Pred,
|
||||
ExprEngine &Eng) const {
|
||||
const ProgramState *state = Pred->getState();
|
||||
SVal X = state->getSVal(Condition);
|
||||
CheckerContext &Ctx) const {
|
||||
SVal X = Ctx.getState()->getSVal(Condition);
|
||||
if (X.isUndef()) {
|
||||
// TODO: The PP will be generated with the correct tag by the CheckerManager
|
||||
// after we migrate the callback to CheckerContext.
|
||||
const ProgramPointTag *Tag = 0;
|
||||
ProgramPoint PP = PostCondition(Condition, Pred->getLocationContext(), Tag);
|
||||
// Generate a sink node, which implicitly marks both outgoing branches as
|
||||
// infeasible.
|
||||
ExplodedNode *N = Builder.generateNode(PP, state,
|
||||
Pred, true);
|
||||
ExplodedNode *N = Ctx.generateSink();
|
||||
if (N) {
|
||||
if (!BT)
|
||||
BT.reset(
|
||||
|
@ -107,7 +98,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
|
|||
R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
|
||||
R->addRange(Ex->getSourceRange());
|
||||
|
||||
Eng.getBugReporter().EmitReport(R);
|
||||
Ctx.EmitReport(R);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,15 +320,39 @@ void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC,
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct CheckBranchConditionContext {
|
||||
typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
|
||||
const CheckersTy &Checkers;
|
||||
const Stmt *Condition;
|
||||
ExprEngine &Eng;
|
||||
|
||||
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
|
||||
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
|
||||
|
||||
CheckBranchConditionContext(const CheckersTy &checkers,
|
||||
const Stmt *Cond, ExprEngine &eng)
|
||||
: Checkers(checkers), Condition(Cond), Eng(eng) {}
|
||||
|
||||
void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
|
||||
NodeBuilder &Bldr, ExplodedNode *Pred) {
|
||||
ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
|
||||
checkFn.Checker);
|
||||
CheckerContext C(Bldr, Eng, Pred, L, 0);
|
||||
checkFn(Condition, C);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Run checkers for branch condition.
|
||||
void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
|
||||
NodeBuilder &B,
|
||||
void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
|
||||
ExplodedNodeSet &Dst,
|
||||
ExplodedNode *Pred,
|
||||
ExprEngine &Eng) {
|
||||
for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
|
||||
CheckBranchConditionFunc fn = BranchConditionCheckers[i];
|
||||
fn(condition, B, Pred, Eng);
|
||||
}
|
||||
ExplodedNodeSet Src;
|
||||
Src.insert(Pred);
|
||||
CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
|
||||
expandGraphWithCheckers(C, Dst, Src);
|
||||
}
|
||||
|
||||
/// \brief Run checkers for live symbols.
|
||||
|
|
|
@ -217,10 +217,13 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
|
|||
ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Pred);
|
||||
return;
|
||||
}
|
||||
currentStmtIdx = 0;
|
||||
currentBuilderContext = 0;
|
||||
}
|
||||
|
||||
const Stmt *ExprEngine::getStmt() const {
|
||||
const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx].getAs<CFGStmt>();
|
||||
const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx]
|
||||
.getAs<CFGStmt>();
|
||||
return CS ? CS->getStmt() : 0;
|
||||
}
|
||||
|
||||
|
@ -1033,6 +1036,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
ExplodedNodeSet &Dst,
|
||||
const CFGBlock *DstT,
|
||||
const CFGBlock *DstF) {
|
||||
currentBuilderContext = &BldCtx;
|
||||
|
||||
// Check for NULL conditions; e.g. "for(;;)"
|
||||
if (!Condition) {
|
||||
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
|
||||
|
@ -1045,17 +1050,16 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
Condition->getLocStart(),
|
||||
"Error evaluating branch");
|
||||
|
||||
ExplodedNodeSet TmpCheckersOut;
|
||||
NodeBuilder CheckerBldr(Pred, TmpCheckersOut, BldCtx);
|
||||
getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr,
|
||||
ExplodedNodeSet CheckersOutSet;
|
||||
getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,
|
||||
Pred, *this);
|
||||
// We generated only sinks.
|
||||
if (TmpCheckersOut.empty())
|
||||
if (CheckersOutSet.empty())
|
||||
return;
|
||||
|
||||
BranchNodeBuilder builder(CheckerBldr.getResults(), Dst, BldCtx, DstT, DstF);
|
||||
for (NodeBuilder::iterator I = CheckerBldr.begin(),
|
||||
E = CheckerBldr.end(); E != I; ++I) {
|
||||
BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
|
||||
for (NodeBuilder::iterator I = CheckersOutSet.begin(),
|
||||
E = CheckersOutSet.end(); E != I; ++I) {
|
||||
ExplodedNode *PredI = *I;
|
||||
|
||||
if (PredI->isSink())
|
||||
|
@ -1107,6 +1111,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
builder.markInfeasible(false);
|
||||
}
|
||||
}
|
||||
currentBuilderContext = 0;
|
||||
}
|
||||
|
||||
/// processIndirectGoto - Called by CoreEngine. Used to generate successor
|
||||
|
|
Loading…
Reference in New Issue