diff options
4 files changed, 67 insertions, 27 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index f31cdc986da..f304d82786e 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -222,18 +222,16 @@ public: 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()); } @@ -297,7 +295,31 @@ protected: }; -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: @@ -310,15 +332,14 @@ 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, @@ -395,7 +416,6 @@ public: void addNodes(ExplodedNode *N) { Frontier.Add(N); } - }; class BranchNodeBuilder: public NodeBuilder { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index f18b04b8b8a..a593fac99a5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -69,6 +69,8 @@ class ExprEngine : public SubEngine { /// currentStmt - The current block-level statement. const Stmt *currentStmt; + unsigned int currentStmtIdx; + const NodeBuilderContext *currentBuilderContext; /// Obj-C Class Identifiers. IdentifierInfo* NSExceptionII; @@ -343,6 +345,11 @@ public: 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); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index eaba5eedb5f..f141392cbd0 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -62,7 +62,8 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled) *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) { @@ -229,6 +230,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder, StateMgr.recycleUnusedStates(); currentStmt = S.getStmt(); + currentStmtIdx = builder.getIndex(); + currentBuilderContext = &builder.getContext(); + PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), currentStmt->getLocStart(), "Error evaluating statement"); @@ -432,7 +436,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, } void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, - ExplodedNodeSet &Dst) { + ExplodedNodeSet &Dst) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), S->getLocStart(), "Error evaluating statement"); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 68ccc59ac95..eeb6b44ef2b 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -530,9 +530,15 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, 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(); @@ -544,17 +550,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // 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: { @@ -567,17 +572,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // 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: @@ -598,10 +602,10 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 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: @@ -619,7 +623,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 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; } @@ -660,14 +664,19 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 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; @@ -729,7 +738,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // 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); |