class BranchCondition {
template <typename CHECKER>
static void _checkBranchCondition(void *checker, const Stmt *condition,
- BranchNodeBuilder &B, ExprEngine &Eng) {
+ NodeBuilder &B, ExprEngine &Eng) {
((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
}
class ExplodedGraph;
class ProgramState;
class EndOfFunctionNodeBuilder;
- class BranchNodeBuilder;
+ class NodeBuilder;
class MemRegion;
class SymbolReaper;
/// \brief Run checkers for branch condition.
void runCheckersForBranchCondition(const Stmt *condition,
- BranchNodeBuilder &B, ExprEngine &Eng);
+ NodeBuilder &B, ExprEngine &Eng);
/// \brief Run checkers for live symbols.
///
typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)>
CheckEndPathFunc;
- typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)>
+ typedef CheckerFn<void (const Stmt *, NodeBuilder &, ExprEngine &)>
CheckBranchConditionFunc;
typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
ST(st),
size(Dst.size()),
Ctx(builder.Eng, builder.getBlock()),
- NB(Ctx, pred),
+ NB(pred, Ctx),
respondsToCallback(respondsToCB) {
assert(!(ST && ST != Pred->getState()));
}
friend class StmtNodeBuilder;
ExplodedNode *BuilderPred;
- NodeBuilderContext &C;
+ const NodeBuilderContext &C;
bool Finalized;
/// \brief The frontier set - a set of nodes which need to be propagated after
bool MarkAsSink = false);
public:
- NodeBuilder(NodeBuilderContext &Ctx, ExplodedNode *N)
+ NodeBuilder(ExplodedNode *N, NodeBuilderContext &Ctx)
: BuilderPred(N), C(Ctx), Finalized(false) {
assert(!N->isSink());
Deferred.insert(N);
}
+ /// Create a new builder using the parent builder's context.
+ NodeBuilder(ExplodedNode *N, const NodeBuilder &ParentBldr)
+ : BuilderPred(N), C(ParentBldr.C), Finalized(false) {
+ assert(!N->isSink());
+ Deferred.insert(N);
+ }
+
virtual ~NodeBuilder() {}
/// \brief Generates a node in the ExplodedGraph.
C.Block->getBlockID());
}
+ // \brief Get the builder's predecessor - the parent to all the other nodes.
ExplodedNode *getPredecessor() const { return BuilderPred; }
+
+ // \brief Returns state of the predecessor.
+ const ProgramState *getState() const { return BuilderPred->getState(); }
};
class CommonNodeBuilder {
}
public:
- BranchNodeBuilder(NodeBuilderContext &C, ExplodedNode *Pred,
+ BranchNodeBuilder(ExplodedNode *Pred, NodeBuilderContext &C,
const CFGBlock *dstT, const CFGBlock *dstF)
- : NodeBuilder(C, Pred), DstT(dstT), DstF(dstF),
+ : NodeBuilder(Pred, C), DstT(dstT), DstF(dstF),
GeneratedTrue(false), GeneratedFalse(false),
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
}
- /// This function generate a new ExplodedNode but not a new
- /// branch(block edge). Creates a transition from the Builder's top
- /// predecessor.
- ExplodedNode *generateNode(const Stmt *Condition, const ProgramState *State,
- const ProgramPointTag *Tag = 0,
- bool MarkAsSink = false);
+ /// Create a new builder using the parent builder's context.
+ BranchNodeBuilder(ExplodedNode *Pred, BranchNodeBuilder &ParentBldr)
+ : NodeBuilder(Pred, ParentBldr), DstT(ParentBldr.DstT), DstF(ParentBldr.DstF),
+ GeneratedTrue(false), GeneratedFalse(false),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+ }
ExplodedNode *generateNode(const ProgramState *State, bool branch,
ExplodedNode *Pred = 0);
bool isFeasible(bool branch) {
return branch ? !InFeasibleTrue : !InFeasibleFalse;
}
-
- const ProgramState *getState() const {
- return getPredecessor()->getState();
- }
};
class IndirectGotoNodeBuilder {
};
public:
- void checkBranchCondition(const Stmt *Condition, BranchNodeBuilder &Builder,
+ void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder,
ExprEngine &Eng) const;
};
}
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
- BranchNodeBuilder &Builder,
+ NodeBuilder &Builder,
ExprEngine &Eng) const {
const ProgramState *state = Builder.getState();
SVal X = state->getSVal(Condition);
if (X.isUndef()) {
- // Generate a sink node.
- ExplodedNode *N = Builder.generateNode(Condition, state, 0, true);
+ // 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,
+ Builder.getPredecessor()->getLocationContext(), Tag);
+ // Generate a sink node, which implicitly marks both outgoing branches as
+ // infeasible.
+ ExplodedNode *N = Builder.generateNode(PP, state,
+ Builder.getPredecessor(), true);
if (N) {
if (!BT)
BT.reset(
Eng.getBugReporter().EmitReport(R);
}
-
- Builder.markInfeasible(true);
- Builder.markInfeasible(false);
}
}
/// \brief Run checkers for branch condition.
void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
- BranchNodeBuilder &B,
+ NodeBuilder &B,
ExprEngine &Eng) {
for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
CheckBranchConditionFunc fn = BranchConditionCheckers[i];
return NULL;
}
-// This function generate a new ExplodedNode but not a new branch(block edge).
-// Creates a transition from the Builder's top predecessor.
-ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
- const ProgramState *State,
- const ProgramPointTag *Tag,
- bool MarkAsSink) {
- ProgramPoint PP = PostCondition(Condition,
- BuilderPred->getLocationContext(), Tag);
- ExplodedNode *N = generateNodeImpl(PP, State, BuilderPred, MarkAsSink);
- assert(N);
- // TODO: This needs to go - we should not change Pred!!!
- BuilderPred = N;
- return N;
-}
-
ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
bool branch,
ExplodedNode *NodePred) {
const CFGBlock *DstT,
const CFGBlock *DstF) {
- BranchNodeBuilder builder(BldCtx, Pred, DstT, DstF);
-
// Check for NULL conditions; e.g. "for(;;)"
if (!Condition) {
- BranchNodeBuilder NullCondBldr(BldCtx, Pred, DstT, DstF);
+ BranchNodeBuilder NullCondBldr(Pred, BldCtx, DstT, DstF);
NullCondBldr.markInfeasible(false);
Engine.enqueue(NullCondBldr);
return;
Condition->getLocStart(),
"Error evaluating branch");
- //TODO: This should take the NodeBuiolder.
- getCheckerManager().runCheckersForBranchCondition(Condition, builder,
+ NodeBuilder CheckerBldr(Pred, BldCtx);
+ getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr,
*this);
- const ProgramState *PrevState = builder.getState();
- SVal X = PrevState->getSVal(Condition);
-
- if (X.isUnknownOrUndef()) {
- // Give it a chance to recover from unknown.
- if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
- if (Ex->getType()->isIntegerType()) {
- // Try to recover some path-sensitivity. Right now casts of symbolic
- // integers that promote their values are currently not tracked well.
- // If 'Condition' is such an expression, try and recover the
- // underlying value and use that instead.
- SVal recovered = RecoverCastedSymbol(getStateManager(),
- builder.getState(), Condition,
- getContext());
-
- if (!recovered.isUnknown()) {
- X = recovered;
+ for (NodeBuilder::iterator I = CheckerBldr.results_begin(),
+ E = CheckerBldr.results_end(); E != I; ++I) {
+ ExplodedNode *PredI = *I;
+
+ if (PredI->isSink())
+ continue;
+
+ BranchNodeBuilder builder(PredI, BldCtx, DstT, DstF);
+ const ProgramState *PrevState = builder.getState();
+ SVal X = PrevState->getSVal(Condition);
+
+ if (X.isUnknownOrUndef()) {
+ // Give it a chance to recover from unknown.
+ if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+ if (Ex->getType()->isIntegerType()) {
+ // Try to recover some path-sensitivity. Right now casts of symbolic
+ // integers that promote their values are currently not tracked well.
+ // If 'Condition' is such an expression, try and recover the
+ // underlying value and use that instead.
+ SVal recovered = RecoverCastedSymbol(getStateManager(),
+ PrevState, Condition,
+ getContext());
+
+ if (!recovered.isUnknown()) {
+ X = recovered;
+ }
}
}
}
builder.generateNode(MarkBranch(PrevState, Term, false), false);
// Enqueue the results into the work list.
Engine.enqueue(builder);
- return;
+ continue;
}
- }
- DefinedSVal V = cast<DefinedSVal>(X);
+ DefinedSVal V = cast<DefinedSVal>(X);
- // Process the true branch.
- if (builder.isFeasible(true)) {
- if (const ProgramState *state = PrevState->assume(V, true))
- builder.generateNode(MarkBranch(state, Term, true), true);
- else
- builder.markInfeasible(true);
- }
+ // Process the true branch.
+ if (builder.isFeasible(true)) {
+ if (const ProgramState *state = PrevState->assume(V, true))
+ builder.generateNode(MarkBranch(state, Term, true), true);
+ else
+ builder.markInfeasible(true);
+ }
- // Process the false branch.
- if (builder.isFeasible(false)) {
- if (const ProgramState *state = PrevState->assume(V, false))
- builder.generateNode(MarkBranch(state, Term, false), false);
- else
- builder.markInfeasible(false);
- }
+ // Process the false branch.
+ if (builder.isFeasible(false)) {
+ if (const ProgramState *state = PrevState->assume(V, false))
+ builder.generateNode(MarkBranch(state, Term, false), false);
+ else
+ builder.markInfeasible(false);
+ }
- // Enqueue the results into the work list.
- Engine.enqueue(builder);
+ // Enqueue the results into the work list.
+ Engine.enqueue(builder);
+ }
}
/// processIndirectGoto - Called by CoreEngine. Used to generate successor