diff --git a/include/clang/Checker/PathSensitive/GRBlockCounter.h b/include/clang/Checker/PathSensitive/GRBlockCounter.h index 67ed9532db..b7d0e8ae0c 100644 --- a/include/clang/Checker/PathSensitive/GRBlockCounter.h +++ b/include/clang/Checker/PathSensitive/GRBlockCounter.h @@ -22,6 +22,8 @@ namespace llvm { namespace clang { +class StackFrameContext; + class GRBlockCounter { void* Data; @@ -30,7 +32,8 @@ class GRBlockCounter { public: GRBlockCounter() : Data(0) {} - unsigned getNumVisited(unsigned BlockID) const; + unsigned getNumVisited(const StackFrameContext *CallSite, + unsigned BlockID) const; class Factory { void* F; @@ -39,7 +42,9 @@ public: ~Factory(); GRBlockCounter GetEmptyCounter(); - GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID); + GRBlockCounter IncrementCount(GRBlockCounter BC, + const StackFrameContext *CallSite, + unsigned BlockID); }; friend class Factory; diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index c5bf5138a6..a3ff0dbedc 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -82,7 +82,7 @@ class GRCoreEngine { void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); - bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, + bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, GRBlockCounter BC); @@ -174,7 +174,9 @@ public: GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited(B.getBlockID()); + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); } ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { @@ -434,7 +436,9 @@ public: } unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited(B.getBlockID()); + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); } ExplodedNode* generateNode(const GRState* State, const void *tag = 0, diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 916511e8bd..dd8e71ed9b 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -153,7 +153,7 @@ public: /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, + bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC); /// ProcessBranch - Called by GRCoreEngine. Used to generate successor diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index f2cd0486e3..93f9e846ab 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -47,7 +47,7 @@ public: /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - virtual bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, + virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC) = 0; /// ProcessBranch - Called by GRCoreEngine. Used to generate successor diff --git a/lib/Checker/GRBlockCounter.cpp b/lib/Checker/GRBlockCounter.cpp index 3fa3e1ebb9..cd26060ef0 100644 --- a/lib/Checker/GRBlockCounter.cpp +++ b/lib/Checker/GRBlockCounter.cpp @@ -18,7 +18,34 @@ using namespace clang; -typedef llvm::ImmutableMap CountMap; +namespace { + +class CountKey { + const StackFrameContext *CallSite; + unsigned BlockID; + +public: + CountKey(const StackFrameContext *CS, unsigned ID) + : CallSite(CS), BlockID(ID) {} + + bool operator==(const CountKey &RHS) const { + return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID); + } + + bool operator<(const CountKey &RHS) const { + return (CallSite == RHS.CallSite) ? (BlockID < RHS.BlockID) + : (CallSite < RHS.CallSite); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(CallSite); + ID.AddInteger(BlockID); + } +}; + +} + +typedef llvm::ImmutableMap CountMap; static inline CountMap GetMap(void* D) { return CountMap(static_cast(D)); @@ -28,9 +55,10 @@ static inline CountMap::Factory& GetFactory(void* F) { return *static_cast(F); } -unsigned GRBlockCounter::getNumVisited(unsigned BlockID) const { +unsigned GRBlockCounter::getNumVisited(const StackFrameContext *CallSite, + unsigned BlockID) const { CountMap M = GetMap(Data); - CountMap::data_type* T = M.lookup(BlockID); + CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID)); return T ? *T : 0; } @@ -43,9 +71,12 @@ GRBlockCounter::Factory::~Factory() { } GRBlockCounter -GRBlockCounter::Factory::IncrementCount(GRBlockCounter BC, unsigned BlockID) { - return GRBlockCounter(GetFactory(F).Add(GetMap(BC.Data), BlockID, - BC.getNumVisited(BlockID)+1).getRoot()); +GRBlockCounter::Factory::IncrementCount(GRBlockCounter BC, + const StackFrameContext *CallSite, + unsigned BlockID) { + return GRBlockCounter(GetFactory(F).Add(GetMap(BC.Data), + CountKey(CallSite, BlockID), + BC.getNumVisited(CallSite, BlockID)+1).getRoot()); } GRBlockCounter diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp index a9347d0164..e4ef6b0e10 100644 --- a/lib/Checker/GRCoreEngine.cpp +++ b/lib/Checker/GRCoreEngine.cpp @@ -126,9 +126,9 @@ void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) { SubEngine.ProcessStmt(E, Builder); } -bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, +bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, GRBlockCounter BC) { - return SubEngine.ProcessBlockEntrance(Blk, State, BC); + return SubEngine.ProcessBlockEntrance(Blk, Pred, BC); } void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator, @@ -256,7 +256,7 @@ void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) { // FIXME: Should we allow ProcessBlockEntrance to also manipulate state? - if (ProcessBlockEntrance(Blk, Pred->State, WList->getBlockCounter())) + if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter())) GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()), Pred->State, Pred); } @@ -265,7 +265,9 @@ void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L, // Increment the block counter. GRBlockCounter Counter = WList->getBlockCounter(); - Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID()); + Counter = BCounterFactory.IncrementCount(Counter, + Pred->getLocationContext()->getCurrentStackFrame(), + L.getBlock()->getBlockID()); WList->setBlockCounter(Counter); // Process the entrance of the block. diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 3ace552adc..0604f8a4e5 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -944,10 +944,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, // Block entrance. (Update counters). //===----------------------------------------------------------------------===// -bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const GRState*, +bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC) { - return BC.getNumVisited(B->getBlockID()) < 3; + return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(), + B->getBlockID()) < 3; } //===----------------------------------------------------------------------===//