diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/CoreEngine.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 67b7d30853d9..775a22e18c61 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -444,7 +444,8 @@ void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term, NodeBuilderContext Ctx(*this, B, Pred); ExplodedNodeSet Dst; ExprEng.processBranch(Cond, Ctx, Pred, Dst, *(B->succ_begin()), - *(B->succ_begin() + 1)); + *(B->succ_begin() + 1), + getCompletedIterationCount(B, Pred)); // Enqueue the new frontier onto the worklist. enqueue(Dst); } @@ -591,6 +592,30 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N, return isNew ? Node : nullptr; } +std::optional<unsigned> +CoreEngine::getCompletedIterationCount(const CFGBlock *B, + ExplodedNode *Pred) const { + const LocationContext *LC = Pred->getLocationContext(); + BlockCounter Counter = WList->getBlockCounter(); + unsigned BlockCount = + Counter.getNumVisited(LC->getStackFrame(), B->getBlockID()); + + const Stmt *Term = B->getTerminatorStmt(); + if (isa<ForStmt, WhileStmt, CXXForRangeStmt>(Term)) { + assert(BlockCount >= 1 && + "Block count of currently analyzed block must be >= 1"); + return BlockCount - 1; + } + if (isa<DoStmt>(Term)) { + // In a do-while loop one iteration happens before the first evaluation of + // the loop condition, so we don't subtract one. + return BlockCount; + } + // ObjCForCollectionStmt is skipped intentionally because the current + // application of the iteration counts is not relevant for it. + return std::nullopt; +} + void CoreEngine::enqueue(ExplodedNodeSet &Set) { for (const auto I : Set) WList->enqueue(I); |
