NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx, bool F = true)
: C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
- assert(DstSet.empty());
+ // assert(DstSet.empty());
Frontier.Add(SrcNode);
}
NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
const NodeBuilderContext &Ctx, bool F = true)
: C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
- assert(DstSet.empty());
+ //assert(DstSet.empty());
//assert(!SrcSet.empty());
-
Frontier.insert(SrcSet);
-
assert(haveNoSinksInFrontier());
}
};
-class StmtNodeBuilder: public NodeBuilder {
+class PureStmtNodeBuilder: public NodeBuilder {
+public:
+ PureStmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx)
+ : NodeBuilder(SrcNode, DstSet, Ctx) {}
+
+ ExplodedNode *generateNode(const Stmt *S,
+ ExplodedNode *Pred,
+ const ProgramState *St,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ bool MarkAsSink = false,
+ const ProgramPointTag *tag = 0,
+ bool Purging = false) {
+ if (Purging) {
+ assert(K == ProgramPoint::PostStmtKind);
+ K = ProgramPoint::PostPurgeDeadSymbolsKind;
+ }
+
+ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+ Pred->getLocationContext(), tag);
+ return generateNodeImpl(L, St, Pred, MarkAsSink);
+ }
+};
+
+class StmtNodeBuilder : public NodeBuilder {
const unsigned Idx;
public:
void GenerateAutoTransition(ExplodedNode *N);
-public:
StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
unsigned idx, const NodeBuilderContext &Ctx)
: NodeBuilder(SrcNode, DstSet, Ctx), Idx(idx),
PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
PointKind(ProgramPoint::PostStmtKind), Tag(0) {}
- ~StmtNodeBuilder();
-
+ virtual ~StmtNodeBuilder();
+
ExplodedNode *generateNode(const Stmt *S,
const ProgramState *St,
ExplodedNode *Pred,
void addNodes(ExplodedNode *N) {
Frontier.Add(N);
}
-
};
class BranchNodeBuilder: public NodeBuilder {
/// currentStmt - The current block-level statement.
const Stmt *currentStmt;
+ unsigned int currentStmtIdx;
+ const NodeBuilderContext *currentBuilderContext;
/// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
+ /// Handle ++ and -- (both pre- and post-increment).
+ void VisitIncrementDecrementOperator(const UnaryOperator* U,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
*this),
SymMgr(StateMgr.getSymbolManager()),
svalBuilder(StateMgr.getSValBuilder()),
- EntryNode(NULL), currentStmt(NULL),
+ EntryNode(NULL),
+ currentStmt(NULL), currentStmtIdx(0), currentBuilderContext(0),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", getContext())),
ObjCGCEnabled(gcEnabled), BR(mgr, *this) {
StateMgr.recycleUnusedStates();
currentStmt = S.getStmt();
+ currentStmtIdx = builder.getIndex();
+ currentBuilderContext = &builder.getContext();
+
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
currentStmt->getLocStart(),
"Error evaluating statement");
}
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+ ExplodedNodeSet &Dst) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
S->getLocStart(),
"Error evaluating statement");
void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+ ExplodedNodeSet &Dst) {
+ Builder->takeNodes(Pred);
+ PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+ bool IncDec = false;
switch (U->getOpcode()) {
default:
+ Builder->addNodes(Pred);
+ IncDec = true;
+ VisitIncrementDecrementOperator(U, Pred, Dst);
break;
case UO_Real: {
const Expr *Ex = U->getSubExpr()->IgnoreParens();
// FIXME: We don't have complex SValues yet.
if (Ex->getType()->isAnyComplexType()) {
// Just report "Unknown."
- Dst.Add(*I);
continue;
}
// For all other types, UO_Real is an identity operation.
assert (U->getType() == Ex->getType());
const ProgramState *state = (*I)->getState();
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+ Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
}
- return;
+ break;
}
case UO_Imag: {
// FIXME: We don't have complex SValues yet.
if (Ex->getType()->isAnyComplexType()) {
// Just report "Unknown."
- Dst.Add(*I);
continue;
}
// For all other types, UO_Imag returns 0.
const ProgramState *state = (*I)->getState();
SVal X = svalBuilder.makeZeroVal(Ex->getType());
- MakeNode(Dst, U, *I, state->BindExpr(U, X));
+ Bldr.generateNode(U, *I, state->BindExpr(U, X));
}
- return;
+ break;
}
case UO_Plus:
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const ProgramState *state = (*I)->getState();
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+ Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
}
- return;
+ break;
}
case UO_LNot:
SVal V = state->getSVal(Ex);
if (V.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I, state->BindExpr(U, V));
+ Bldr.generateNode(U, *I, state->BindExpr(U, V));
continue;
}
break;
}
-
- MakeNode(Dst, U, *I, state);
+ Bldr.generateNode(U, *I, state);
}
-
- return;
+ break;
}
}
-
+
+ if (!IncDec)
+ Builder->addNodes(Dst);
+}
+
+void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
// Handle ++ and -- (both pre- and post-increment).
assert (U->isIncrementDecrementOp());
ExplodedNodeSet Tmp;
// It isn't feasible for the original value to be null.
// Propagate this constraint.
Constraint = svalBuilder.evalEQ(state, SymVal,
- svalBuilder.makeZeroVal(U->getType()));
+ svalBuilder.makeZeroVal(U->getType()));
state = state->assume(Constraint, false);