[analyzer] Make branch for condition callback use CheckerContext

Now, all the path sensitive checkers use CheckerContext!

llvm-svn: 142944
This commit is contained in:
Anna Zaks 2011-10-25 19:56:54 +00:00
parent 3eae33412d
commit f380534a1a
5 changed files with 53 additions and 35 deletions

View File

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

View File

@ -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 &)>

View File

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

View File

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

View File

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